微信小程序知识点汇总

689 阅读10分钟

1. 初衷

近期公司要做一个微信小程序, 难度不大。不过里边的知识点还是比较琐碎的,我打算把一些常用的api和常用组件以及开发一个项目所需要的一些步骤都整体等等都罗列在下面, 以后再想做一个微信小程序的时候就可以快速完成。

2. 一些高频api汇总

一些常用的api知道是干嘛的,不过单词拼写总是记得不是很牢靠, 或者比较多,不想敲。 直接来这里找答案好了

// 设置顶部部title(json)
navigationBarTitleText: "顶部的标题", // json中设置
wx.setNavigationBarTitle({
  title: 'js动态更改顶部表体' // js中设置
})
// 使用组件(json)
usingComponents: {
    select: "/components/select/select",
    van-field: "/miniprogram_npm/vant-weapp/field/index",
}
// 使用阿里icon(wxml)
<view class="icon-company iconfont"></view>
// 跳转页面(js)  navigateTo redirectTo navigateBack switchTab
wx.navigateTo({
  url: '/pages/personManage/addPerson',
})
// 获取data-*="{{item}}"传递的数据数据
e.currentTarget.dataset.*
// 动态修改小程序顶部title内容
wx.setNavigationBarTitle({
  title: "title名称"
})

3. 使用阿里图标库来作小程序icon图标

  1. 官网地址:    www.iconfont.cn/
  2. 使用步骤: 登录官网, 将图标放进购物车, 点击购物车里的添加至项目。 给项目起个名字, 在项目中可以对图标进行一些具体的操作。 最后点击下载至本地。 这是下载至本地后的文件夹打开后的样子

只操作iconfont.css即可。 将iconfont.css改成微信小程序可识别的 iconfont.wxss, 放入本项目中, 我放在了image文件夹下。 然后在全局app.wxss中引入 @import '/image/iconfont.wxss'。 可以在iconfont.wxss中进行一些icon图标颜色, 背景色等的设置。举例

.iconfont {
  font-family: "iconfont" !important;
  font-size: var(--sm-txt);  // 这是全局small号的字体
  font-style: normal;
  color: var(--color-default); // 这是全局默认颜色
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

在小程序页面中使用icon, 要引入两个class, 基础class iconfont 和图标class icon-***

<view class="icon-company iconfont" style="margin-right: 10rpx;"></view>
  1. 步骤总结

从阿里图标库官网下载图标至本地。 将文件夹中的iconfont.css改为iconfont.wxss并移动至小程序项目中。 在app.wxss中导入iconfont.wxss。 然后就可以在页面中使用icon图标了。

  1. 改变iconfont图标背景色 方法1. 直接在iconfont.wxss中全局改变css样式color (推荐) 方法2. 直接在阿里图标库官网中进行修改样式(颜色,大小, 格式, class名字等), 然后下载到本地使用。
  2. 批量添加阿里图标iconfont
  • 打开阿里官网中你要添加的阿里图标。 打开控制台输入以下代码, 其实就是触发点击事件, 可以一次性的选择当前页面的所有图标。 执行完以下代码就把本页所有icon全加入到项目中了
var span = document.querySelectorAll('.icon-cover');
for (var i = 0, len = span.length; i < len; i++) {
     console.log(span[i].querySelector('span').click());
}

4. 去掉控制台搜索引擎警告

-url:WAService.js
  • 在project.config.json中更改checkSiteMapfalse
// project.config.json
'checkSiteMap': false

5. console调试工具隐藏WAService.js输出的无用日志

// 在控制台中输入下面的代码过滤掉 WAService.js
-url:WAService.js

开发微信小程序,调试控制台总是显示着一堆的日志,大多是WAService.js输入的页面初始化日志,影响自己日志的显示。

可以通过控制台设置参数来过滤掉无用的日志

先来一个问题截图看看原来是啥样

解决方案: 我们通过输入文本过滤掉WAService.js文件,代码如下

-url:WAService.js

输入后的控制台截图如下

6. 公共请求方法封装

微信小程序请求后台接口, 有一套小程序自己的请求api。 wx.request。 不过为了统一处理返回的数据并复用代码,还是需要去重新封装下接口请求。以下为我总结的微信小程序封装后台请求的代码

//  将公共方法http.js写在utils文件夹下
const app = getApp();
const http = (url, data = {}, params) => {
  return new Promise((resolve, reject) => {
    // 如果不设置showLoading为true,则默认显示loading动画
    if (params.showLoading) {
      wx.showLoading({
        title: '加载中...',
        duration: 10000,
        mask: true,
      })
    }
    wx.request({
      url: app.globalData.host + url, // 在app.js中定义全局baseUrl, 拼接上要请求的接口路径
      data: data, 
      method: (params.method || "POST").toUpperCase(), // 请求方法, 不传默认是get,并转为大写
      header: params.header || {
        'content-type': 'application/json',
        'token': app.globalData.gOpenid, // 将wx.login返回的openid存在全局里作为token
      }, // 请求头
      success(res) {
        // 只处理请求状态码为200的结果, 其余的结果都reject。
        if (res.statusCode === 200 && res.data.code !== 1) {
          wx.hideLoading();
          resolve(res.data);
        } else if (res.statusCode === 200 && res.data.code === 1) {
          wx.hideLoading() // 关闭加载中的请求动画
          wx.showToast({
            icon: 'none',
            title: res.data.msg,
            duration: 10000,
          })
          reject(res.data)
        } else {
          wx.hideLoading() // 关闭加载中的请求动画
          wx.showToast({
            icon: 'none',
            title: '接口报错',
            duration: 10000,
          })
          reject(res.data)
        }
      },
      fail(err) {
        wx.hideLoading() // 关闭加载中的请求动画
        wx.showToast({
          icon: 'none',
          title: err.errMsg,
          duration: 10000,
        })
        reject(err)
      },
    })
  })
}

module.exports = {
  http
}

// 在index.js中请求后台接口
import { http } from '../../utils/request' 

7. wxml中使用wxs语法

WXS 代码可以编写在 wxml 文件中的 标签内,或以 .wxs 为后缀名的文件内。 由于微信小程序不像vue一样使用双向数据绑定, wxml中无法引用js中的函数和全局函数,所以就需要wxs文件来处理wxml中需要js操作的代码

注意事项

    1. wxs不能使用es6语法(注意,如果有使用报错,一定要先检查是否写了es6语法)
    1. wxs引入只能使用相对路径
    1. 正则不能使用/ /new Regexp()。 必须使用getRegExp

1.单独创建wxs文件

// utils文件夹下新建filters.wxs

// 将后台返回的字符串中的<br>转换成wxml可以识别的换行符'\n'
function translateBr(str) {
    var regExp = getRegExp('<br>', 'g')
    var res = str.replace(regExp, "\n");
    return res
}
  
module.exports = {   
  translateBr: translateBr,  // 这块不能简写,因为简写就成了es6语法会报错
}
// 在wxss文件中使用
// 引入wxs
<wxs module="filters" src="../../utils/filters.wxs"></wxs>
// 使用wxs
<view>{{filters.toFix('43231.3162321')}}</view>

2. 在wxml页面中创建wxs文件

<wxs module="isSimple">
  function isSimple(columns) {
    return columns.length && !columns[0].values;
  }
  module.exports = isSimple;
</wxs>

8 获取手机设备信息

wx.getSystemInfo({
    success:function(res){
        that.setData({
            scrollHeight:res.windowHeight
        });
    }
});

9. 使用函数节流

概念:  规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。
场景: 在使用小程序的时候会出现这样一种情况:当网络条件差或卡顿的情况下,使用者会认为点击无效而进行多次点击,最后出现多次跳转页面的情况或者同一函数多次执行
解决办法 :  使用函数节流(throttle):函数在一段时间内多次触发只会执行第一次,在这段时间结束前,不管触发多少次也不会执行函数。
用处:  

  • 多用于页面scroll滚动
  • 或者窗口resize
  • 或者防止按钮重复点击等情况,
  • DOM 元素的拖拽功能实现(mousemove)
  • 计算鼠标移动的距离(mousemove)
  • Canvas 模拟画板功能(mousemove)
  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
  • 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce(函数防抖) 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次
// utils/util.js
const throttle = (fn, gapTime = 1000) => { // 默认间隔时间为1000毫秒, 可修改
  let _lastTime = null;
  return function () {
    let _nowTime = +new Date()
    if (_nowTime - _lastTime > gapTime || !_lastTime) {
      fn.apply(this, arguments) //将this和参数传给原函数
      _lastTime = _nowTime 
    }
  }
}

module.exports = {
  throttle
}

// pages/throttle/throttle.wxml
<button bindtap="btnThrottle" type="primary">这是被throttle的按钮</button>

// pages/throttle/throttle.js
import util from '../../utils/util'
Page({
  // 带throttle的按钮点击事件, throttle函数的第二个参数可以不写(默认1000)
  btnThrottle: util.throttle(function (e) {
    console.log(e)
    console.log(this)
  },2000), 
})

10. 页面跳转

跳转分为2种方式 wxml页面内部跳转和js跳转,两种方法都支持绝对和相对路径跳转。 若要传值,将值通过? &的方式拼接在url的结尾处。在其他页面接收传递过来的值,只需要在onload中操作options参数即可 返回上一级或上N级页面使用wx.navigateBack, 参数为delta,数字类型。代表返回的页面数,如果delta大于现有页面数, 则返回到首页

注意: switchTab这种导航方式, 不能带参传递

// wxml内跳转
<navigator url="/pages/c/c?user_id=123">跳转到新页面</navigator>  // 默认open-type为navigate
<navigator url="../c/c" open-type="redirect" class="mb">在当前页打开</navigator>
// open-type的常用5个值
// navigate, redirect, switchTab, relaunch, navigateBack。 对应js跳转的响应功能

// 在c页面获取传递过来的值
onLoad: function (options) {
    console.log(options.user_id)  // 123
},

// js跳转
wx.navigateTo({
  url: '/pages/index/index',
  success:function(res){}  # success, fail, complete回调一般不用写
});
// 以上方法共5种跳转方式 ,分别是navigateTo, redirectTo,  switchTab,  reLaunch 
// wx.navigateTo: 保留当前页面,跳转到应用内某个页面
// wx.redirectTo: 关闭当前页面, 跳转到应用内某个页面
// wx.swtichTab: 只能跳转到tabBar配置页面
// wx.relaunch: 关闭所有页面, 打开到应用内某个页面
// wx.navigateBack: 返回上级页面

// 返回上一级, 默认delta为1 
wx.navigateBack()  
// 返回上两级
wx.navigateBack({
    delta: 2
})

11. input框的双向数据绑定

微信小程序和三大前端框架的语法有些不一样, 不是双向数据绑定。 所以需要自己去进行绑定。 在input输入框中(这里用的Vant Weapp中的van-field)。通过data-prop="需要双向绑定的值"的方式, 用bindinput给这个自定义数据赋值,来达到双向绑定的效果。

// wxml
 <van-field value="{{ myTest }}" data-prop="myTest" bindinput="changeModel" label="备注"  clearable placeholder="请输入备注">
 
// js  注意:如果是原生的input, 赋值需要改成 e.detail.value
changeModel(e) {
    let data = {};
    data[e.currentTarget.dataset.prop] = e.detail;
    this.setData(data);
}

12. 预览图片

注意: 图片不能使用本地图片

// wxml  通过data-src传递图片数据
<swiper indicator-dots="true" autoplay="true" interval="{{interval}}" duration="{{duration}}" circular="true">
  <block wx:for="{{imgUrls}}" wx:key="*this">
    <swiper-item>
      <image src="{{item}}" bindtap="previewImg" data-src="{{item}}" class="slide-image" width="100%" />
    </swiper-item>
  </block>
</swiper>
// js 
data: {
    imgUrls: [
      'http://tmp/wxbedd25e64caedbb9.o6zAJs7URvWOa3AX_TZWnM1qVnbM.zPzOncOAlt0Of3471b5a06ab4fbdaac852e522cffdce.jpg'
    ],
    indicatorDots: false,
    autoplay: false,
    interval: 3000,
    duration: 800,
},
previewImg(e) {
  let imgUrl = e.currentTarget.dataset.src;
  wx.previewImage({
    // 所有图片的URL列表,数组格式
    current: imgUrl,
    urls: this.data.imgUrls,
    success: function (res) {

    }
  })
}

13. 父子组件通信

1. 父组件调用子组件的方法

子组件中: 定义方法 restFilterDatas

父组件中: 使用selectComponent来调用子组件的方法

// wxml
<fa-cmp id='fa' ></fa-cmp>
// js
this.selectComponent('#fa').childFunc();

14. 根据返回数据,生成多个echarts柱状图表

微信本身不支持echarts, 要想使用echarts图表, 需要使用微信小程序二次开发的组件。 在github上github.com/ecomfe/echa… 下载这个项目, 拷贝 ec-canvas 目录到自己项目的组件components下,然后做相应的调整。

1.最基础使用.

在app.json中创建test文件。 "pages/test/test"

// test.json
{
  "usingComponents": {
   	"ec-canvas": "/components/ec-canvas/ec-canvas"
  }
}
   
// test.wxml
<view class="container">
  <ec-canvas  style="width:100%;height:600rpx" id="mychart-dom-bar" canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>
</view>
   
// test.js
import * as echarts from '../../components/ec-canvas/echarts'
function initChart(canvas, width, height, dpr) {
  const chart = echarts.init(canvas, null, {
    width: width,
    height: height,
    devicePixelRatio: dpr // 像素
  });
  canvas.setChart(chart);

  var option = {
     title: {
                text: 'ECharts 入门示例'
            },
            tooltip: {},
            legend: {
                data:['销量']
            },
            xAxis: {
                data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
            },
            yAxis: {},
            series: [{
                name: '销量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20]
            }]
  };
  chart.setOption(option);
  return chart;
}

Page({
  data: {
    ec: {
      onInit: initChart
    }
  }
});

2. 根据后端返回的数据动态生成多个图表

说下思路。 initChart是生成图表的方法。 这个方法是在echarts.js中引入的。 而ec-canvas.js中则实际操作了这个方法。通过查看ec-canvas.js中的源码, 发现initByNewWay这个函数里处理这个回调。 我们只需要在这个方法里, 把图标绘制需要的参数传递进来就能在test.js中使用这个参数来进行页面的绘制。

// test.html
<view wx:for="{{itemList}}"  wx:for-item="item" wx:key="*this">
   <view class="list-item">
      <ec-canvas id="mychart-dom-bar" canvas-id="mychart-bar" chartData="{{item}}" ec="{{ ec }}"></ec-canvas>
   </view>
</view>
   
// test.js
import * as echarts from '../../components/ec-canvas/echarts';

function initChart(canvas, width, height, drp, data) { //这里多加一个参数
  const chart = echarts.init(canvas, null, {
    width: width,
    height: height,
    devicePixelRatio: drp
  })
  canvas.setChart(chart);
  let options = {
    title: {
      text: data.project,
      padding: [0, 5],
      itemGap: 0,
      top: 2,
      textStyle: {
        fontSize: 14,
        height: 6,
      }
    },
    tooltip: {},
    legend: {
      data: ['业绩'],
      show: false,
    },
    xAxis: {
      data: data.xDatas,
      type: 'category',
      axisLabel: {
        interval: 0, //横轴信息全部显示  
        // rotate: -15, //-15度角倾斜显示  
      },
    },
    yAxis: {},
    series: [{
      name: '业绩',
      type: 'bar',
      data: data.sDatas,
      barCategoryGap: '40%',
      barWidth: 14,
      roundCap: true,
      itemStyle: {
        color: 'blue',
      },
      label: {
        show: true,
        position: 'top'
      },
    }]
  }
  chart.setOption(options);
  return chart;
}
Page({
  /**
   * 页面的初始数据
   */
  data: {
    ec: {
      onInit: initChart
    },
    itemList: [],
    dataParams: {
      "project": "",
      "agent": "BFPID000000M970007",
      "supplier": "BFPID000000M970000",
      "startDate": "",
      "endDate": ""
    },
  },
  onLoad() {
    this.setData({
      itemList: [{
        project: 'andy凌云',
        xDatas: ["报备", "带看", "小订", "认购", "签约", "已过期"],
        sDatas: [5, 20, 36, 10, 10, 20]
      }, {
        project: 'andy凌云2',
        xDatas: ["报备", "带看", "小订", "认购", "签约", "已过期"],
        sDatas: [5, 20, 36, 10, 10, 20]
      }, {
        project: 'andy凌云3',
        xDatas: ["报备", "带看", "小订", "认购", "签约", "已过期"],
        sDatas: [5, 20, 36, 10, 10, 200]
      }, {
        project: 'andy凌云4',
        xDatas: ["报备", "带看", "小订", "认购", "签约", "已过期"],
        sDatas: [5, 20, 36, 10, 10, 200]
      }],
    })
  },
})
   
// 修改ec.canvas.js, 将传进来的值通过回调返回回去

// 在properties中新增参数
   chartData:{
   	type: Object
   }
// 更改initByNewWay函数, 将属性值加进来
    initByNewWay(callback) {
      // version >= 2.9.0:使用新的方式初始化
      const query = wx.createSelectorQuery().in(this)
      query
        .select('.ec-canvas')
        .fields({
          node: true,
          size: true
        })
        .exec(res => {
          const canvasNode = res[0].node
          this.canvasNode = canvasNode
          const canvasDpr = wx.getSystemInfoSync().pixelRatio
          const canvasWidth = res[0].width
          const canvasHeight = res[0].height
          const ctx = canvasNode.getContext('2d')
          const canvas = new WxCanvas(ctx, this.data.canvasId, true, canvasNode)
          echarts.setCanvasCreator(() => {
            return canvas
          })
          if (typeof callback === 'function') {
            this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)
          } else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
            this.chart = this.data.ec.onInit(canvas, canvasWidth, canvasHeight, canvasDpr, this.data.chartData)  // 这一行是新加的属性值
          } else {
            this.triggerEvent('init', {
              canvas: canvas,
              width: canvasWidth,
              height: canvasHeight,
              dpr: canvasDpr,
              data: this.data.chartData
            })
          }
        })
    },
   

上面的itemList数据是写死的。 如果是需要后端接口返回的数据, 只需要把后端接口返回的数据, 转换成类似格式并赋值给itemList变量即可显示echarts图表。

效果图

15. 动态设置顶部背景色navigationBarBackgroundColor的值

wx.setNavigationBarColor(OBJECT) // api
wx.setNavigationBarColor({
    frontColor: '#ffffff', // 必写项
    backgroundColor: '#1BC3B8', // 必写项
    animation: { // 可选项
        duration: 400,
        timingFunc: 'easeIn'
    }
})

16. image相关

  • 小程序image宽度固定,高度自适应 <image mode="widthFix" src='{{store.logo}}'></image>