简介

  1. 用户不需要下载安装,点开即用,用完即走,实现用户当前需求的工具
  2. 运行环境不同:网页运行在浏览器环境中,小程序运行在微信环境中
  3. API不同:小程序无法调用DOM和BOM的API,但小程序可以调用微信环境提供的API,例如:地理位置、扫码、支付

项目结构

  1. 默认项目文件
    • pages:用来存放所有小程序页面,以单独文件夹存在
    • utils:用来存放工具性质的模块
    • app.js小程序项目的入口文件
    • app.json:小程序项目的全局配置文件
    • app.wxss:小程序项目的全局样式文件
    • project.config.json:项目的配置文件
    • sitemap.json:用来配置小程序及其页面是否允许被微信索引

常用组件

  1. view:类似于HTML中的div,是一个块级元素
  2. block:类似于Vue中的template,是一个占位符
  3. scroll-view:滚动列表效果
  4. swiper和swiper-item:轮播图容器组件和轮播图item组件
  5. text:显示文字,selectable属性实现长按选中文本
  6. rich-text:通过nodes属性把HTML字符串渲染为对应的UI结构
    <rich-text nodes="<h1 style='color:lightcoral;'>标题</h1>"></rich-text>
  7. button:按钮组件,通过open-type属性可以调用微信提供的各种功能
  8. image:图片组件,mode属性用来指定图片的裁剪和缩放模式;默认宽300px,高240px

样式介绍

rpx尺寸单位

  1. rpx是微信小程序独有的,用来解决屏幕适配的尺寸单位;实现原理rpx把所有设备的屏幕,在宽度上等分为750份(当前屏幕总宽度为750rpx)
  2. rpx与px之间的单位换算,比如:屏幕宽度为375px,共有750物理像素,等分750rpx
    • 750rpx = 375px = 750物理像素
    • 1rpx = 0.5px = 1物理像素
设备 rpx换算px(屏幕宽度/750) px换算rpx(750/屏幕宽度)
iPhone5 1rpx = 0.42px 1px = 2.34rpx
iPhone6 1rpx = 0.5px 1px = 2rpx
iPhone6 Plus 1rpx = 0.552px 1px = 1.81rpx
  1. 官方建议:开发微信小程序时,设计师可以用iPhone6作为视觉稿的标准

导入样式

例如:根目录下创建common公共样式,然后在index.wxss导入common.wxss

全局样式

根目录有个app.wxss文件,是专门用来写全局样式,不需要导入

局部样式

页面的.wxss文件中定义的样式为局部样式,只作用于当前页面

修改data值

看起来很像vue,但又有点不一样

1
2
3
4
5
6
7
8
9
10
11
<view>数字:{{count}}</view>
<button type="primary" bindtap="changeCount">点击修改</button>

data: {
count: 1
},
changeCount(){
this.setData({
count: this.data.count + 1
})
}

事件绑定

常用事件

  1. bindtap:类似于vue中的@click,在微信里与data数据同一层
  2. bindinput:用来获取输入框中的文本,通过e.detail.value获取文本数据

事件传参

  1. 小程序中的事件传参比较特殊,不能在绑定事件同时为事件处理函数传递参数;bindtap属性无法传值,相当于调用名称为btnhandler(123)的事件处理函数
    <button bindtap="btnhandler(123)">事件传参</button>
  2. 组件提供data-xxx自定义属性传参,其中xxx表示参数名;info会被解析为参数名,数值2会被解析为参数值
    <button bindtap="btnHandler" data-info="{{2}}">事件传参</button>
  3. 在事件处理函数中,通过e.target.dataset.参数名即可获取到具体参数的值
    1
    2
    3
    4
    5
    <button type="primary" bindtap="btnHandler" data-info="{{2}}">事件传参</button>

    btnHandler(e){
    console.log(e.target.dataset.info)
    }

获取文本数据

  1. bindinput输入文本时触发,通过e.detail.value获取文本数据
    1
    2
    3
    4
    5
    <input type="text" bindinput="inputHandler"/>

    inputHandler(e){
    console.log(e.detail.value)
    }
  2. 绑定data数据,输入文本的同时修改data数据;value默认值动态绑定msg,输入文本时触发inputHandler方法,msg修改成文本内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <input value="{{msg}}" bindinput="inputHandler"/>

    data: {
    msg: 'Hi, '
    },
    inputHandler(e){
    this.setData({
    msg: e.detail.value
    })
    console.log(this.data.msg)
    }

条件渲染

  1. 使用wx:if="{{condition}}"来判断是否需要渲染该代码块
    1
    2
    3
    <view wx:if="{{sex === 1}}">男</view>
    <view wx:elif="{{sex === 2}}">女</view>
    <view wx:else>保密</view>
  2. block标签是占位符,不显示在页面中,实现多个组件显示隐藏
    1
    2
    3
    4
    <block wx:if="{{true}}">
    <view>你好</view>
    <view>幽蓝</view>
    </block>
  3. hidden属性类似v-show,同样起到显示隐藏效果,它和if区别在于生成原理上不同,if是动态创建或移除元素,hidden是切换样式(display:none/block)控制元素显示隐藏,频繁切换hidden性能更好
    <view hidden="{{true}}">条件为true隐藏,条件为false显示</view>

列表渲染

  1. wx:for循环渲染组件,默认item表示项的值,index表示索引
    1
    2
    3
    4
    5
    6
    7
    <view wx:for="{{brand}}">
    品牌:{{item}},索引:{{index}}
    </view>

    data: {
    brand: ['苹果', '华为', '小米']
    }
  2. 修改默认item、index名字
    1
    2
    3
    <view wx:for="{{brand}}" wx:for-item="value" wx:for-index="i">
    品牌:{{value}},索引:{{i}}
    </view>
  3. wx:key用来提高wx:for渲染性能,vue中不写:key会报错,小程序中不写wx:key会报警告
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <view wx:for="{{brand}}" wx:key="index">
    品牌:{{item.name}}
    </view>

    data: {
    brand: [
    {name: '华为'},
    {name: '小米'},
    {name: '魅族'},
    ]
    }

全局配置

app.json

  1. 根目录app.json文件是小程序的全局配置文件,常用配置项:
    • pages:记录当前小程序所有页面的存放路径
    • window:全局设置小程序窗口的外观
    • tabBar:设置小程序底部的tabBar效果
    • style:是否启动新版的组件样式

window常用配置项

属性名 默认值 说明
navigationBarTitleText Weixin 导航栏标题文字内容
navigationBarBackgroundColor #fff 导航栏背景颜色
navigationBarTextStyle black 导航栏标题颜色,仅支持black / white
backgroundColor #fff 下拉窗口的背景色
backgroundTextStyle dark 下拉loading的样式,仅支持dark / light
enablePullDownRefresh false 是否全局开启下拉刷新
onReachBottomDistance 50 页面上拉触底事件触发时距页面底部距离,单位为px

tabBar

  1. tabBar用于多页面快速切换,类似早期智能手机的底部栏,有返回、首页、后台等按钮;tabBar中只能配置2~5tab页签;渲染顶部tabBar时,不显示icon,只显示文本

  2. tabBar6个组成部分

    • backgroundColor:tabBar的背景色
    • borderStyle:tabBar上边框的颜色
    • selectedIconPath:选中时的图片路径
    • iconPath:未选中时的图片路径
    • selectedColor:tab上的文字选中时的颜色
    • color:tab上文字的默认(未选中)颜色
  3. tabBar配置项

    属性名 默认值 说明
    position bottom tabBar的位置,仅支持bottom / top
    borderStyle black tabBar的上边框的颜色,仅支持black / white
    color tab上文字的默认(未选中)颜色
    selectedColor tab上文字选中时颜色
    backgroundColor tabBar的背景色
    list 必填,标签页的列表,2~5个tab页签
  4. tab项配置选项

    属性名 说明
    position 必填,页面路径,页面必须在pages中预先定义
    borderStyle 必填,tab上显示的文字
    color 未选中时的图标路径;当postion为top时,不显示icon
    selectedColor 选中时的图标路径;当postion为top时,不显示icon
  5. tabBar写法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    {
    "pages":[
    "pages/index/index",
    "pages/test/test"
    ],
    "tabBar": {
    "list": [
    {
    "pagePath": "pages/index/index",
    "text": "index"
    },
    {
    "pagePath": "pages/test/test",
    "text": "test"
    }
    ]
    },
    ...
    }

    tabBar想要展示的页面,必须放在pages数组内的顶部,否则会显示失败

页面配置

  1. 页面配置个人称它为局部配置,新生成的页面,文件夹自带.json文件,它是当前页面设置局部配置的地方
  2. 常用配置项
    属性名 默认值 说明
    navigationBarBackgroundColor #000 当前页面导航栏背景颜色,如#000
    navigationBarTextStyle black 当前页面导航栏标题颜色,仅支持black/white
    navigationBarTitleText 当前页面导航栏标题文字内容
    backgroundColor #fff 当前页面下拉窗口的背景色
    backgroundTextStyle dark 当前页面下拉loading的样式,仅支持dark/light
    enablePullDownRefresh false 是否为当前页面开启下拉刷新的效果
    onReachBottomDistance 50 页面上拉触底时间触发时距页面底部距离,单位为px

数据请求

网络数据请求的限制

  1. 出于安全性方面的考虑,小程序官方对数据接口的请求做出如下两个限制:
    • 只能请求HTTPS类型的接口
    • 必须将接口的域名添加到信任列表中
  2. 配置request合法域名:登入微信小程序管理后台 > 开发 > 开发设置 > 服务器域名 > 修改request
    • 域名只支持https协议
    • 域名不能使用IP地址或localhost
    • 域名必须经过ICP备案
    • 服务器域名一个月内最多可申请5次修改

发送get请求

调用微信小程序提供的wx.request()方法,示例代码:

1
2
3
4
5
6
7
8
9
10
11
wx.request({
url: 'https://www.xxxxx.com/api/get', // 请求的接口地址,必须基于https协议
method: 'GET',
data: { // 发送到服务器的数据
name: 'ulan',
age: 9
},
success: (res) => { // 请求成功之后的回调函数
console.log(res)
}
})

发送post请求

修改上面method为post请求即可method: 'POST'

页面刚加载时请求数据

1
2
3
4
5
6
7
8
// 生命周期函数,监听页面加载
onLoad(){
this.getInfo()
this.postInfo()
}

getInfo(){...}
postInfo(){...}

关于跨域和Ajax

  1. 跨域问题只存在于浏览器,由于小程序宿主环境是微信客户端,所以小程序不存在跨域问题
  2. Ajax的核心依赖于浏览器中的XMLHttpRequest这个对象,由于小程序宿主环境是微信客户端,所以小程序不能叫做”发起Ajax请求”,而是叫做”发起网络数据请求”。

页面导航

  1. 声明式导航:声明一个导航组件,点击组件实现页面跳转
  2. 编程式导航:调用小程序的导航API

声明式导航

  1. navigator组件跳转到指定的tabBar页面时,需要指定url属性和open-type属性
    • url表示要跳转的页面的地址,必须以/开头
    • open-type表示跳转的方式,必须为switchTab
      <navigator url="/pages/index/index" open-type="switchTab">导航到主页面</navigator>
  2. navigator组件跳转到非tabBar页面,操作跟上面相同,只不过open-type需要改成navigate
    <navigator url="/pages/log/log" open-type="navigate">导航到log页面</navigator>

    为了简便,导航到非tabBar页面,open-type=”navigate”属性可以省略

  3. navigator后退页面,open-type指定navigateBack,delta后退的层级
    <navigator open-type="bavigateBack" delta="1">后退</navigator>

    为了简便,如果只是后退到上一页面,可以省略delta属性,因为默认值就是1

编程式导航

  1. wx.switchTab方法的属性
    • url:需要跳转的tabBar页面路径,路径后不能带参数
    • success:接口调用成功的回调函数
    • fail:接口调用失败的回调函数
    • complete:接口调用结束的回调函数(成功、失败都会执行)

1.1 导航到tabBar页面

1
2
3
4
5
6
7
<button bindtap="gotoIndex">跳转到主页</button>

gotoIndex(){
wx.switchTab({
url: '/pages/index/index'
})
}
  1. wx.navigateTo方法的属性
    • url:需要跳转的tabBar页面路径,路径后不能带参数
    • success:接口调用成功的回调函数
    • fail:接口调用失败的回调函数
    • complete:接口调用结束的回调函数(成功、失败都会执行)

2.1 导航到非tabBar页面

1
2
3
4
5
6
7
<button bindtap="gotoLog">跳转到log页面</button>

gotoLog(){
wx.navigateTo({
url: '/pages/log/log'
})
}
  1. wx.navigateBack方法的属性
    • delta:默认值1,返回的页面数,如果delta大于现有页面数,则返回到首页
    • success:接口调用成功的回调函数
    • fail:接口调用失败的回调函数
    • complete:接口调用结束的回调函数(成功、失败都会执行)

3.1 后退导航

1
2
3
4
5
<button bindtap="gotoBack">后退</button>

gotoBack(){
wx.navigateBack()
}

导航传参

  1. 声明式导航传参

    • 参数与路径之间使用?分隔
    • 参数键与参数值用=相连
    • 不同参数用&分隔
      <navigator url="/pages/index/index?name=ulan&age=9">跳转到主页面</navigator>
      说明:跳转到主页面,通过?分隔参数,传递name和age
  2. 编程式导航传参:调用wx.navigateTo()方法跳转页面携带参数

    1
    2
    3
    4
    5
    6
    7
    <button bindtap="gotoIndex">跳转到主页面</button>

    gotoIndex(){
    wx.navigateTo({
    url: '/pages/index/index?name=ulan&age=9'
    })
    }
  3. onLoad事件接收参数,options用来接收参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    data: {
    // 用来存放参数
    query: {}
    }

    // 生命周期函数——监听页面加载
    onLoad(options){
    console.log(options) // {name: "ulan", age: 9}
    this.setData({
    query: options
    })
    }

页面事件

下拉刷新

  1. 启动下拉刷新两种方式

    • 全局:app.json的window节点,将enablePullDownRefresh设置为true
    • 局部:页面的.json配置文件中,将enablePullDownRefresh设置为true

      实际开发中,推荐使用第2种方式,为需要的页面单独开启下拉刷新

      1
      2
      3
      4
      {
      "usingComponents": {},
      "enablePullDownRefresh": true
      }
  2. 全局或局部.json配置文件中,通过backgroundColor和backgroundTextStyle来配置样式

    • backgroundColor:窗口的背景颜色,仅支持16进制的颜色值
    • backgroundTextStyle:loading的样式,仅支持dark和light
      1
      2
      3
      4
      5
      6
      {
      "usingComponents": {},
      "enablePullDownRefresh": true,
      "backgroundColor": "#efefef",
      "backgroundTextStyle": "dark"
      }
  3. onPullDownRefresh监听页面的下拉刷新事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <view>数字:{{count}}</view>

    data: {
    count: 9
    }

    // 页面相关事件处理函数,监听用户下拉动作
    onPullDownRefresh(){
    this.setData({
    count: 0
    })
    }
  4. 当处理完下拉刷新后,loading效果会一直显示,不会主动消失。调用wx.stopPullDownRefresh()可以停止当前页面的下拉刷新。

    1
    2
    3
    4
    5
    6
    7
    8
    onPullDownRefresh(){
    this.setData({
    count: 0
    })

    // 放在最后,当上面指令完成后,停止刷新效果
    wx.stopPullDownRefresh()
    }

上拉触底

  1. 上拉触底是移动端专有名词,通过手指在屏幕上的上拉滑动操作,加载更多数据的行为
  2. onReachBottom()监听当前页面的上拉触底事件,想看到效果,最好页面很长有滚动条
    1
    2
    3
    onReachBottom(){
    console.log('触发了上拉触底的事件')
    }
  3. 默认触底距离是50px,容易频繁触发上拉触底事件,可在全局或页面的.json配置文件中,通过onReachBottomDistance属性配置上拉触底距离
    1
    2
    3
    4
    {
    "usingComponents": {},
    "onReachBottomDistance": 150
    }

生命周期

生命周期分类

  1. 应用生命周期函数
    • onLauch(options){}:小程序初始化完成时,全局只触发一次
    • onShow(options){}:小程序启动或从后台进入前台显示时触发
    • onHide(){}:小程序从前台进入后台时触发
  2. 页面生命周期函数
    • onLoad(options){}:监听页面加载,一个页面只调用一次
    • onSHow(){}:监听页面显示
    • onReady(){}:监听页面初次渲染完成,一个页面只调用一次
    • onHide(){}:监听页面隐藏
    • onUnload(){}:监听页面卸载,一个页面只调用一次

自定义组件

组件的引用方式

  1. 组件的引用方式分两种:
    • 局部引用:只能在当前被引用的页面内使用
    • 全局引用:可以在每个小程序页面中使用
      1
      2
      3
      4
      5
      6
      7
      8
      9
      // 在页面的.json文件中,引入组件
      {
      "usingComponents": {
      "my-test": "/components/test/test"
      }
      }

      // 在页面的.wxml文件中,使用组件
      <my-test></my-test>

组件和页面的不同点

  1. 组件的.json文件中需要声明"component": true属性
  2. 组件的.js文件中调用的是Component()函数
  3. 组件的事件处理函数需要定义到methods节点中

组件样式隔离

  1. 组件样式隔离:组件A的样式不会影响到组件B,同样不会影响到页面,反之页面的样式不会影响到其他组件
  2. 只有class选择器具有隔离效果,其他选择器不受样式隔离的影响

data数据、methods方法

  1. 定义data数据和methods方法,类似vue写法呢
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Component({
    data: {
    count: 0
    },
    methods: {
    // 事件处理函数
    addCount(){
    this.setData({ count: this.data.count + 1 })
    // 调用自定义方法
    this._showCount()
    }

    // 自定义方法建议以_开头
    _showCount(){
    wx.showToast({
    title: 'count值为:' + this.data.count,
    icon: 'none'
    })
    }
    }
    })

properties接收传递数据

  1. properties用来接收外界传递到组件中的数据
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Component({
    // 属性定义
    properties: {
    max: {
    type: Number,
    // 属性默认值
    value: 10
    }
    }
    })

    // 如果传递max为9,默认值10会被覆盖
    <my-test max="9"></my-test>
  2. data和properties,两者数据都存在同一个对象上,且都是可读可写,为了更好管理数据,咱们人为给它们进行区分
    • data更倾向于存储组件的私有数据
    • properties更倾向于存储外界传递到组件中的数据
      console.log(this.data === this.properties) // true

observers数据监听器

  1. observers用来监听和响应任何属性和数据字段的变化,从而执行特定的操作;类似于vue中的watch侦听器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // 组件的UI结构
    <view>{{n1}} + {{n2}} = {{sum}}</view>
    <button size="mini" bindtap="addN1">n1自增</button>
    <button size="mini" bindtap="addN2">n2自增</button>

    Component({
    data: { n1: 0, n2: 0, sum: 0 },
    methods: {
    addN1(){ this.setData({ n1: this.data.n1 + 1 })},
    addN2(){ this.setData({ n2: this.data.n2 + 1 })}
    },
    // 数据监听节点
    observers: {
    'n1, n2'(n1, n2){
    this.setData({ sum: n1 + n2 })
    }
    }
    })
  2. 如果某个对象需要被监听的属性太多,可以使用通配符**来监听对象中所以属性的变化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Component({
    data: {
    rgb: {
    r: 0,
    g: 0,
    b: 0
    },
    fullColor: '0, 0, 0'
    },
    observers: {
    'rgb.**'(obj){
    this.setData({
    fullColor: `${obj.r}, ${obj.g}, ${obj.b}`
    })
    }
    }
    })

纯数据字段

  1. 有些情况下,某些data中的字段(包括setData设置的字段)既不会展示在界面上,也不会传递给其他组件,仅仅在当前组件内部使用
  2. 此时,可以指定这样的数据字段为”纯数据字段”,它们将仅仅被记录在this.data中,而不参与任何界面渲染过程,这样有助于提升页面更新性能
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Component({
    data: {
    // 将rgb改造为以_开头的纯数据字段
    _rgb: {}
    },

    // 指定所有_开头的数据字段为纯数据字段
    observers: {
    pureDataPattern: /^_/
    }
    })

组件生命周期

  1. 组件全部生命周期函数
    • created:组件刚创建好时执行
    • attached:组件被挂载到页面未渲染时执行
    • ready:组件渲染完成后执行
    • moved:组件移动到另一个位置时执行
    • detached:组件被删除时执行
    • error:组件报错时执行
  2. created:此时还不能调用setData,通常给组件的this添加一些自定义的属性字段
  3. attached:此时this.data已被初始化完毕,可以进行一些初始化工作(例如发送请求,获取初始数据)
  4. detached:退出一个页面时,触发组件的detached生命周期函数;适合做一些清理性质的工作
    1
    2
    3
    4
    5
    6
    7
    Component({
    lifetimes: {
    created(){},
    attached(){},
    detached(){}
    }
    })

组件所在的页面生命周期

  1. 自定义组件的行为依赖于页面状态的变化,此时就需要用到组件所在页面的生命周期
  2. 比如你有两个页面,分别是主页和log页,主页设置好show和hide,默认进入主页执行show生命周期函数,切换到log页执行hide生命周期函数
    1
    2
    3
    4
    5
    6
    7
    Component({
    pageLifetimes: {
    show(){}, // 页面被展示
    hide(){}, // 页面被隐藏
    resize(size){} //页面尺寸变化
    }
    })

组件插槽

  1. 换个思维来理解,组件插槽类似于电源插座,不确定你以后会使用什么电子设备,总之先占个坑
  2. 默认每个组件只允许使用一个进行占位,默认只支持单个插槽
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 组件导入后,取名为my-test
    <view>
    <view>这是组件的内部节点</view>
    <slot></slot>
    </view>

    // index.wxml页面
    <my-test>
    <view>这是插入到组件slot中的内容</view>
    </my-test>
  3. 启用多个插槽
    1
    2
    3
    4
    5
    6
    // 组件的.js文件
    Component({
    options: {
    multipleSlots: true
    }
    })
  4. 自定义插槽,我希望不同插槽显示不同内容,可以使用name属性命名,引入时使用slot属性
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 组件导入后,取名为my-test
    <view>
    <view>这是组件的内部节点</view>
    <slot name="ulan"></slot>
    <slot name="jintao"></slot>
    </view>

    // index.wxml页面
    <my-test>
    <view>这是插入到组件slot中的内容</view>
    <view slot="ulan">我是ulan</view>
    <view slot="jintao">我的朋友金涛</view>
    </my-test>

父子组件通信

  1. 父子组件通信的3种方式
    • 属性绑定:用于父组件向子组件的指定属性设置数据,仅能设置JSON兼容的数据
    • 事件绑定:用于子组件向父组件传递数据,可以传递任意数据
    • 获取组件实例:父组件通过this.selectComponent()获取子组件实例对象,可以直接访问子组件的任意数据和方法
  2. 属性绑定
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // index页面的.js文件
    data: {
    count: 0
    }

    // index页面的.wxml文件,通过属性给my-test子组件传递数据
    <view>父组件的count值:{{count}}</view>
    <my-test count="{{count}}"></my-test>

    // test子组件的.js文件,设置默认值9
    properties: {
    count: {
    type: Number,
    value: 9
    }
    }

    // test子组件的.wxml文件,由于接受父组件传递的数据,这里count显示为0
    <view>子组件接受的count值:{{count}}</view>
  3. 事件绑定
    • 在父组件的js中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件
    • 在父组件的wxml中,通过自定义事件的形式,将步骤1中定义的函数引用,传递给子组件
    • 在子组件的js中,通过调用this.triggerEvent('自定义事件名称', { 参数对象 }),将数据发送到父组件
    • 在父组件的js中,通过e.detail获取到子组件传递过来的数据
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      // 第一步index.js
      Page({
      data: {
      count: 0
      },
      // 自定义事件,接收子组件传递过来的数据,并修改count
      syncCount(e){
      this.setData({
      count: e.detail.value
      })
      }
      })

      // 第二步index.wxml,这个bind:sync表示自定义事件,名称叫sync
      <view>父组件的count值:{{count}}</view>
      <my-test count="{{count}}" bind:sync="syncCount"></my-test>

      // 第三步test.js
      Component({
      properties: {
      count: {
      type: Number,
      value: 9
      }
      },
      methods: {
      // 添加点击+1事件
      addCount(){
      this.setData({
      count: this.properties.count + 1
      })
      // 触发自定义事件,将数值同步给父组件
      this.triggerEvent('sync', { value: this.properties.count })
      }
      }
      })

      // 第四步test.wxml,点击+1后,会修改count值,接着触发自定义事件
      <view>子组件接受的count值:{{count}}</view>
      <button type="default" bindtap="addCount">点击+1</button>
  4. 获取组件实例:父组件调用this.selectComponent("id或class选择器"),获取子组件的实例对象,从而直接访问子组件的任意数据和方法。调用时需要传入一个选择器,例如this.selectComponent(".customA")
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 父组件wxml
    <my-test count="{{count}}" bind:sync="syncCount" class="customA" id="cA"></my-test>
    <button bindtap="getChild">获取子组件实例</button>

    // 父组件js
    getChild(){
    const child = this.selectComponent('#cA')
    child.setData({
    // 如果写this会指向父组件,这次想修改子组件的count数据,要用child指向
    count: child.properties.count + 1
    })
    // 调用子组件的addCount方法
    child.addCount()
    }

behaviors组件代码共享

  1. behaviors用于组件间代码共享,类似于vue中的mixins;每个behavior可以包含一组属性、数据、生命周期函数和方法,组件引用它时,它的属性、数据和方法会被合并到组件中
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 调用Behavior()方法,创建实例对象
    // 使用module.exports将behavior实例对象共享出去
    module.exports = Behavior({
    // 属性节点
    properties: {},
    // 私有数据节点
    data: { username: '幽蓝' },
    // 事件处理函数和自定义方法节点
    methods: {},
    // 其他节点......
    })
  2. 导入behaviors到组件中
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // test.js
    const myBehavior = require('../../behaviors/my-behavior')

    Component({
    behaviors: [myBehavior],
    data: {}
    })

    // test.wxml,这样就能使用username共享数据
    <view>在behavior中定义的用户名是:{{username}}</view>
  3. behavior所有可用节点
    • properties:同组件的属性
    • data:同组件的数据
    • methods:同自定义组件的方法
    • behaviors:引入其他的behavior
    • created:生命周期函数
    • attached:生命周期函数
    • ready:生命周期函数
    • moved:生命周期函数
    • detached:生命周期函数
  4. 同名字段的覆盖和组合规则
    • 数据覆盖规则:组件 > 父behavior > 子behavior、靠后的behavior > 靠前的behavior

使用npm第三方包

npm包的限制

  1. 小程序支持使用npm安装第三方包,受限制影响能用的包其实很少,npm包有如下3个限制
    • 不支持依赖于Node.js内置库的包
    • 不支持依赖于浏览器内置对象的包
    • 不支持依赖于C++插件的包

Vant Weapp

  1. Vant Weapp是有赞前端团队开源的一套小程序UI组件库,使用MIT开源许可协议,对商业使用比较友好

未完待续…