编程崽

登录

一叶在编程苦海沉沦的扁舟之上,我是那只激情自射的崽

微信小程序开发

微信小程序开发

官方文档-页面

注册

进入 微信公众平台 进行注册。

注册页面

选择小程序:

eff4a9eadfe7fcba51cbe0cc6b9016b0.png

填写正确的注册信息

注意这里的邮箱,必须是之前没有和微信有过联系的邮箱:

Snipaste_2021-02-05_10-28-18.png

登记页面填写和上传审核资质

邮箱激活就是打开邮箱点击新连接,跳转至信息登记页面

注意这里的主体类型,选择不同的类型,需要填写和上传不同的资质。

注意:如果主体类型选择的是企业,则后面的步骤需要使用企业银行账户向腾讯指定账号打款,以此进行企业验证,打的款后面验证步骤完成后会退回,而在后面一些小程序资质认证相关步骤,主体类型为企业的,仍需要支付300元,来使用第三方服务来辅助,必须的步骤了。

Snipaste_2021-02-05_10-31-26.png

登录后开发前准备

开发前端时,我们使用浏览器来预览项目,开发小程序,同样需要一个用来预览的工具,这个工具能模拟微信的小程序环境。

它不仅是个小程序浏览器,也可以进行开发编辑等等,但可能用的少,使用不习惯,所以可以使用其他代码编辑器开发,使用开发者工具来预览和调试,真的把它当成一个「浏览器」来使用。

下载微信官方的 微信开发者工具

开发者工具下载完成,打开后使用微信扫一扫登录后,界面如下:

可以选择用来开发或引入不同类型的项目。

Snipaste_2021-02-05_10-52-36.png

点击导入或新建小程序,导入小程序会让你选择一个目录,新建小程序的界面如下:

  • 名称和目录可以自己修改
  • AppID 可以使用测试号开发,后期可以随时修改的,或者去 小程序管理页面 中的 开发 -> 开发管理 -> 开发设置 得到。

Snipaste_2021-02-05_11-06-03.png

最后点击新建,会自动创建目录,生成一个无实际内容的项目结构。

整体说明

小程序的语法,和 vue 是极度类似的。

每个页面,有 wxml、wxss、js 和 json 四个文件,json 作为页面的配置文件,暂时忽略。

wxml 就是起着 html 的作用,内部结构类似于 vue 的 template 中的内容,内部标签做过封装的 html。

wxss 的样式上,默认情况,只有全局的 app.wxss 内样式会全局生效,单个页面或组件的样式文件,只影响本身的样式,不会影响全局、子组件、其他组件等,但如果有需要求,需要样式穿透,需要修改该页面或组件的 js 中的 options.styleIsolation 字段,详见 组件样式隔离

文件结构整体说明

  • /pages/:页面文件们
    • index/:一个页面,里面的文件名和此文件夹名一致,只是格式不同
      • index.js:js 文件,此页面的逻辑开发文件
      • index.json:json 文件,配置文件,可在此页面,覆盖配置全局 /app.json 文件中的某些配置
      • index.wxml:wxml 文件,页面结构,类似于 html 文件
      • index.wxss:wxss 文件,页面中的样式,类似于 css 文件
    • logs/:另一个页面
      • logs.js
      • logs.json
      • logs.wxml
      • logs.wxss
    • 其他页面...
  • /utils/:给用户预留的用来写工具的文件夹,可删
  • /app.js:项目总入口js,项目初始化、全局钩子函数等等
  • /app.json:项目全局配置文件,路由配置、顶部栏和顶部栏的功能和样式配置等等
  • /app.wxss:项目全局样式文件
  • /project.config.json:项目信息等,类似于 npm 的 package.json 文件
  • /sitemap.json:微信索引配置文件

整体入口文件:/app.js

身为入口文件,需要初始化 app,同时可以绑定一些 app 级的钩子函数、全局方法、全局变量等。

可以写一些其他方法,用此文件可以用 this 可以访问,其他页面需要用 getApp() 方法,拿到 App 实例对象后访问。

js 复制代码
App({
  onLaunch() {}, // 钩子函数,App 刚被打开
  onHide() {}, // 钩子函数,App 被隐藏,进入后台
  onShow() {}, // 钩子函数,App 从后台打开至前台
  onError(error) {}, // 事件监听,发生错误
  onPageNotFound() {}, // 事件监听,第一次打开时,默认页面没找到(一般是由于路径写错了)
  onThemeChange() {}, // 事件监听,监听到系统主题变化

  // 其他对象,比如下面这个惯例用来存放全局数据
  globalData: {},
})

整体全局配置文件:/app.json

官方文档

该文件为项目的整体配置文件,包括页面路由、插件、网络超时时间等均在此文件配置,页面内容可配置内容如下:

js 复制代码
{
  pages: [], // 必填 页面路径列表,无论是页面(使用 Page 生成)还是组件(使用 Component 生成),都可以作为页面使用
  entryPagePath: '', // 小程序默认启动首页
  window: {}, // 全局的默认窗口表现
  tabBar: {}, // 底部 tab 栏的表现
  networkTimeout: {}, // 网络超时时间
  debug: boolean, // 是否开启 debug 模式,默认关闭
  functionalPages: boolean, // 是否启用插件功能页,默认关闭
  subpackages: {}, // [] 分包结构配置
  workers: '', // Worker 代码放置的目录
  requiredBackgroundModes: [], // 需要在后台使用的能力,如「音乐播放」
  plugins: {}, // 使用到的插件
  preloadRule: {}, // 分包预下载规则
  resizable: boolean, // PC 小程序是否支持用户任意改变窗口大小(包括最大化窗口);iPad 小程序是否支持屏幕旋转。默认关闭
  usingComponents: {}, // 全局自定义组件配置 开发者工具
  permission: {}, // 小程序接口权限相关设置
  sitemapLocation: '', // 指明 sitemap.json 的位置
  style: '', // 指定使用升级后的weui样式
  useExtendedLib: {}, // 指定需要引用的扩展库
  entranceDeclare: {}, // 微信消息用小程序打开
  darkmode: boolean, // 小程序支持 DarkMode
  themeLocation: '', // 指明 theme.json 的位置,darkmode为true为必填 开发者工具 1.03.200427
  lazyCodeLoading: '', // 配置自定义组件代码按需注入
  singlePage: {}, // 单页模式相关配置
}

使用 navigator 标签或 js 跳转切换页面

官方文档

对于路由的触发方式以及页面生命周期函数如下:

路由方式 触发时机 路由前页面 路由后页面
初始化 小程序打开的第一个页面 onLoad, onShow
打开新页面 调用 API wx.navigateTo
使用组件 <navigator open-type="navigateTo"/>
onHide onLoad, onShow
页面重定向 调用 API wx.redirectTo
使用组件 <navigator open-type="redirectTo"/>
onUnload onLoad, onShow
页面返回 调用 API wx.navigateBack
使用组件<navigator open-type="navigateBack">
用户按左上角返回按钮
onUnload onShow
Tab 切换 调用 API wx.switchTab
使用组件 <navigator open-type="switchTab"/>
用户切换 Tab
各种情况请异步官方文档
重启动 调用 API wx.reLaunch
使用组件 <navigator open-type="reLaunch"/>
onUnload onLoad, onShow

小程序的 API(wx.的功能)

官方文档

是小程序中,使用 js 能实现的功能,主要是通过 wx[方法名] 的方式使用,也有其他方式的调用,其功能包括并不限于基础、系统、更新、小程序、调试、定时器、环境变量、路由、界面、交互、键盘、发起请求、下载、上传...等功能,具体参考官方文档吧,功能太多了。

js 相关

页面的 js 文件基本配置

使用 Page 方法初始化页面,传入一个对象,这个对象可以用来编写逻辑

js 复制代码
Page({
  data: {}, // 页面的初始数据
  options: {}, // 页面的组件选项,同 Component 构造器 中的 options ,需要基础库版本 2.10.1
  onLoad() {}, // 生命周期—监听页面加载
  onShow() {}, // 生命周期—监听页面显示
  onReady() {}, // 生命周期—监听页面初次渲染完成
  onHide() {}, // 生命周期—监听页面隐藏
  onUnload() {}, // 生命周期—监听页面卸载(一般跳转页面,不会卸载)

  onPullDownRefresh() {}, // 监听用户下拉动作
  onReachBottom() {}, // 页面上拉触底事件的处理函数
  onShareAppMessage() {}, // 用户点击右上角转发
  onShareTimeline() {}, // 用户点击右上角转发到朋友圈
  onAddToFavorites() {}, // 用户点击右上角收藏
  onPageScroll() {}, // 页面滚动触发事件的处理函数
  onResize() {}, // 页面尺寸改变时触发,详见 响应显示区域变化
  onTabItemTap() {}, // 当前是 tab 页时,点击 tab 时触发

  // 其他 any 开发者可以添加任意的函数或数据到 Object 参数中,在页面的函数中用 this 可以访问
})

定义和修改页面变量

定义变量:

js 复制代码
// pages/index/index.js
Page({
  /**
   * 页面的初始数据
   */
  data: {
    name: '我的名字',
    people: {
      name: 'people 的名字',
      age: 18,
    },
  },
}

修改变量:

js 复制代码
// 没错,用法和 react 的 this.setState 很相似,和 react 不同的是,this.setData 是一个同步函数
console.log(this.data.name) // 我的名字
this.setData({
  name: '新的名字',
  'people.age': 19, // 只修改 people 的 age 字段,等效于下面注释的内容
  // people: {
  //   ...this.data.people,
  //   age: 19,
  // }
})
console.log(this.data.name) // 新的名字

绑定事件

类似于 html 中的事件,小程序也支持很多事件,比如点击事件 tap、手指触摸动作开始 touchstart 等等,

这些事件有多个绑定方式,把绑定方式拼接在事件前即可:

  • bind:最常用的绑定方式
  • catch:会阻止事件向上冒泡
  • mut-bind:基础库 2.8.2 添加的,比较不常用,在冒泡时,只触发一次

注意: 不能在事件中传值,只能写一个方法名,想传数据,需要设置为标签的自定义属性,再在事件对象中获取。

使用时,需要添加前缀 bind: 比如:

html 复制代码
<view bindtap="clickName" data-age="{{people.age}}">{{people.name}}</view>

事件方法

js 复制代码
Page({
  clickName(e) {
    console.log(e)
    // 将打印事件对象,包含点击位置、点击对象、点击对象的位置信息、绑定的自定义属性等
  }
})

常用事件:

  • tap:手指触摸后马上离开
  • touchstart:手指触摸动作开始
  • touchmove:手指触摸后移动
  • touchcancel:手指触摸动作被打断,如来电提醒,弹窗
  • touchend:手指触摸动作结束
  • longpress:手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发 1.5.0
  • longtap:手指触摸后,超过350ms再离开(推荐使用longpress事件代替)
  • transitionend:会在 WXSS transition 或 wx.createAnimation 动画结束后触发
  • animationstart:会在一个 WXSS animation 动画开始时触发
  • animationiteration:会在一个 WXSS animation 一次迭代结束时触发
  • animationend:会在一个 WXSS animation 动画完成时触发
  • touchforcechange:在支持 3D Touch 的 iPhone 设备,重按时会触发

页面钩子函数等

  • onLoad(options):生命周期函数--监听页面加载

  • onReady():生命周期函数--监听页面初次渲染完成

  • onShow():生命周期函数--监听页面显示

  • onHide():生命周期函数--监听页面隐藏

  • onUnload():生命周期函数--监听页面卸载

  • onPullDownRefresh():页面相关事件处理函数--监听用户下拉动作

  • onReachBottom():页面上拉触底事件的处理函数

  • onShareAppMessage():用户点击右上角分

数据缓存 storage

官方文档

类似于前端开发的 localStorage,小程序也有:storage。

以下是操纵 storage 的方法的同步版本,把 Sync 去掉就是异步版本,但用法会有所不同,需要添加成功失败的回调函数等等,详情异步官方教程。

js 复制代码
wx.setStorageSync(key, value) // 设置
wx.getStorageSync(key) // 获取
wx.removeStorageSync(key) // 移除
wx.getStorageInfoSync() // 获取 storage 存储信息
wx.clearStorageSync() // 清空 storage

wxml 相关

wxml 和 html 变化比较大的是下面两个:

  • view 标签取代 div
  • text 标签取代 span

所以小程序的代码中,看不到 div 和 span,但可能会看到大量的 view 和 text 标签。

标签 text

官方文档

有以下特性:

  • text 标签,专门用于写文本的标签,内部只能再嵌套 text标签
  • 会自动保留换行的原样输出
  • user-select 属性:只有这个标签中的文字,可以实现长按复制的功能,前提也是需要设置该属性,会使文本节点显示为 inline-block
  • decode 属性:默认不会解析 &nbsp; 等输入,需要添加 decode 属性
  • space 属性,值为字符串,控制内部文本中的空格如何显示,取值:ensp-中文字符空格一半大小;emsp-中文字符空格大小;nbsp-根据字体设置的空格大小

标签 image

官方文档

支持 JPG、PNG、SVG、WEBP、GIF 等格式。

  • 该组件的图片,默认宽度320px、高度240px,图片会被强制拉伸
  • image组件中二维码/小程序码图片不支持长按识别。仅在wx.previewImage中支持长按识别
  • lazy-load 属性,是否使用懒加载
  • mode 属性,图片的尺寸、位置等设置,有以下值:
    • scaleToFill:缩放模式,不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素
    • aspectFit:缩放模式,保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。
    • aspectFill:缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。
    • widthFix:缩放模式,宽度不变,高度自动变化,保持原图宽高比不变
    • heightFix:缩放模式,高度不变,宽度自动变化,保持原图宽高比不变
    • top:不缩放图片,图片移动至顶部
    • bottom:不缩放图片,图片移动至底部
    • center:不缩放图片,图片移动至中间
    • left:不缩放图片,图片移动至左边
    • right:不缩放图片,图片移动至右边
    • top left:不缩放图片,图片移动至左上边
    • top right:不缩放图片,图片移动至右上边
    • bottom left:不缩放图片,图片移动至左下边
    • bottom right:不缩放图片,图片移动至右下

标签 navigator

官方文档

页面链接,类似 a 标签,但 navigator 是块级元素。

  • url:跳转的链接。
  • target:
    • self:默认,当前小程序
    • miniProgram,其他小程序
  • open-type:跳转方式(带 关闭 字的,意思是只页面会被卸载)
    • navigate:默认值,保留当前页面(跳转后的页面左上角会有个返回按钮)并跳转,不能跳转到存在于 tabbar 中的页面,否则点击无反应,对应 wx.navigateTowx.navigateToMiniProgram 的功能
    • redirect: 关闭 当前页面,跳转到应用内的某个页面,不能跳转到存在于 tabbar 中的页面,否则点击无反应,对应 wx.redirectTo 的功能
    • switchTab:跳转到 tabBar 页面,并 关闭 其他所有非 tabBar 页面,对应 wx.switchTab 的功能
    • reLaunch: 关闭 所有页面,打开到应用内的某个页面,对应 wx.reLaunch 的功能
    • navigateBack: 关闭 当前页面,返回上一页面或多级页面,对应 wx.navigateBack 的功能
    • exit:退出小程序,target="miniProgram"时生效

标签 button

官方文档

样式相关属性:

  • size:按钮的大小
  • type:按钮的样式类型
  • plain:按钮是否镂空,背景色透明
  • disabled:是否禁用
  • loading:名称前是否带 loading 图标

一个关键属性 open-type,取值如下:

  • contact:打开客服会话,如果用户在会话中点击消息卡片后返回小程序,可以从 bindcontact 回调中获得具体信息,具体说明(小程序插件中不能使用)
  • share:触发用户转发给好友的功能,使用前建议先阅读使用指引
  • getPhoneNumber:获取用户手机号,需用户授同意,实际是拿到用户授权信息,需要通过后台真正去获取,可以从bindgetphonenumber回调中获取到用户信息,具体说明 (小程序插件中不能使用)
  • getUserInfo:获取用户信息,需用户授同意,可以直接拿到用户个人信息,可以从bindgetuserinfo回调中获取到用户信息 (小程序插件中不能使用)
  • launchApp:打开APP,实际是需要先从 App 跳转到此小程序,这个功能是再返回 App 的功能,可以通过app-parameter属性设定向APP传的参数,具体说明
  • openSetting:打开授权设置页,让用户查看自己给这个小程序的授权,并可以关闭授权。
  • feedback:打开“意见反馈”页面,用户可提交反馈内容并上传日志,开发者可以登录小程序管理后台后进入左侧菜单“客服反馈”页面获取到反馈内容

标签 icon

官方文档

小程序提供的一些iconfont,没几个,通过 type、size、color 来控制展示。

wxml 中绑定变量

变量需要使用双花括号引入,直接写 js 中 data 对象中定义好的字段即可。

如果是标签的自定义属性,需要添加 data- 前缀,否则无法显示。

html 复制代码
<view>{{name}}</view>
<view data-age="{{people.age}}">{{people.name}}</view>

wxml 中的 wx:for 用法

  • wx:for:绑定遍历的数组
  • wx:key:指定用作 key 的数组对象的字段,如果是个普通数组,可以写为 *this,表示没有 key
  • wx:for-index:非必须,指定遍历后当前项的索引值,默认 index
  • wx:for-item:非必须,指定遍历后当前项的临时变量,默认 item

在 js 中绑定数组 list

js 复制代码
Page({
  data: {
    list: [
      {
        thisId: 1,
        name: '名字1'
      },
      {
        thisId: 2,
        name: '名字2'
      },
      {
        thisId: 3,
        name: '名字3'
      },
    ],
  },
}

在 wxml 中使用

html 复制代码
<view
  wx:for="{{list}}"
  wx:key="thisId"
  wx:for-index="index"
  wx:for-item="item"
>
  <view>索引值:{{index}}</view>
  <view>名字:{{item.name}}</view>
</view>

wx:for 也可以遍历对象,遍历对象时 wx:for-index 为当前字段的 key,wx:for-item 为当前字段的值。

wx:if 和 wx:hidden 用法

  • wx:if 等同于 vue 的 v-if,根据条件来决定是否渲染 wx:hidden 等同于 vue 的 v-show,根据条件来决定是否显示
html 复制代码
<view wx:if="{{false}}">不渲染</view>
<view wx:elif="{{false}}">不渲染</view>
<view wx:else="{{false}}">渲染</view>

<view wx:hidden="{{true}}">不显示</view>

简易双向绑定 model: 功能

在 WXML 中,普通的属性的绑定是单向的,但有时这个会比较麻烦,尤其输入框的值,比如:

html 复制代码
<!-- 当 value 值改变时,input 显示的值也会变化,但当用户修改 input 时,this.data.value 却不会变 -->
<input value="{{value}}" />

如果想实现类似 vue 的 v-model 功能,则可以是用「简易双向绑定机制」

可以在对应项目之前加入 model: 前缀:

html 复制代码
<input model:value="{{value}}" />

当用户修改 input 的值时,this.data.value 的值,也会相当于执行了 this.setData() 一样,同时被修改。

还可以在使用自定义组件时,使用简易双向绑定功能

html 复制代码
<!-- 父组件的 wxml -->
<!-- 把 this.data.pageValue 传递给子组件的 myValue -->
<MyComponent model:my-value="{{pageValue}}"></MyComponent>
js 复制代码
// 子组件的js
Component({
  properties: {
    myValue: String, // 接收值
  },
  ready() {
    // 直接更新 myValue,此时父组件的 this.data.pageValue 也会被同步修改
    this.setData({
      myValue: 'leaf'
    })
  }
})

import 和 include 引用 wxml

官方文档

WXML 提供两种文件引用方式:import 和 include 两个标签。

import 可以在该文件中使用目标文件定义的 template。

使用 <import src="wxml 文件路径"> 引入其他 wxml 文件,然后就可以使用此文件定义的模板 template 了。

html 复制代码
<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>

include 标签可以将目标文件除了 <template/> <wxs/> 外的整个代码引入,相当于是拷贝到 include 位置

比如:

html 复制代码
<include src="header.wxml"/>
<view> body </view>

wxs 脚本文件

官方文档

wxs 脚本,类似于 html 中的 script 标签,可以写脚本。

但 wxs 脚本的语法基于 js,但和 js 有一些不同。

最好还是不要使用。

wxss 相关

wxss 样式文件不支持 * 选择器

wxss 样式文件的单位 rpx

规定页面宽度固定是 750rpx(类似于 css 的 vw、vh 的概念),使用 rpx 可以保证无论多大尺寸的屏幕上,元素的大小比例都是一样的。

引入 wxss 样式文件

在某个 wxss 文件中引入其他的 wxss 文件,需要使用 @import,只支持相对路径引入,比如:

css 复制代码
@import "../index/index.wxss";

组件

官方文档

一般会再根目录下,创建一个 /components 文件夹,放置所有的组件,比如:

  • /components/:组件文件们
    • Tabs/:一个组件,里面的文件名和此文件夹名一致,只是格式不同
      • Tabs.js:js 文件,此组件的逻辑开发文件
      • Tabs.json:json 文件,配置文件,可在此组件,覆盖配置全局 /app.json 文件中的某些配置
      • Tabs.wxml:wxml 文件,组件结构,类似于 html 文件
      • Tabs.wxss:wxss 文件,组件中的样式,类似于 css 文件
    • 其他组件...
  • /pages/:页面文件们
  • /utils/:给用户预留的用来写工具的文件夹,可删
  • /app.js:项目总入口js,项目初始化、全局钩子函数等等
  • /app.json:项目全局配置文件,路由配置、顶部栏和顶部栏的功能和样式配置等等
  • /app.wxss:项目全局样式文件
  • /project.config.json:项目信息等,类似于 npm 的 package.json 文件
  • /sitemap.json:微信索引配置文件

其中 json 文件默认内容如下:

json 复制代码
{
  "component": true,
  "usingComponents": {}
}

js 文件默认内容如下(去除了无用的换行和空格):

js 复制代码
// components/Tabs/Tabs.js
Component({
  properties: {}, // 组件的属性列表
  data: {}, // 组件的初始数据
  methods: {}, // 组件的方法列表

  created() {}, // 生命周期函数-在组件实例刚刚被创建时执行,注意此时不能调用 setData
  attached() {}, // 生命周期函数-在组件实例进入页面节点树时执行
  ready() {}, // 生命周期函数-在组件布局完成后执行
  moved() {}, // 生命周期函数-在组件实例被移动到节点树另一个位置时执行
  detached() {}, // 生命周期函数-在组件实例被从页面节点树移除时执行
  error(error) {}, // 每当组件方法抛出错误时执行

  // 和页面相关的生命周期函数
  show() {}, // 页面被展示
  hide() {}, // 页面被隐藏
  resize(size) {}, // 页面尺寸变化

  observers: {}, // 组件数据字段监听器,用于监听 properties 和 data 的变化,参见 数据监听器
  behaviors: [], // 类似于mixins和traits的组件间代码复用机制,参见 behaviors
  relations: {}, // 组件间关系定义,参见 组件间关系
  externalClasses: [], // 组件接受的外部样式类,参见 外部样式类
})

基本使用组件

已经写完一个组件,比如写了 /components/Tabs/Tabs 组件,那么这个组件就是「被使用组件」,需要使用该组件的页面或组件,称为「使用者」。

打开使用者的 json 文件,在 usingComponents 字段中添加被使用组件,可以使用相对路径或绝对路径:

json 复制代码
  "usingComponents": {
    "Tabs": "../../components/Tabs/Tabs"
    // "Tabs": "/components/Tabs/Tabs"
  }

然后打开使用者的 wxml 文件,直接使用标签即可。

html 复制代码
<!-- 使用者的 wxml -->
<Tabs><Tabs>

父组件向子组件传值

假设父组件为 /pages/index/index,子组件为 /components/Tabs/Tabs。

html 复制代码
<!-- /pages/index/index.wxml 中 -->
<Tabs name="小明" age="{{18}}"></Tabs>

在子组件的 properties 属性中进行接收,即可把传来的字段,认为是注册在 data 中一样使用了。

js 复制代码
// /components/Tabs/Tabs.js 中
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    name: {
      type: String, // 将会把传来的值,隐形转换为 type 指定的类型
      value: '没有传 name', // 如果父组件没有传这个值时的缺省值
    },
    age: Number, // 可以直接指定 type 即可,不设置缺省值
  },
  ready() {
    console.log(this.data.name) // 小明
    console.log(this.properties.name) // 小明
  },
  // ...其他字段省略
})

子组件向父组件传值

子组件使用方法 this.triggerEvent() 方法,触发父组件监听的方法,并传递数据和配置。

父组件使用 bind{事件名} 来监听子组件事件,并绑定方法进行处理。

this.triggerEvent(name, detail, options)

  • name:String,触发的父组件的方法名
  • detail:Any,传送的数据
  • options:Object,事件触发的配置
    • bubbles:Boolean,默认 false,事件是否冒泡
    • composed:Boolean,默认 false,事件是否可以穿越组件边界,为false时,事件将只能在引用组件的节点树上触发,不进入其他任何组件内部
    • capturePhase:Boolean,默认 false,事件是否拥有捕获阶段

假设父组件为 /pages/index/index,子组件为 /components/Tabs/Tabs。

子组件发射数据

js 复制代码
// /components/Tabs/Tabs.js 中的某方法中
this.triggerEvent('tabsSend', 'from Tabs Data') // 触发 pageEventListener

父组件接受数据

html 复制代码
<!-- 父组件 /pages/index/index.wxml -->
<!-- 绑定事件监听,使用 bind{事件名} -->
<Tabs bindtabsSend="tabsSend"></Tabs>

父组件处理接受到事件后的方法

js 复制代码
// 父组件 /pages/index/index.js
Page({
  // 添加方法 --- 如果为组件,需要把方法写在 methods 对象中。
  tabsSend(e) {
    // e.detail 即为传过来的数据
    console.log(e.detail) // from Tabs Data
  }
})

组件的插槽 slot

和 vue 的插槽类似。

默认可支持单个不具名插槽,如果需要多个插槽,也就是具名插槽,需要在该该组件的 js 文件的 options 配置对象中,添加 multipleSlots: true。

假设父组件为 /pages/index/index,子组件为 /components/Tabs/Tabs。

子组件开发时,做好预先处理,使用 留好位置:

html 复制代码
<!-- /components/Tabs/Tabs -->
<view>子组件中</view>
<slot></slot>
父组件在子组件标签中写内容,会自动填写到子组件的 所在的位置
html 复制代码
<!-- /components/index/index -->
<Tabs>
  <view>这是父组件传入的节点</view>
</Tabs>

组件的混入 behaviors

官方文档

behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的 “mixins” 或 “traits”。

每个 behavior 可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。 每个组件可以引用多个 behavior ,behavior 也可以引用其它 behavior 。

只有组件才能使用 behaviors,且 behaviors 中可以再引入使用其他的 behaviors。

behaviors 中会有和组件相同的字段或方法的定义,其遵循:「同名字段的覆盖和组合规则

其大致规则如下:

  • 同名的属性 (properties) 或方法 (methods)
    • 组件的属性或方法会覆盖 behavior 中的同名属性或方法
    • 定义靠后的 behavior 的属性或方法会覆盖靠前的同名属性或方法
  • 如果有同名的数据字段 (data)
    • 同名的数据字段都是对象类型,会进行对象合并
    • 其余情况会进行数据覆盖,组件 > 父 behavior > 子 behavior 、 靠后的 behavior > 靠前的 behavior
  • 生命周期函数不会相互覆盖
    • 子 behavior 优先于 父 behavior 执行
    • 靠前的 behavior 优先于 靠后的 behavior 执行

创造一个 behaviors:

js 复制代码
// /components/behavior_1.js 中
module.exports = Behavior({
  properties: {}, // 同组件的属性
  data: {}, // 同组件的数据
  methods: {}, // 同自定义组件的方法
  behaviors: [], // 引入其它的 behavior
  created() {}, // 生命周期函数
  attached() {}, // 生命周期函数
  ready() {}, // 生命周期函数
  moved() {}, // 生命周期函数
  detached() {}, // 生命周期函数
})

引入使用 behaviors:

js 复制代码
// 某个组件中

// 先引入
const behaviors_1 = require('../behavior_1')

// 再使用
Component({
  behaviors: [ behaviors_1 ],
  // 其他字段...
})

内置 behaviors

小程序内置一些 behaviors,自定义组件可以通过引用内置的 behavior 来获得内置组件的一些行为:

js 复制代码
Component({
  behaviors: ['wx://form-field']
})

更多内置 behaviors 参考官方文档。

数据监听 observers

官方文档

只有组件才有的数据监听功能 observers,其类似于 vue 的 watch。

observers 是 setData 方法执行时被触发时,监听的变量被赋值,哪怕赋值前后的值无变化,也会被触发。

js 复制代码
Component({
  data: {
    numA: 1,
    numB: 100,
    numAll: 0,
    people: {name: '小明'},
    list: [0, 1, 2],
  },
  // 监听数据变化
  observers: {
    // 监听 numAll 被修改
    numAll(numAll) {},
    // 在 numA 或者 numB 被设置时,执行这个函数
    'numA, numB'(numA, numB) {},
    // 监听 people.name 被修改
    'people.name'(name) {},
    // 监听数组 list 第一项被修改
    'list[0]'(list0) {},
    // 监听 people 任何一项被修改
    'people.**'(people) {},
    // 每次 setData 时都触发
    '**'(data) {},
  },
})

data 中的纯数据字段

官方文档

data 中定义的字段,和 properties 接受的属性们,都可以使用再 wxml 中,但很多时候,我们的一些字段仅仅是记录在 js 中使用,而并不会参与页面展示。

这时可以把这个字段定义为「纯数据字段」,不用于 WXML 中的界面渲染,可以用于提升页面更新性能。

使用方式就是指定规则,然后 data 和 properties 属性中所有符合规则的数据,都被指定为纯数据字段。

使用方式一:在 js 中设置 ,在组件的 js 文件中,给 options 配置对象添加 pureDataPattern 字段,赋值正则表达式。

js 复制代码
Component({
  options: {
    pureDataPattern: /^_/ // 指定所有 _ 开头的数据字段为纯数据字段
  },
  data: {
    a: 1,
    _a: 123, // 纯数据字段
  },
  properties: {
    a: Boolean,
    _b: { // 纯数据字段
      type: Boolean,
      observer() {}, // 不要这样做!这个 observer 永远不会被触发
    },
  }
})

使用方式二:在 json 中设置 ,在组件的 json 文件中,给 options 配置对象添加 pureDataPattern 字段,赋值正则表达式的字符串。

js 复制代码
{
  "pureDataPattern": "^_"
}