# WXML 和 HTMl 的区别
标签名称不同
- HTML ( div span img a )
- WXML ( view text image navigator )
属性节点不同
<a href="#"> 超链接 </a>
<navigator url="/pages/index/index"> 主页 </navigator>
提供了类似 Vue 中的模板语法
- 数据绑定
- 列表渲染
- 条件渲染
# WXSS
一套样式语言,类似 CSS
# 区别
- 新增 rpx 尺寸单位
- WXSS 在底部支持新的尺寸单位 rpx,在不同大小的屏幕上小程序会自动进行换算
- 提供了全局的样式和局部样式
- 项目根目录中的
app.wxss
会作用于所有小程序页面 - 局部页面 .wxss 样式仅对当前页面生效
- WXSS 仅支持部分 CSS 选择器
- .class 和 #id
- element
- 并集选择器,后代选择器
- ::after 和 ::before 等伪类选择器
- 样式导入
@import "/common/common.wxss";
- 全局样式
在 app.wxss 中的样式为全局样式,作用于每一个页面
# 组件
官方文档
小程序中的组件是由宿主环境提供的,官方把小程序的组件分为了好几大类,分别是:
- 视图容器
- 基础内容
- 表单组件
- 导航组件
- 媒体组件
- map 地图组件
- canvas 画布组件
- 开放能力
- 原生组件说明
- 无障碍访问
- 导航栏
- 页面属性配置节点
# 常见的组件
view
- 普通视图区域
- 类似 HTML 中的 div, 是一个块级元素
- 常用来实现页面的布局效果
scroll-view
- 可滚动的视图区域
- 常用来实现滚动列表效果
swiper 和 swiper-item
- 轮播图
button
- 按钮组件 可以通过
open-type
属性调用微信提供的各种功能 (客服 转发 获取用户限权 获取用户信息等)
- 按钮组件 可以通过
# WXML 模板语法
# 数据绑定
- 在 data 中定义数据
Page({ | |
// 页面初始数据 | |
data: { | |
msg: "雪泥马", | |
list: { | |
name: "雪泥马", | |
age: 20, | |
sex: "男", | |
img: "https://mrnobody233.gitee.io/images/avatar.jpg" | |
}, | |
}, | |
}) |
- 在 WXML 中使用数据
<text> { msg } </text> | |
<text> { list.name } </text> | |
// 动态绑定属性 与 vue 不同 | |
<image src="{list.img}"></image> |
# 事件绑定
小程序中的常用事件
- bindtap 手指触摸后马上离开,类似 HTML 中的 click
- 为按钮绑定 tap 触摸事件
<button bindtap="btnClick">点我</button>
- 在 js 文件中定义对应的事件处理函数
Page({ | |
data:{ | |
msg:"雪泥马" | |
}, | |
// 事件参数通过形参 event (简写 e) 来接收 | |
btnClick(e) { | |
console.log(e); | |
}, | |
*// 通过调用 `this.setData (dataObject)` 方法可以给页面中的数据重新赋值 | |
btnClick() { | |
this.setData({ | |
msg: "布雪蜡" | |
}) | |
}, | |
}) |
事件传参
小程序不能在绑定事件的同时为事件处理函数传递参数,可以为组件提供data-name
自定义属性传参,其中 name 代表的是参数的名字<button bindtap="btnClick" data-step="{2}">事件传参</button>
通过
event.target.dataset.参数名
来获得具体参数值btnClick(e) {
this.setData({
msg: "布雪蜡"
})
console.log(e.target.dataset.step);
// 沙比吧。。。
},
- bindinput 文本框的输入事件
- 为文本框绑定事件
<input bindinput="iptHandler" type="text"/>
- 在 js 页面中定义事件处理函数
iptHandler(e) {
console.log(e.detail.value);
//e.detail.value 是变化后文本框最新的值
},
- bindchange 状态改变时触发
当事件回调触发的时候,会收到一个事件对象 event
属性 | 类型 | 说明 |
---|---|---|
type | String | 事件类型 |
timeStamp | integer | 页面打开到触发事件所经过的毫秒数 |
target | Object | 触发事件的组件的一些属性值集合 |
currentTarget | Object | 当前组件的一些属性值集合 |
detail | Object | 额外的信息 |
touches | Array | 触摸事件,当前停留在屏幕中的触摸点信息的组件 |
changedTouches | Array | 触摸事件,当前变化的触摸点属性的数组 |
# 条件渲染
- 在小程序中,使用
wx:if="{ isShow }"
wx:else
wx:elif
来判断是否需要渲染该代码块
<view wx:if="{isShow}">true</view> | |
<view wx:else>{isShow}</view> | |
<button bindtap="isShow">你干嘛~哎哟</button> |
data:{ | |
isShow:true, | |
}, | |
isShow(){ | |
this.setData({ | |
isShow: !this.data.isShow | |
}) | |
}, |
- 结合
<blok>
使用 wx:if
如果想要 一次性控制多个组件的展示和隐藏 可以使用一个 <block></block>
将多个组件包装起来。并在标签上使用 wx:if 控制属性,
<block wx:if="{ isShow }"> | |
<view>雪泥马</view> | |
<view>布雪蜡</view> | |
</block> |
- hidden
懒得说了 和 vue 中的条件渲染一样,一个是直接移除元素,一个是切换 display:none/block 样式
# 列表渲染
- wx:for 和 v-for 一样,循环渲染重复的组件结构,语法稍微有些不同
<view wx:for="{phoneList}"> | |
<text>索引是:{index}, item项是:{item}</text> | |
</view> |
- wx:key 不多说了
<view wx:for="{phoneList}" wv:key="index"> | |
<text>索引是:{index}, item项是:{item}</text> | |
</view> |
# 全局配置
# 常用配置项目
小程序根目录下的 app.json
文件是小程序的全局配置文件,下面是常用的几个配置文件
- pages
- 记录当前小程序所有页面的存放路径
- window
- 全局设置小程序窗口的外观
- tabBar
- 设置小程序底部的 tabBar 效果
- style
- 是否启用新版的组件样式
# window 节点常用的配置项
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
navigationBarTitleText | String | 字符串 | 导航栏标题文字 |
navigationBarBackgroundColor | HexColor | #000 | 导航栏背景颜色 |
navigationBarTextStyle | String | white | 导航栏标题颜色,只支持 white 和 black.. |
backgroundColor | HexColor | #fff | 窗口背景颜色 |
backgroundTextStyle | String | dark | 下拉 loading 的样式 仅支持 dark /light |
enablePullDownRefresh | Bollean | false | 是否全局开启下拉刷新 |
onReachBottomDistance | Number | 50 | 页面上拉触底事件触发时距页面底部距离 单位为 px |
# tabBar
用于实现多页面的快速切换,小程序一般分为 底部和顶部,注意: tabBar 中只能配置最少 2 个,最多 5 个 tab 标签,当渲染顶部 tabBar 时,不显示 icon,只显示文本
# tabBar 的 6 个组成部分
- backgroundColor: 背景色
- selectedIconPath: 选中时的图片路径
- borderStyle:tabBar 的边框颜色
- iconPath:未选中的图片路径
- selectedColor:tabBar 上文字选中时的颜色
- color:未选中时的文字颜色
# tabBar 节点配置项
"tabBar": { | |
"backgroundColor": "#ccc", | |
"color": "#fff", | |
"selectedColor": "#000", | |
"list": [ | |
{ | |
"pagePath": "pages/index/index", | |
"text": "首页", | |
"selectedIconPath": "./imagses/indexActive.png", | |
"iconPath": "./imagses/index.png" | |
}, | |
{ | |
"pagePath": "pages/demo/demo", | |
"text": "演示", | |
"selectedIconPath": "./imagses/msgActive.png", | |
"iconPath": "./imagses/msg.png" | |
}, | |
{ | |
"pagePath": "pages/call/call", | |
"text": "电话", | |
"selectedIconPath": "./imagses/callActive.png", | |
"iconPath": "./imagses/call.png" | |
} | |
] | |
}, |
# 网络数据请求
# 限制
出于安全方面考虑,小程序官方对数据接口的请求做成了如下两个限制
- 只能请求 HTTPS 类型的接口
- 登录小程序管理后台 -> 开发 -> 开发管理 -> 开发设置 -> 服务器域名 -> 修改 request 合法域名
- 必须将接口的域名添加到信任列表中
# 发起请求
调用小程序提供的 wx.request()
方法,可以发起 GET 数据请求
wx.request({ | |
url: 'https://www.escook.cn/api/get', // 地址 | |
method: 'GET', // 方法 | |
data: { // 传送的数据 | |
name: 'zs', | |
age: 20, | |
}, | |
success: (res) => { // 返回的结果 | |
console.log(res); | |
} | |
}) |
# 页面导航
指页面之间的相互跳转,在小程序中实现页面导航的两种方式
- 声明式导航
- 在页面中声明一个
<navigator>
导航组件 - 通过点击
<navigator>
组件实现页面跳转
- 编程式导航
- 调用小程序提供的导航 API,实现页面的跳转
# 声明式导航
# 导航到 tabBar 页面
tabBar 页面指的是被配置为 tabBar 的页面
在使用 <navigator>
组件跳转到指定的 tabBar 页面时,需要指定 url 属性和 open-type 属性。
- url 表示要跳转的页面的地址 必须以 / 开头
- open-type 表示跳转的方式 如果是 tabBar 页面 必须为 switchTab
<navigator url="/pages/index/index" open-type="switchTab">跳转首页</navigator> |
# 跳转到非 tabBar 页面
意思是没有被配置 tabBar 的页面
只需要将属性 open-type 设置为 navigate 即可
实际上不加也行,open-type 的默认值就是 navigate
<navigator url="/pages/info/info" open-type="navigate">跳转info页面</navigator> |
# 后退导航
如果要后退到上一页面或多级页面,则需要指定 open-type 属性 和 delta 属性
- open-type 的值必须是 navigateBack 表示进行后退导航
- delta 的值必须是数字,表示后退的层级
<navigator open-type="navigateBack" delta="1">返回上一级</navigator> |
也可以省略 delta 属性 ,默认值就是 1
# 编程式导航
# 跳转到 tabBar 页面
通过 wx.switchTab(Object Object)
方法,可以跳转到 tabBar 页面。其中 Object 参数对象的属性列表如下
其中 url 参数是必填,其他是可选
属性 | 类型 | 说明 |
---|---|---|
url | String | 需要跳转的 tabBar 页面的路径,路径后不能携带参数 |
success | function | 接口调用成功的回调函数 |
fail | function | 接口调用失败的回调函数 |
complete | function | 接口调用结束的回调函数 (调用成功,失败都会执行) |
<button bindtap="gotoIndex">跳转到首页</button> |
// 跳转到首页 | |
gotoIndex() { | |
wx.switchTab({ | |
url: '/pages/index/index' | |
}) | |
}, |
# 跳转到非 tabBar 页面
调用 wx.navigateTo(Object Object
方法,object 参数对象和上一个一样,就不做演示了
# 后退导航
一样的,懒得说了 换成 wx.navigateBack()
就行 不过是 url 换成了 delta 而已
backOne() { | |
wx.navigateBack({ | |
delta: 1, | |
}) | |
}, |
# 导航传参
- 声明式导航传参
- 参数与路径之间使用?分格
- 参数键与参数值用 = 相连
- 不同参数用 & 分格
<navigator url="/pages/info/info?name=zs&age=20" open-type="navigate">跳转info页面</navigator> |
编程式导航也是一样的
在 onLoad 中接收导航传参
通过声明式导航传参和编程式导航传参所携带的参数,可以直接在 onLoad 事件中直接获取到
/** | |
* 生命周期函数 -- 监听页面加载 | |
*/ | |
onLoad(options) { | |
console.log(options); | |
}, |
# 页面事件
# 下拉刷新事件
就是手指在屏幕的下拉滑动操作,从而重新加载页面数据
全局开启下拉刷新
在 app.json 的 window 节点中将 enablePullDownRefresh 设置成 true 就行局部开启下拉刷新
在对应的 json window 节点中设置就行 推荐使用第二种方式
- 监听页面的下拉刷新事件
在页面的.js 文件中,通过 onPullDownRefresh()
函数即可监听当前的下拉刷新事件
onPullDownRefresh() { | |
console.log("触发了demo页面的下拉刷新"); | |
}, |
- 停止下拉刷新的效果
当处理完下拉刷新后,loading 效果会一直显示,不会主动消失,调用 wx.stopPullDownRefresh()
就可以停止当前页面的下拉刷新
onPullDownRefresh() { | |
this.setData({ | |
number: this.data.number + 1 | |
}) | |
console.log("触发了demo页面的下拉刷新"); | |
wx.stopPullDownRefresh() | |
}, |
# 上拉触底事件
通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为
- 监听页面的上拉触底事件
在页面的.js 文件中,通过 onReachBottom()
函数即可监听当前页面的上拉触底事件
- 配置上拉触底距离
触发上拉触底事件时,滚动条距离页面底部的距离
可以在.json 文件中 通过 onReachBottomDistance
来配置触底的距离 默认为 50px
- 添加 loading 提示效果
wx.showLoading () 可以显示 loading 提示框效果
wx.hideLoading () 关闭提示效果
getColors() { | |
wx.showLoading({ | |
title: '数据加载中...', | |
}) | |
wx.request({ | |
url: 'https://www.escook.cn/api/color', | |
method: "GET", | |
success: (res) => { | |
this.setData({ | |
colorList: [...this.data.colorList, ...res.data.data] | |
}) | |
}, | |
complete: () => { | |
wx.hideLoading() | |
} | |
}) | |
}, |
# 生命周期
指一个对象从 创建 -> 运行 -> 销毁 的整个阶段,强调的是一个时间段
- 应用的生命周期函数
小程序的生命周期函数需要在 app.js 中进行申明
App({ | |
// 小程序初始化完成时,执行此函数,全局只触发一次,可以做初始化的工作 | |
onLaunch(options) {}, | |
// 小程序启动。或从后台进入前台显示时触发 | |
onShow(options) {}, | |
// 小程序从前台进入后台时触发 | |
onHide(){} | |
}) |
- 页面的生命周期函数
小程序的页面生命周期函数需要在页面的.js 文件中进行声明
Page({ | |
onLoad(options){} // 监听页面加载,一个页面只调用一次 | |
onShow(){} // 监听页面显示 | |
onReady(){} // 监听页面初次渲染完成,一个页面只调用一次 | |
onHide(){} // 监听页面隐藏 | |
onUnload(){} // 监听页面卸载,一个页面只调用一次 | |
}) |
# WXS 脚本
wxs 代码可以编写在 wxml 文件的 <wxs>
标签中,就好像 html 中的 <script>
标签内一样
- 内嵌 wxs 脚本
wxml 文件中的每个标签,必须提供 module 属性 ,用来指定当前 wxs 的模块名称 方便 wxml 中访问模块中的成员
<view>{demo.toUpper("zs")}</view> | |
<wxs module="demo"> | |
// 将文本转为大写 如 zs=> ZS | |
module.exports.toUpper = function (str) { | |
return str.toUpperCase() | |
} | |
</wxs> |
一般用来当过滤器来使用
- 定义外联的 wxs 脚本
就好像 javascript 可以编写在.js 后缀的文件中...
//tools.wxs 文件 | |
// 字母小写 | |
function toLower(str){ | |
return str.toLowerCase() | |
} | |
module.exports = { | |
toLower: toLower | |
} |
- 使用外联的 wxs 脚本
- module 用来指定模块的名称
- src 用来指定要引入的脚本路径,必须是相对路径
<view> {m2.toLower("LS")}</view> | |
<wxs src="../../utils/tools.wxs" module="m2"></wxs> |
# 自定义组件
# 组件的创建于引用
- 创建组件
- 在根目录创建
components
文件 - 右键新建 component 会自动生成组件对应的 4 个文件 .js .json .wxml .wxss
- 在根目录创建
- 引用组件
在 .json 配置文件中引用即可,全局配置在app.json
"usingComponents": { | |
"my-test": "/components/test/test" | |
}, |
- 组件与页面的区别
- 组件中需要声明
"component": true,
- 组件的方法需要定义在
methods
节点中
# properties 属性
类似 vue 中的 prop
Component({ | |
properties: { | |
// 完整写法 | |
number: { | |
type: Number, // 数据类型 | |
value: 0 // 属性默认值 | |
}, | |
// 简写 | |
number: Number | |
}, | |
}) |
父组件传参
<my-test number="20"></my-test> | |
<my-test number="{num}"></my-test> |
# 组件的生命周期
- created: 组件实例刚刚被创建时执行
- attached: 组件实例进入页面节点数时执行
- ready: 组件在视图层布局完成后执行
- moved: 组件实例被移动到节点树另一个位置时执行
- detached: 组件实例被从页面节点树移除时执行
- lifetimes 节点
在小程序中生命周期可以定义在lifetimes
内进行声明
lifetimes: { | |
created() {}, | |
attached() {} | |
}, |
- pageLifetimes 节点
组件所在页面的生命周期函数
pageLifetimes: { | |
// 页面被展示 | |
show() {}, | |
// 页面被隐藏 | |
hide() {}, | |
// 页面尺寸变化 | |
resize() {} | |
}, |
# 数据监听器
类似 vue 中的 watch 侦听器 ,用于监听和响应任何属性和数字字段的变化,从而执行特定的操作。
// 监听器 | |
observers: { | |
// 单个 | |
'number': function (val) { | |
console.log(val); | |
}, | |
// 多个 | |
'num1,num2':function(num1,num2){ | |
console.log(num1,num2); | |
} | |
}, |
监听对象属性的变化
observers: { | |
'object.num1,object.num2':function(num1,num2){ | |
// do something | |
} | |
}, |
# 插槽
可以提供一个 <slot>
节点 用于承载组件使用者提供的 wxml 结构
- 启用多个插槽
在自定义组件中,需要使用多个 <slot>
插槽时,可以在.js 文件中通过以下方法打开
Component({ | |
options: { | |
// 在组件定义时的选项中启动多个 slot | |
multipleSlots: true | |
}, | |
}) |
- 定义多个插槽
使用不同的 name 来区分不同的插槽
<view class="container"> | |
<slot name="left"></slot> | |
<slot name="right"></slot> | |
</view> |
- 使用多个插槽
<pinkBox> | |
<view class="www" slot="right"></view> | |
<view class="www" slot="left"></view> | |
</pinkBox> |
# 父子组件之间的通信
# 父子组件之间通信的 3 种方式
- 属性绑定
- 用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容的数据
- 事件绑定
- 用于子组件向父组件传递数据,可以传递任意数据
- 获取组件实例
- 父组件可以通过
this.selectComponent()
获取子组件实例对象 - 这样就可直接访问子组件的任意数据和方法
# 属性绑定
属性绑定用于实现父向子传值,而且只能传递普通类型的数据,无法将方法传递给子组件。
<!-- 父组件的 data 节点 --> | |
data:{ | |
count:0 | |
} | |
<!-- 父组件的 wxml 结构 --> | |
<test count="{ count }"></test> |
子组件在 properties 节点中声明对应的属性并使用
// 子组件的 properties 节点 | |
properties: { | |
// 完整写法 | |
count: { | |
type: Number, // 类型 | |
value: 0 // 默认值 | |
} | |
// 简写 | |
count:Number | |
}, | |
// 子组件的 wxml 结构 | |
<text> | |
<!--swig0--> | |
</text> |
# 事件绑定
事件绑定用于实现子向父传值,可以传递任何类型的数据
- 在父组件的 js 中定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件
syncCount(e) { | |
console.log('syncCount'); | |
}, |
- 在父组件中的 wxml 中,通过自定义事件的形式,将步骤 1 中定义的函数引用,传递给子组件
<pinkBox num="{num}" bind:sync="syncCount"> |
- 在子组件的 js 中,通过调用 this.triggerEvent (' 自定义事件名称 ',{参数对象}),将数据发送到父组件
addNum() { | |
this.setData({ | |
num: this.properties.num + 1 | |
}) | |
// 触发自定义事件,将数值同步给父组件 | |
this.triggerEvent('sync', this.properties.num) | |
} |
- 在父组件的 js 中,通过
e.detail
获取到子组件传递过来的数据
syncCount(e) { | |
console.log('syncCount'); | |
console.log(e.detail) | |
}, |
# 获取组件实例
可以在父组件里调用 this.selectComponent("id或class选择器")
, 获取子组件的实例对象,从而直接访问子组件的任意数据和方法
// 父组件 wxml 结构 | |
<test num="{num}" bind:sync="syncCount" class="customA"></test> | |
<button bindtap="getChild">获取子组件实例</button> | |
// js | |
getChild() { | |
const child = this.selectComponent('.customA') | |
child.setdata({ count:child.properties.num }) // 调用子组件的 setData 方法 | |
child.addNum() // 调用子组件的 addNum 方法 | |
}, |
# behaviors
用于实现组件之间代码共享的特性,类似 vue 中的 mixins
每个 behavior 可以包含一组 属性,数据,生命周期函数和方法。 组件引用它时,它的属性,数据和方法会被合并到组件中。
每个组件可以引用多个 behavior , behavior 也可以引用其他的 behavior
- 创建 behavior
调用 Behavior (object object) 方法即可创建一个共享的 behavior 实例对象 供所有的组件使用
module.exports = Behavior({ | |
data: { | |
username: 'zs' | |
}, | |
properties: { | |
}, | |
methods: { | |
} | |
}) |
- 导入并使用 behavior
在组件中,使用 require()
方法导入需要的 behavior,挂在后即可访问 behavior 中的数据和方法
const myBehavior = require("../behaviors/my-behavior") | |
Component({ | |
behaviors: [myBehavior], | |
}) | |
// wxml | |
<view> behavior中定义的用户名:<!--swig1--></view> |
# API Promise 化
在小程序中,实现 API Promise 化主要依赖于 miniprogram-api-promise
第三方的 npm 包。
npm i -s miniprogram-api-promise
然后在小程序入口文件 app.js 只需要调用一次 promisefyAll () 方法,即可实现异步 API 的 Promise 化
//app.js | |
import {promisifyAll} from 'miniprogram-api-promise' | |
const wxp = wx.p = {} | |
promisifyAll(wx, wxp) |
调用 promise 化的异步 api
async getMsg() { | |
const {data: res} = await wx.p.request({ | |
url: 'https://www.escook.cn/api/get', | |
data: { | |
name: 'zs', | |
age: 20 | |
}, | |
}) | |
console.log(res.data); | |
}, |
# 全局数据共享
为了解决组件之间数据共享的问题 类似 vuex
小程序中的全局数据共享方案
在小程序中可以使用 mobx-miniprogram
配合 mobx-miniprogram-bindings
实现全局数据共享
- mobx-miniprogram 用来创建 Store 实例对象
- mobx-miniprogram-bindings 用来把 Store 中的共享数据或方法,绑定到组件或页面中使用
- 安装 MobX 相关的包
npm i mobx-miniprogram mobx-miniprogram-bindings
- 在项目根目录创建 store 文件
// store\store.js | |
// 在这个 js 文件中 专门来创建 Store 的实例对象 | |
import { | |
observable, | |
action | |
} from 'mobx-miniprogram' | |
export const store = observable({ | |
// 数据字段 | |
numA: 1, | |
numB: 2, | |
// 计算属性 | |
get sum() { | |
return this.numA + '!!!' | |
}, | |
//actions 方法 专门用来修改 store 中的值 | |
updateNumA: action(function (step) { | |
this.numA += step | |
}) | |
}) |
- 将 Store 中的成员绑定到页面中
// 页面的 .js 文件 | |
// 导入需要的成员 | |
// 通过此方法可以将 store 中的数据或者方法绑定到当前页面中 | |
import {createStoreBindings} from 'mobx-miniprogram-bindings' | |
// | |
import {store} from '../../store/store' | |
Page({ | |
// 在生命周期函数中进行绑定工作 | |
onLoad: function (options) { | |
this.storeBindings = createStoreBindings(this, { | |
store, | |
fields: ['numA', 'numB', 'sum'], // 需要的数据 | |
actions: ['updateNumA'] // 需要的方法 | |
}) | |
}, | |
// - 监听页面卸载 中做清理的工作 | |
onUnload: function () { | |
this.storeBindings.detoryStoreBindings() | |
}, | |
}) |
- 在页面上使用 Store 中的成员
<view><!--swig2--></view> | |
<view><!--swig3--></view> | |
<view><!--swig4--></view> | |
<button bindtap="bindHandler" data-step="1">num+1</button> | |
// js | |
bindHandler(e) { | |
this.updateNumA(e.target.dataset.step) | |
}, |
5. 将 Store 中的成员绑定到组件中
// components/test/test.js | |
import {storeBindingsBehavior} from 'mobx-miniprogram-bindings' | |
import {store} from '../../store/store' | |
Component({ | |
/** | |
* 组件的属性列表 | |
*/ | |
behaviors: [storeBindingsBehavior], // 通过 storeBindingsBehavior 来实现自动绑定、 | |
storeBindings: { | |
store, | |
fields: { // 指定需要绑定的字段数据 | |
numA: () => store.numA, // 绑定字段的 第 1 种方式 | |
numB: (store) => store.numB, // 绑定字段的 第 2 种方式 | |
sum: 'sum' // 绑定字段的 第 3 种方式 | |
}, | |
actions: { // 指定要绑定的方法 | |
updateNumA: 'updateNumA' | |
}, | |
}, | |
}) |
6. 在组件中使用
<view class="containerBox"> | |
<!--swig6--> | |
<button bindtap="numAdd" data-step="1">+1</button> | |
</view> | |
// js | |
numAdd(e) { | |
console.log(e); | |
this.updateNumA(e.target.dataset.step) | |
} |
# 分包
指把一个完整的小程序项目,按需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载,
# 使用分包
- 配置方法
开发者通过在 app.json subpackages
字段声明项目分包结构:
{ | |
"pages":[ | |
"pages/index", | |
"pages/logs" | |
], | |
"subpackages": [ | |
{ | |
"root": "packageA", // 分包根目录 | |
"pages": [ // 分包页面路径,相对于分包根目录 | |
"pages/cat", | |
"pages/dog" | |
] | |
}, { | |
"root": "packageB", | |
"name": "pack2", | |
"pages": [ | |
"pages/apple", | |
"pages/banana" | |
] | |
} | |
] | |
} |
- 引用原则
- 主包无法引用分包内的私有资源
- 分包之间不能相互引用私有资源
- 分包可以引用主包内的公共资源
# 独立分包
独立分包本质上也是分包,但是可以独立于主包和其他分包而单独运行
- 独立分包和普通分包的区别
- 普通分包必须依赖于主包才能运行
- 独立分包可以在不下载主包的情况下独立运行
- 独立分包配置方法
与普通分包相同,只需在 subpackages
字段中对应的分包配置项中定义 independent
字段声明对应分包为独立分包。
"subpackages": [ | |
{ | |
"root": "moduleA", | |
"pages": [ | |
"pages/rabbit", | |
"pages/squirrel" | |
] | |
}, { | |
"root": "moduleB", | |
"pages": [ | |
"pages/pear", | |
"pages/pineapple" | |
], | |
+ "independent": true | |
} | |
] |
- 引用原则
独立分包和普通分包以及主包之间是相互隔绝的,不能相互引用彼此的资源,独立分包也不能引用主包内的公共资源。
# 分包预下载
指在进入小程序的某个页面,由框架自动预下载可能需要的分包,从而提高进入后续分包页面的启动速度
- 配置分包预下载
预下载分包行为在进入某个页面时触发,通过在 app.json
增加 preloadRule
配置来控制。
"preloadRule": { // 分包预下载的规则 | |
"pages/index": { // 触发分包预下载的页面路径 | |
"network": "all", // 表示在指定的网络模式下进行预下载,all (不限网络) 和 wifi | |
"packages": ["important"] //package 表示进入页面后预下载哪些分包 | |
}, | |
"sub1/index": { | |
"packages": ["hello", "sub3"] | |
}, | |
"sub3/index": { | |
"packages": ["path/to"] | |
}, | |
"indep/index": { | |
"packages": ["__APP__"] | |
} | |
} |