小程序基本了解
小程序与普通网页的区别
运行环境不同
- 网页运行在浏览器环境中
- 小程序运行在微信环境中
API不同
- 运行环境不同,这也就导致小程序无法调用DOM和BOM的API。
- 但是可以调用微信环境中提供的各种API
开发模式不同
- 网页的开发模式:浏览器 + 代码编辑器
- 小程序: 申请小程序开发者账号,安装小程序开发者工具,创建和配置小程序项目
小程序项目结构
|-- project_02 // 根目录
|-- .eslintrc.js // eslint配置
|-- app.js // 小程序入口文件
|-- app.json // 全局配置文件
|-- app.wxss // 全局样式文件
|-- project.config.json // 项目配置文件
|-- project.private.config.json // 项目私有配置文件 会覆盖 project.config.json相同字段
|-- sitemap.json // 配置页面能否被微信索引
|-- pages // 存放页面的文件夹
| |-- index
| | |-- index.js // 页面js文件(存放页面数据,事件处理函数等)
| | |-- index.json // 页面配置文件(配置页面窗口外观,表现)
| | |-- index.wxml // 页面模板文件
| | |-- index.wxss // 页面样式文件
| |-- logs
| |-- logs.js
| |-- logs.json
| |-- logs.wxml
| |-- logs.wxss
|-- utils // 存放工具函数的文件夹
|-- util.js
小程序配置文件
- app.json
全局页面配置文件,配置页面的窗口,页面的路径等
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle":"black"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
pages节点 ---> 小程序的页面路径,在此配置会默认生成页面的目录结构
window节点 ---> 配置页面的背景色,文字颜色等,全局生效
style节点 ---> 定义小程序组件使用的样式版本
sitemapLocation节点 --> 指定sitemap.json的位置
- project.config.json
项目的配置文件,用来配置跟项目相关的配置
setting节点 ---> 定义编译相关的配置
projectname ---> 配置项目的名称
appid ---> 配置小程序的appid
- sitemap.json
配置页面是否被微信搜索到。
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow", // 允许索引 disallow 不允许索引
"page": "*" // * 表示所有的页面
}]
}
在项目配置文件peoject.config.json中的setting节点添加 "checkSiteMap": false, 可以隐藏掉索引情况提示信息
- 页面的 .json文件
可以对当前页面的窗口外观样式进行配置
覆盖全局的app.json中window节点下的配置
小程序代码构成
如何创建一个页面
- 直接在app.json里边的pages节点下新增页面的路径,项目会自动创建对应的页面目录
- 在pages文件夹右键,新建文件夹,右键新建的文件夹,新建page,输入页面名后会自动生成页面需要的文件,此时app.json的pages节点也会自动添加这个页面路径
修改首页对应的页面
只需要将pages节点中的路径位置调整一下顺序,第一个就表示首页的页面
wxml和html的区别
标签名称不同
- html(div, span, a, img)
- wxml(view, text, navigator, image)
属性不同
- <a href="#">
- <navigator url="/pages/home/home"></navigator>
支持类似于vue的模板语法
- 数据绑定
- 列表渲染
- 条件渲染
wxss和css的区别
新增rpx单位
- css中需要手动对像素px进行换算,例如:rpx单位
- rpx则可以在不同尺寸的屏幕上自动进行换算
提供了全局样式和局部样式
- app.wxss全局样式会作用于所有的页面
- 局部页面的 .wxss 样式只针对于当前页面的样式
小程序中的js文件
app.js
- 是整个小程序的入口文件,通过调用App()函数启动小程序
页面的 .js文件
- 是页面的入口文件,通过调用Page()函数创建并运行页面
普通的 .js文件
- 普通的功能函数模块,封装一些公用的函数或者属性,供其他页面使用
小程序中的组件
小程序组件分类
- 视图容器
- 基础内容
- 表单组件
- 导航组件
- 媒体组件
- map地图组件
- canvas画布组件
- 开放能力
- 无障碍访问
常用的视图容器组件
view组件
- 类似于div,用来布局
scroll-view组件
- 可以滚动的div,用来实现列表滚动
swiper和swiper-item组件
- 轮播图容器(swiper)和里边的每一项轮播图(swiper-item),用来实现轮播图
常用的基础内容组件
text组件
- 普通的文本组件,类似于span
rich-text
- 富文本组件,支持html字符串转换成wxml结构
<text>13213212</text>
<rich-text nodes="<h1>12313</h1>"></rich-text>
其他常用的组件
button组件
- 按钮组件,更丰富的功能,可通过open-type属性调用微信的功能(客服,转发,用户授权等)
image组件
- 图片组件,存放图片的容器
navigator组件
- 页面导航组件,类似于a
小程序中的api
事件监听api
- 以on开头,监听某个事件
- 例如:wx.onWindowResize(() => {}) 监听窗口尺寸的变化
同步api
- 以Sync结尾,可以直接接受函数返回值
- 例如:wx.setStorageSync('key', 'value') 本地存储
异步的api
- 不带Sync的api,需要通过success fail compalete接收
- 例如:wx.request()发送一个网络请求 需要通过success回调函数接收数据
小程序语法
数据绑定,mustache语法
// js
Page({
data: {
// 在这里进行数据绑定
num: 1,
src: 'http://wwjjds.com/1.png'
}
})
// wxml
在wxml模板中 使用mustache语法进行渲染 双大括号的形式
// 绑定内容
<view>{{ num }}</view>
// 绑定属性
<image src="{{ src }}"></image>
// 表达式
<view>{{ num > 1 ? '大于1' : '小于等于1' }}</view>
// 算术运算
<view>{{ num * 100 }}</view>
事件绑定
tap点击事件 bindtap 或者bind:tap
input文本框输入事件 bindinput 或者bind:input
change状态改变时触发 bindchange 或者bind:change
事件对象的属性(event)
属性 | 类型 | 说明 |
---|---|---|
type | String | 事件类型 |
timeStamp | Integer | 页面打开到触发这个事件经过的时间,毫秒数 |
targer | Object | 触发事件的组件的一些属性值集合 |
currentTarger | Object | 当前组件的一些属性值集合 |
detail | Object | 额外的一些信息 |
touches | Array | 触摸事件,当前停留在屏幕上的触摸点信息数组 |
changedTouches | Array | 触摸事件,当前变化的触摸点信息数组 |
target
- target指的是事件触发的源头
currentTarget
- currentTarget指的是正在触发的那个元素
// js
Page({
tapHandler(e) {
console.log(e, 'event');
}
})
<!-- wxml -->
<view class="mine-container" data-count="{{ 2 }}" bindtap="tapHandler">
<button type="primary" data-num="{{ 1 }}">按钮</button>
</view>
点击按钮,此时事件向上冒泡,e.target指的就是这个button按钮,即事件触发的源头,可以从e. target . dataset. num 拿到num值。
e.currentTarget是正在触发事件的那个元素 view,可以e. currentTarget. dataset. count拿到count值
为data进行赋值
调用this.setData()函数为data中的属性进行赋值操作
btnClick (e) {
console.log(e);
// 修改data中的数据
this.setData({
// 要修改的属性 : 修改的值 通过this.data拿到data中的数据
num: this.data.num + 1
})
},
事件传参
通过在wxml模板上绑定属性,绑定方式为 data-*,在事件对象中通过e. target. dataset对象拿到对应的属性
// js
Page({
tapHandler(e) {
console.log(e, 'event');
console.log(e.target.dataset.num) // button绑定的属性data-num
}
})
<!-- wxml -->
<view class="mine-container" data-count="{{ 2 }}" bindtap="tapHandler">
<button type="primary" data-num="{{ 1 }}">按钮</button>
</view>
input事件
bindinput进行绑定 通过e.detail.value拿到最新的值
// js
Page({
data: {
inputValue: ''
},
inputChange(e) {
console.log(e.detail.value); // 文本框中的值
this.setData({
inputValue: e.detail.value // 实现双向绑定 修改文本框数据 data中的数据也一并修改
})
},
})
<!-- wxml -->
<input value="{{ inputValue }}" bindinput="inputChange"/>
条件渲染
- wx:if
- wx:elif
- wx:else
// js
Page({
data: {
sex: 1
}
})
<!-- wxml -->
<view wx:if="{{ sex === 1 }}">男</view>
<view wx:elif="{{ sex === 0 }}">女</view>
<view wx:else> 未知 </view>
结合block标签进行条件渲染,block标签不会渲染到页面中,只是起到了包裹的作用
<!-- wxml -->
<block wx:if="{{ true }}">
<view>view1</view>
<view>view2</view>
</block>
<view wx:if="{{ true }}">
<view>view1</view>
<view>view2</view>
</view>
- hidden
<view hidden="{{ true }}">hidden隐藏</view>
wx:if和hidden的区别
hidden 通过display: none进行隐藏,wx:if会创建或者移除该元素
列表渲染
wx:for
默认索引是index,数据项是item
通过属性 wx:for-index="" 修改对应的索引变量
通过属性 wx:for-item="" 修改对应的数据项变量
通过wx:key提高渲染效率,不需要mustache语法,索引index,如果每一项有id的话直接写id属性
// js
Page({
data: {
list: [
{id: 1, name: '苹果'},
{id: 2, name: '草莓'},
{id: 3, name: '鸭梨'}
]
}
})
<!-- wxml -->
<text>------------列表渲染------------</text>
<view wx:for="{{ list }}" wx:key="id">
<text>名称:{{ item.name }}</text>
<view>索引:{{ index }}</view>
</view>
<text>------------列表渲染 自定义index和item------------</text>
<view wx:for="{{ list }}" wx:key="id" wx:for-index="ind" wx:for-item="ite">
<text>名称:{{ ite.name }}</text>
<view>索引:{{ ind }}</view>
</view>
rpx单位
适配不同屏幕尺寸
rpx实现原理:
- rpx把所有设备屏幕划分为750份,即宽度为750rpx,在小屏幕上,1rpx宽度较小,在大屏幕上,宽度较大。
- 小程序在运行时,会把rpx单位的样式换成对应的px单位,实现屏幕的适配。
设备 | 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 |
iPhone6 屏幕宽度 375px 物理像素750,rpx等分750物理像素
即 1rpx = 1物理像素 = 0.5px
一般会采用iPhone6设计稿, rpx是整数
小程序全局配置
app.json全局配置文件
常用配置项节点
pages
- 配置小程序的页面
window
- 配置页面窗口外观
tabBar
- 设置小程序的tabBar
style
- 小程序组件使用的样式版本号(v2)最新版
window节点
小程序窗口可以分为三类:
navigationBar
- 导航栏区域
background
- 背景区域,下拉刷新时可见
wxml
- 页面的主体布局区域
常用的window属性
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
navigationBarTitleText | String | 字符串 | 导航栏标题文本内容 |
navigationBarBackgroundColor | HexColor | #000000 | 导航栏背景色,16进制颜色 |
navigationBarTextStyle | String | white | 导航栏标题颜色,仅支持white/black |
backgroundColor | HexColor | #ffffff | 窗口背景色,下拉才会显示 |
backgroundTextStyle | String | dark | 下拉loding的样式,仅支持dark/light |
enablePullDownRefresh | Boolean | false | 是否开启全局下拉刷新 |
onReachBottomDistance | Number | 50 | 上拉触底事件距离页面底部的距离,单位px |
tabBar节点
tabBar两种:底部tabBar,顶部tabBar
tabBar至少要配置两项,最多五个
顶部的yabBar不会显示icon图标,只显示文本
tabBar属性
属性 | 类型 | 必填 | 默认值 | 说明 |
---|---|---|---|---|
position | String | 否 | bottom | tabBar位置 仅支持bottom/top |
borderStyle | String | 否 | black | tabBar上边框的颜色 仅支持black/white |
color | HexColor | 否 | tabBar文本,未选中时的颜色 | |
selectedColor | HexColor | 否 | tabBar文本,选中时的颜色 | |
backgroundColor | HexColor | 否 | tabBar的背景色 | |
list | Array | 是 | tabBar的列表,最少两个,最多五个 |
list数组对象
pagePath
- tab对应的页面路径
text
- tab对应的文本
iconPath
- tab对应的图标
selectedIconPath
- tab选中时的图标
// // app.json
{
"pages": [
"pages/mine/mine",
"pages/index/index",
"pages/logs/logs",
"pages/home/home"
],
"window": {
"backgroundColor": "#f0f0f0", // 下拉窗口背景色 16进制颜色
"backgroundTextStyle": "dark", // 下拉小圆点的样式 dark / light
"navigationBarBackgroundColor": "#ff00ff", // 导航栏背景色 16进制颜色
"navigationBarTitleText": "我的小程序", // 导航栏标题文本
"navigationBarTextStyle": "white", // 导航栏标题文本样式 仅支持white/black
"enablePullDownRefresh": true, // 是否开启下拉刷新 全局生效
"onReachBottomDistance": 100 // 上拉触底事件,距离底部的距离 100px
},
"tabBar": {
"position": "bottom", // tab位置 bottom/top
"color": "#000", // tab未选中的文本颜色
"selectedColor": "#f12f00", // tab选中的文本颜色
"backgroundColor": "#f0f0f0", // tab背景色
"list": [ // tab页签选项列表
{
"pagePath": "pages/mine/mine", // tab对应的页面路径
"text": "mine", // tab对应的文本
"iconPath": "", // tab对应的图标
"selectedIconPath": "" // tab选中时的图标
},
{
"pagePath": "pages/index/index",
"text": "index",
"iconPath": "",
"selectedIconPath": ""
},
{
"pagePath": "pages/logs/logs",
"text": "logs",
"iconPath": "",
"selectedIconPath": ""
}
]
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
小程序网络请求
小程序网络请求的限制
- 只能请求https类型的接口
- 接口域名必须要添加到信任列表中(微信公众平台)
如何去配置合法接口域名
打开微信公众平台 --- 开发 --- 开发管理 --- 开发设置 --- 服务器域名
使用wx.request()发起网络请求
Page({
onLoad(options) {
this.getLoop() // 页面加载之后就会调用
this.onLogin()
},
// 发送get请求
getLoop() {
wx.request({
url: 'https://www.wrz521.top:8080/api/getLoopArt', // 请求地址
method: 'GET', // 请求方法
data: {}, // 传递的数据
success(res) { // 成功后的回调
console.log(res.data, '请求结果');
},
})
},
// 发送post请求
onLogin() {
wx.request({
url: 'https://www.wrz521.top:8080/api/login',
method: 'POST',
data: {
username: 'admin',
password: '123456789'
},
success(res) {
console.log(res.data, '请求结果');
}
})
},
})
跨域和ajax
小程序不存在跨域,不是运行在浏览器上的。
ajax依赖于浏览器xhr对象,小程序是依赖微信客户端,不能说是ajax请求,只能说网络数据请求
小程序页面导航
页面导航的两种方式
声明式导航
- 使用navigator组件, 点击navigator组件实现页面跳转
- 跳转tabBar页面 需要指定open-type属性为 switchTab
- 跳转到非tabBar页面 需要指定open-type为navigate
编程式导航
- 调用小程序的导航api进行跳转
- 跳转tabBar页面 使用wx.switchTab()
- 跳转到非tabBar页面 使用wx.navigatorTo()
跳转到tabBar页面
声明式导航:
<!-- wxml -->
<navigator url="/pages/index/index" open-type="switchTab">
点击 跳转到tab index页面
</navigator>
编程式导航:
wx.switchTab()
Page({
goTabIndex() {
wx.switchTab({
url: '/pages/index/index',
success(res) { // 成功回调
console.log(res, 'success');
},
fail(err) { // 失败回调
console.log(err, 'fail');
},
complete(res) { // 成功或失败都会调用
console.log(res, 'complete');
}
})
}
})
跳转到非tabBar页面
声明式导航:
<!-- wxml -->
<navigator url="/pages/home/home" open-type="navigate">点击 跳转到非tab home页面</navigator>
编程式导航:
wx.navigateTo()
Page({
goPageHome() {
wx.navigateTo({
url: '/pages/home/home',
success(res) { // 成功回调
console.log(res, 'success');
},
fail(err) { // 失败回调
console.log(err, 'fail');
},
complete(res) { // 成功或失败都会调用
console.log(res, 'complete');
}
})
},
})
后退导航
声明式导航
- 使用组件时 指定 open-type属性为navigateBack delta属性为 后退的层级,是一个数字
编程时导航
- 使用wx.navigateBack()
声明式导航
<!-- wxml -->
<navigator open-type="navigateBack" delta="1">后退</navigator>
编程式导航
wx.navigateBack()
Page({
goPageHome() {
wx.navigateBack({
delta: 1, // 返回的层级
success(res) { // 成功回调
console.log(res, 'success');
},
fail(err) { // 失败回调
console.log(err, 'fail');
},
complete(res) { // 成功或失败都会调用
console.log(res, 'complete');
}
})
},
})
导航传参
声明式导航
- 在url的链接中以查询字符串的形式携带
- url链接和参数之间 ? 隔开
- 多个参数之间 & 隔开
编程式导航
- 在url的链接中以查询字符串的形式携带
- url链接和参数之间 ? 隔开
- 多个参数之间 & 隔开
获取携带的参数
- 在onLoad(options)生命周期函数中,options就是携带的参数对象
// wxml
<navigator url="/pages/home/home?age=18&name=zs" open-type="navigate">
点击 跳转到非tab home页面
</navigator>
// mine.js
Page({
goPageHome() {
wx.navigateTo({
url: '/pages/home/home?name=zs&age=18',
success(res) {
console.log(res, 'success');
},
fail(err) {
console.log(err, 'fail');
},
complete(res) {
console.log(res, 'complete');
}
})
},
})
// home.js
Page({
onLoad(options) {
console.log(options) // 页面参数 {name: zs, age: 18}
}
})
小程序页面事件
下拉刷新事件
onPullDownRefresh()
开启下拉刷新
- app.json 设置 window节点 设置enablePullDownRefresh: true,全局生效
- 页面的json 设置enablePullDownRefresh: true,只有当前这个页面生效(建议)
监听页面的onPullDownRefresh事件
- 下拉刷新会触发
- 需要手动调用wx.stopPullDownRefresh()停止下拉刷新
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
console.log('页面刷新了');
wx.stopPullDownRefresh({
success(res){
console.log(res, '停止下拉刷新了');
}
})
},
上拉触底事件
onReachBottom()
设置上拉触底距离
- app.json window节点配置 onReachBottomDistance: 100 距离底部100px的位置触发上拉触底事件
监听页面的onReachBottom事件
- 上拉到指定位置会触发该事件
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
console.log('上拉触底了');
},
滑动页面事件
onPageScroll(Object object)
参数Object object
scrollTop
- 页面在垂直方向已滚动的距离(单位px)
点击右上角菜单‘收藏’按钮
onAddToFavorites(Object object)
参数Object object
webViewUrl
- 页面如果包含web-view组件时,会返回web-view的url
该事件需要 return一个Object,用来自定义收藏内容
Object
title
- 自定义标题,默认页面标题或者账号名称
imageUrl
- 自定义图片,默认页面截图
query
- 自定义query字段,默认当前页面的query
更多
官方文档:https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html
小程序生命周期
什么是生命周期
一个对象从创建到销毁的过程就是他的生命周期
小程序生命周期
小程序生命周期可以分为两类:
应用生命周期
- 小程序从启动 --> 运行 --> 销毁的过程
页面的生命周期
- 小程序每个页面从加载 --> 渲染 --> 销毁的过程
其中页面的生命周期范围小,应用生命周期范围大,两者包含关系
小程序启动 --> 页面A生命周期 --> 页面B生命周期 --> ... --> 小程序结束
生命周期函数
生命周期函数会伴随着生命周期,自动依次调用执行。
允许我们在某个特定的时间段,做一些操作,例如在页面加载的时候,初始化页面的数据,此时就需要onLoad生命周期函数。
应用生命周期函数
需要在app.js中调用App(Object object)函数,指定小程序应用的生命周期回调
onLaunch
- 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
onShow
- 当小程序启动,或从后台进入前台显示,会触发 onShow
onHide
- 当小程序从前台进入后台,会触发 onHide
onError
- 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
onPageNotFound
- 当页面不存在时触发
onUnhandledRejection
- 有未处理的promise,reject事件时触发
onThemeChange
- 系统主题变化时触发
其他
- 可以添加任意的函数或者数据变量,全局使用,通过this进行调用
// app.js
App({
onLaunch: function () {},
onShow: function (options) {},
onHide: function () {},
onError: function (msg) {},
globalData: { // 可以定义全局的数据或者函数,通过this进行调用
userInfo: null
}
})
页面生命周期函数
需要在页面的 .js中调用Page(Object object)函数,指定页面的生命周期回调
onLoad
- 页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数
onShow
- 页面显示/切入前台时触发
onReady
- 页面初次渲染完成时触发。一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互
onHide
- 页面隐藏/切入后台时触发。如 wx.navigateTo 或底部tab切换到其他页面,小程序切入后台等
onUnload
- 页面卸载时触发。如wx.redirectTo或wx.navigateBack到其他页面时
// pages/home/home.js
Page({
onLoad(options) {
console.log(options, '页面参数');
},
onShow() {},
onReady() {},
onHide() {},
onUnload() {},
})
更多
官方文档:https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html
小程序wxs脚本
wxs和js
区别:
- wxs通常用作过滤器
- wxs有自己的数据类型
wxs不支持es6及以上的语法形式
- let const 解构赋值 箭头函数等
wxs遵循CommonJs规范
- module对象
- require()函数
- module.exports对象
wxs用法
内嵌在wxml中
定义wxs暴露出一个函数,在{}语法中调用 wxs脚本必须要有一个属性module指定模块名
<view>{{ m1.toUpper(username) }}</view>
<wxs module="m1">
module.exports.toUpper = function (str) {
return str.toUpperCase()
}
</wxs>
外联wxs脚本
定义wxs后缀的脚本文件 如 tools.wxs
在wxs中定义函数,并暴露
在wxml中引入wxs脚本文件,
调用m2里边的函数就行
<wxs src="../../utils/tools.wxs" module="m2"></wxs>
注意点
- 只能搭配{}语法使用,不能作为事件回调来使用
- wxs不能调用js中的函数
- wxs不能调用小程序提供的api
小程序自定义组件
如何自定义
- 在项目根目录components文件夹中创建文件夹
- 右键文件夹,新建Component,会自动生成组件需要的文件
局部注册组件
- 在页面的.json文件的usingComponents 节点中注册
- 注册方式 组件名称:组件路径
{
"usingComponents": {
"my-test": "/componnets/test/test"
}
}
全局注册组件
- 在app.json文件的usingComponents 节点中注册
- 注册方式同上
如何使用
在wxml中以标签的形式使用
<my-test></my-test>
组件特点
- 组件样式隔离不会影响其他组件或者页面
- 只有class类选择器才会受到样式隔离
如何修改样式隔离
在组件的js文件中添加options节点,添加属性styleIsolation为isolated
Component({
options: {
styleIsolation: "isolated"
},
})
styleIsolation属性值
可选值 | 默认值 | 描述 |
---|---|---|
isolated | 是 | 启用样式隔离,组件内外的class类声明的样式不会相互影响 |
apply-shared | 否 | 页面的wxss样式会影响到组件内部的样式,组件样式不会影响外部 |
shared | 否 | 组件内外的样式,相互影响 |
组件和页面的区别
组件
- 组件的js调用Component(Object object)函数
- 组件的方法函数定义在Component(Object object)函数的methods节点中
- 其他Component函数的节点
页面
- 页面的js调用Page(Object object)函数
- 页面的方法函数直接写在里边就好了
- 其他Page函数的节点
// 页面js
Page({
data: {},
goBack() { // 页面的方法函数,直接写就完事了
wx.navigateBack({
delta: 1,
})
},
onLoad(options) {
console.log(options, '页面参数');
console.log('onLoad');
}
})
// 组件js
Component({
options: {
styleIsolation: "isolated"
},
/* 组件的属性列表 用来接收组件上的属性*/
properties: {
num: {
type: Number, // 属性类型
value: 10 // 默认值
},
num1: Number, // 简化版
},
/* 组件的初始数据 */
data: {},
/* 组件的方法列表 */
methods: {
goBack() { // 组件的方法函数,定义在methods节点
wx.navigateBack({
delta: 1,
})
},
}
})
Component(Object object)函数
参数Object object
options
- 类型:Object
- 描述:组件配置选项
data
- 类型:Object
- 描述:存放组件私有数据
properties
- 类型:Object | Map
- 描述:组件外传递过来的属性映射,接收
methods
- 类型:Object
- 描述:组件的方法函数
更多参数节点参考:https://developers.weixin.qq.com/miniprogram/dev/reference/api/Component.html
组件数据监听
- Components函数添加observers节点
- 监听多个字段 num1, num2
- 监听对象的属性 obj.prop1,obj.prop2
- 监听对象所有属性,使用通配符*,obj.* 代表所有的属性
Component({
observers: { // 数据监听器
'num, num2': function (newNum, newNum2) { // 监听多个字段
// 做一些事情
},
'obj.prop1, obj.prop2': function (newProp1, newProp2) { // 监听对象属性
// 做一些事情
},
'obj.**': function (newObj) { // 监听对象所有的属性
// 做一些事情
}
},
})
纯数据字段
特点:
- 不会再页面中展示渲染
- 不会传递给其他组件使用
- 有利于提升页面更新的性能
设置纯数据字段:
- options节点新增pureDataPattern属性
- pureDataPattern值是一个正则表达式
- 符合表达式的数据就是纯数据字段
Component({
options: {
styleIsolation: "isolated",
pureDataPattern: /^_/ // 以下划线开头的数据,就是纯数据字段
},
data: {
_a: true
}
})
组件生命周期函数
生命周期函数
created
- 组件示例刚刚创建完执行
- 不能调用setData函数,只能在this上挂载一些自定义属性字段
attached
- 组件初始化完毕,进入到页面节点树执行
- 可以发送网络请求,初始化一些数据
ready
- 组件在视图布局完成后执行
moved
- 组件实例被移动到节点树的另一个位置时执行
detached
- 组件实例被从页面节点树移除时执行
使用的两种方法:
- 直接和data平级,写就完事了
- 使用 lifetimes节点,生命周期函数写在这里边(推荐)
Component({
lifetimes: {
created() {
console.log('test1组件 created');
},
attached() {
console.log('test1组件 attached');
}
}
})
组件所在页面的生命周期函数
生命周期函数
show
- 组件所在页面显示的时候触发
hide
- 组件坐在页面隐藏的时候触发
resize
- 组件所在页面的尺寸发生变化的时候触发
使用方法
- 新增pageLifetimes节点,将函数写在里边
Component({
lifetimes: {
created() {
console.log('test1组件 created');
},
attached() {
console.log('test1组件 attached');
}
},
pageLifetimes: {
show() {
console.log('组件所在页面显示了 show');
},
hide() {
console.log('组件所在页面隐藏了 hide');
},
resize() {
console.log('组件所在页面窗口尺寸变化了 resize');
}
}
})
组件插槽
匿名插槽
- 使用slot标签占位时,不设置name属性
具名插槽
- 使用slot标签占位时,设置name属性
开启组件多插槽
- 组件默认只能使用一个插槽
- 在options节点,新增multipleSlots: true,开启多插槽支持
<!-- 组件wxml -->
<view>
<slot name="before"></slot>
<slot></slot>
<slot name="after"></slot>
</view>
<!-- 引用组件的wxml -->
<cy-test1>
<view slot="after"> 渲染到name为 after的插槽 </view>
<view slot="before"> 渲染到name为 before的插槽 </view>
<view>渲染到默认插槽</view>
</cy-test1>
小程序组件传值
父子间组件通讯
通讯方法:
属性绑定
- 绑定属性在子组件上,子组件内通过properties进行接收
事件绑定
- 通过bind绑定自定义事件,子组件内通过this. triggerEvent(自定义事件名称, 传递的数据)进行调用
获取组件实例
- 直接通过this.selectComponent()获取组件实例
父向子传值
通过属性绑定
<!-- 父组件 使用组件,并添加属性arrList="父组件的某个数据" -->
<my-test arrList="{{ arr }}">
<text slot="before">before对应的插槽内容</text>
1231456
<text slot="after">after对应的插槽内容</text>
</my-test>
<!-- 在子组件的js的properties节点中添加对应的属性,并声明类型或者默认值 -->
properties: {
arrList: {
type: Array
}
}
<!-- 子组件封装 -->
<view style="background: pink;">
<slot name="before"></slot>
<slot></slot>
<slot name="after"></slot>
<view>----------</view>
<text wx:for="{{ arrList }}" wx:key=" id ">
接受到了父组件传递的数组: {{ item.name }}, {{ item.id }} // 拿到接收到的数据渲染
</text>
</view>
子向父传值
通过事件绑定
// 调用组件 并绑定自定义事件
<my-test arrList="{{ arr }}" fatherNum="{{ num }}" bind:getValue="getValue">
<text slot="before">before对应的插槽内容</text>
1231456
<text slot="after">after对应的插槽内容</text>
</my-test>
// js
getValue (e) {
console.log(e, '子组件调用父组件的getValue函数');
},
// 子组件触发这个自定义函数 并传值
this.triggerEvent('getValue', {value: 5})
获取组件实例
使用this.selectComponent() 传入id或者class选择器
this.selectComponent('.my-text1') // 组件标签添加class类
behaviors
类似于vue mixins混入
使用方法:
- 创建behaviors,新建一个js文件, 调用Behavior()函数创建一个behavior实例对象,通过module.exports向外暴露,组件调用时,会被合并到组件中
// js
module.exports = Behavior({
data: {},
properties: {},
methods: {}
})
- 通过require导入该js文件,并且在组件的behaviors节点中注册使用
const myBehavior = require('../../behaviors/my-behaviors')
// 在组件中添加behaviors节点,对应一个数组
behaviors: [myBehavior],
- behaviors中可用的节点 同组件属性
小程序npm包
npm包支持和限制
- 不支持依赖nodejs内置库的npm包
- 不支持依赖浏览器对象的npm包
- 不支持依赖c++插件的npm包
下载和使用
新版:
下载npm包 --> 工具 --> 构建npm包
旧版:
下载npm包 --> 右侧详情模块勾选npm包 --> 工具 --> 构建npm包
小程序全局共享容器
mobx全局共享
小程序可以使用mobx-miniprogram和mobx-miniprogram-bindings实现全局数据共享。
- mobx-miniprogram用来创建store对象
- mobx-program-bindings用来挂载store容器到页面 或者 组件中
如何使用mobx
下载npm包
npm install mobx-miniprogram --save
npm i mobx-miniprogram-bindings --save
# or
npm install --save mobx-miniprogram mobx-miniprogram-bindings
创建store容器
新建store.js文件
import { observable, action } from 'mobx-miniprogram'
// 创建store容器
export const store = observable({
// 数据字段
numA: 1,
numB: 2,
// 计算属性
get sum() {
return this.numA + this.numB
},
// action方法 修改数据
update: action(function(a = 0, b = 0) {
this.numA += a
this.numB += b
})
})
在页面中使用
// js
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'
Page({
data: {},
editNum(e) {
const a = e.target.dataset.a || 0
const b = e.target.dataset.b || 0
this.update(a, b)
},
onLoad(options) {
// 挂载store容器
this.storeBindings = createStoreBindings(this, {
store, // store容器
fields: ['numA', 'numB', 'sum'], // 映射数据字段和计算属性
actions: ['update'] // 映射action方法
})
},
})
<!-- wxml -->
<view>{{numA }} + {{ numB }} = {{ sum }}</view>
<van-button type="primary" bindtap="editNum" data-a="{{ 1 }}">A + 1</van-button>
<van-button type="info" bindtap="editNum" data-b="{{ 1 }}">B + 1</van-button>
在组件中使用
// js
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'
Component({
behaviors: [storeBindingsBehavior], // 挂载behavior
storeBindings: { // storeBindings配置选项
store,
// fields: ['numA', 'numB', 'sum'],
fields: { // 可以自定义变量名称 numABC: 'numA'
numA: 'numA', // 直接映射numA
numB: () => store.numB, // 函数返回numB
sum: (store) => store.sum // 函数返回sum
},
// actions: ['update']
actions: {
update: 'update'
}
}
properties: {},
data: {},
methods: {
editNum(e) {
const a = e.target.dataset.a || 0
const b = e.target.dataset.b || 0
this.update(a, b)
}
}
})
小程序分包
什么是分包
分包指的是将一个完整的小程序项目根据需求划分为不同的子包,在构建时打包成不同的分包,用户在使用的时候按需进行加载
分包特点
加载规则
- 小程序启动时,默认会下载主包并且启动主包内的页面(tabbar页面需要放到主包)
- 当用户进入分包内的某个页面,客户端会把对应的分包下载下来,进行展示(非tabbar页面按照功能的不同,划分不同的分包,进行按需下载)
体积限制
- 整个小程序的所有分包大小不能超过16M(主包 + 所有分包)
- 单个分包或者主包不能超过2M
引用原则
普通分包
- 可以引用主包内的公共资源
- 不能引用其他分包的私有资源
- 主包不能引用分包的私有资源
独立分包
- 资源独立
打包原则
- 小程序会按照subPackages的配置进行分包
- subPackages之外的目录将被打包到主包中
- tabbar页面必须要在主包中
- 分包之间不能互相嵌套
分包好处
- 可以优化小程序首次启动的下载时间,在多团队协作开发时能够更好的解耦协作
项目构成
分包前
- 小程序所有的页面和资源都被打包在一起
- 整个项目体积过大,影响小程序的首次启动的下载时间
分包后
- 小程序项目由一个主包和多个分包组成
- 主包一般只包含项目的启动页面或者tabbar页面,以及所有分包都需要使用的一些公共资源
- 分包只包含和当前分包有关的页面和私有资源
如何配置分包
在app.json中添加节点 subPackages 是一个数组,多个分包,就写多个对象
"subPackages": [
{
"root": "pkgA", // 分包的根目录
"name": "p1", // 分包的别名
"pages": [ // 分包下面的页面 会自动创建
"pages/cat/cat",
"pages/logs/logs"
]
}
],
独立分包
独立分包和普通分包区别
独立分包
- 本质上还是分包
- 功能独立
- 不能引用主包公共资源,不能引用分包的私有资源,独立分包之间也不可相互引用,资源完全独立
- 不依赖主包,可以单独运行,提升分包页面的启动速度
普通分包
- 普通分包依赖于主包,需要先下载主包
- 可以引用主包公共资源
配置独立分包
只需要在分包中添加independent为true,则当前分包就是一个独立分包
{
"root": "pkgB",
"name": "p2",
"pages": [
"pages/cat/cat",
"pages/logs/logs"
],
"independent": true
}
分包预下载
分包预下载指的是,在进入小程序的某个页面时,由框架自动预下载可能需要的分包,从而提升后续进入分包时页面的启动速度
配置分包预下载
- 预下载分包的行为,会在进入到指定的页面时触发。
- 在app.json中配置preloadRule节点,定义预下载规则。
- 分包预下载所有页面共享2M,预下载的大小不能超过2M
"preloadRule": {
"pages/logs/logs": { // 页面路径,哪一个页面,进入这个页面,预加载哪些packges分包
"packages": ["p1", "p2"], // 分包的name别名或者 root根目录
"network": "all" // 下载环境 all 所有 wifi 仅限wifi环境
}
},
评论 (0)