全局生命周期函数
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
onLaunch | function | 否 | 监听小程序初始化,全局只会执行 1 次 |
onShow | function | 否 | 监听小程序启动或切前台。 |
onHide | function | 否 | 监听小程序切后台。 |
局部生命周期函数
属性 | 类型 | 说明 |
---|---|---|
onLoad | function | 页面加载时触发 (一个页面只会调用一次) |
onShow | function | 页面显示时触发,页面显示/切入前台时触发 |
onReady | function | 页面初次渲染完成时触发(一个页面只会调用一次 |
onHide | function | 页面隐藏/切入后台时触发 |
onUnload | function | 页面卸载时触发 |
组件生命周期函数
Component({
#组件的生命周期
lifetimes: {
created: function () {
// 在组件实例刚刚被创建时执行,注意此时不能调用 setData
// 一般用来为组件添加一些自定义属性字段。
this.test = '测试'
},
attached: function() {
// attached 在组件完全初始化完毕、进入页面节点树后执行
// 模板已经解析完毕,并且挂载到页面上
// 一般都是在这里写对应的交互
console.log(this.test)
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
},
# 组件所在页面的生命周期
pageLifetimes: {
// 监听组件所在的页面展示(后台切前台)状态
show () {
console.log('组件所在的页面被展示')
},
// 监听组件所在的页面隐藏(前台切后台、点击 tabBar)状态
hide () {
console.log('组件所在的页面被隐藏')
}
}
})
微信小程序四个文件
- js:页面逻辑-必须存在
- wxml:页面结构-必须存在
- json:小页面配置
- wxss:页面样式
遍历、判断、显示隐藏
<!-- 小程序遍历内置item和index -->
<!-- 遍历对象时需要绑定wx:key wx:for-item="students" wx:for-index="key" 这两个是重新指定每一项和下标的名称-->
<view wx:key="id" wx:for="{{students}}" wx:for-item="students" wx:for-index="key" class="table">
<!-- wx:if="{{students.age > 18}}" 暂时移除条件-->
<text>{{key+1}}</text>
<text>{{students.name}}</text>
<text>{{students.age}}</text>
<text>{{students.gender}}</text>
</view>
<!-- 遍历数组或者字符串时绑定的wx:key="*this" -->
<text wx:for="{{bro}}" wx:key="*this">{{item}}</text>
<!-- 测试if elif else -->
<view>
<text wx:if="{{num === 1}}">您现在是{{num}}级别111</text>
<text wx:elif="{{num === 2}}">您现在是{{num}}级别222</text>
<text wx:else>您现在是{{num}}级别🐂</text>
</view>
<!-- 测试wx:if 与 hidden -->
<button type="primary" bind:tap='toggle'>显示/隐藏</button>
<!-- wx:if与v-if类似,是惰性的,如果首次不加载的话可以节省资源 -->
<view wx:if="{{hidden}}">{{msg}}</view>
<!-- 变量hidde值是true,这边要取反,不然就隐藏了 hidden与v-show类似 -->
<view hidden="{{!hidden}}">{{msg}}</view>
url="{{'/pages/notify/index?id='+item.id}}" 带参跳转
scroll-view使用
<scroll-view
class="scroll-y"
scroll-y //开启y轴滚动
lower-threshold="100" //距离底部还剩余多少触发下拉加载
bindscrolltolower="getMore" //下拉加载事件
enable-back-to-top //点击顶部栏返回顶部
refresher-enabled //开启下拉刷新
refresher-default-style="black" // loading效果
refresher-background="#f7f7f8" // loading背景颜色
bindrefresherrefresh="onrefresh" //上拉刷新函数
refresher-triggered="{{ triggered }}" //loading的显示状态
>
<view wx:for="{{ arr }}" wx:key="*this">{{ item }}</view>
</scroll-view>
微信小程序发布上线流程
开发者身份 ==> 分包 ==> 上传填写版本号 ==> 审核 ==> 上传发布
微信小程序最大宽是750rpx
微信小程序自定义导航栏
在app.json(全局)或者 page内的.json文件内配置navigationStyle
js{ "usingComponents": {}, "navigationStyle": "custom" }
微信小程序的两种渲染模式
Skyline,在低版本的客户端中,将使用 WebView 渲染模式进行渲染。在全局app.json中配置渲染模式
小程序事件处理
- 获取值:event.detail.value
- 阻止冒泡:将bindtap变成catchtap
- 事件传参:在标签上用data-id="1"
- 获取用event.currentTarget.dataset(事件绑定者身上的数据,冒泡) event.target.dataset(触发者本身上的数据)
- 事件传参:mark:id="1" 获取用event.mark 父元素绑定mark时也能通过冒泡机制访问到
小程序数据双向绑定:model:value=""
block:不是页面组件,仅用于包裹元素,支持列表渲染、条件渲染等,类似vue中template
小程序跳转方式
- wx.switchTab:只能跳转tabBar页面,路径后不能带参数
- wx.navigateTo:保留当前页面,跳转下一页面,不能跳转到tabBar
- wx.redirectTo:关闭当前页面,跳转下一页面,不能跳转到tabBar
- wx.reLaunch:关闭所有页面打开指定页面( 页面栈也清空了 )
路由传参--通过onLoad生命周期获取
wx.navigateTo({
url: '/pages/list/list?id=1&name=tom'
})
#获取参数
onLoad(options){
console.log(options)
}
小程序组件---父传子
组件设置样式必须优先用class,color/font会从组件外继承
开发中常见的组件主要分为 公共组件 和 页面组件 两种,因此注册组件的方式也分为两种:
- 全局注册:在
app.json
文件中配置usingComponents
节点进行引用声明,注册后可在任意组件使用 - 局部注册:在页面的
json
文件中配置usingComponents
节点进行引用声明,只可在当前页面使用
{
"usingComponents": {
"自定义组件的标签名": "自定义组件文件路径"
}
}
组件中的方法必须写在methods中--含父传子
#使用组件并传参的方式
<custom-checkbox label="我已阅读并同意 用户协议 和 隐私协议" position="right" />
#custom-checkbox组件
//wxml中的代码
<view class="custom-checkbox-container">
<view class="custom-checkbox-box {{ position === 'right' ? 'right' : 'left' }}">
<checkbox class="custom-checkbox" checked="{{ isChecked }}" bindtap="updateChecked" />
<view>
<text>{{ label }}</text>
</view>
</view>
</view>
//js中的代码
Component({ //注意此处是Component
options: { //样式隔离选项 默认`isolated`,apply-shared:父影响子,但子不影响父; shared:影响全局及其他为shared的组件
styleIsolation: 'apply-shared'
},
// 组件的属性列表,主要用来接收组件使用者传递给组件内部的属性以及数据
properties: {
// 如果需要接收传递的属性,有两种方式:全写、简写
// label: String
label: {
// 数据类型:String、Number、Boolean、Object、Array 也可以设置为 null,表示不限制类型
type: String,
value: ''
},
// 文字显示位置
position: {
type: String,
value: 'right'
}
},
data: {
isChecked: false
},
methods: {
// 更新复选框的状态
updateChecked () {
this.setData({
isChecked: !this.data.isChecked
})
console.log(this.properties.label) //可以拿到传进来的数据 也可以通过setData修改 但是不建议
//要是修改建议用 下方的监听器 监听传进来的数据然后进行修改
}
}
})
子传父通信--通过triggerEvent('事件名',数据)
#子组件中
<button type="primary" plain bindtap="sendData">传递数据</button>
#.js
Component({
// 组件的初始数据
data: {
num: 666
},
methods: {
// 将数据传递给父组件
sendData () {
// 需要使用 triggerEvent 发射自定义事件, 第二个参数,是携带的参数
this.triggerEvent('myevent', this.data.num)
}
}
})
#.wxml父组件
<view>{{ num }}</view>
<!-- 需要在自定义组件标签上通过 bind 方法绑定自定义事件,同时绑定事件处理函数 -->
<custom05 bind:myevent="getData" />
#.js
Page({
data: {
num: ''
},
getData (event) {
// 可以通过事件对象event.detail 获取子组件传递给父组件的数据
this.setData({
num: event.detail
})
}
})
获取子组件实例selectComponent()方法
<!-- 父组件 -->
<costom bind:myevent="getData" class="custom" />
<button bindtap="getChildComponent"></button>
// 父组件
Page({
data: {},
getChildComponent: function () {
const child = this.selectComponent('.custom') //填写id或者类
console.log(child)
}
})
数据监听器-只能在组件中使用
可以用于监听和响应任何属性和数据字段的变化,有时,需要在一些数据字段被 setData 设置时,需要执行一些操作。那么就可以使用 observers
数据监听器来实现。语法如下:
Component({
data: {
num: 10,
count: 1,
obj: { name: 'Tom', age: 10 },
arr: [1, 2, 3]
},
observers: {
// key 是需要检测数据
// value 是一个函数,函数接收一个形参作为参数,是最新的值
num: function(newNum) {
console.log(newNum)
},
// 数据监听器支持监听属性或内部数据的变化,可以同时监听多个
'num, count': function (newNum, newCount) {
console.log(newNum, newCount)
}
// 监听器可以监听子数据字段
'obj.age': function(newAge) {
console.log(newAge)
},
// 如果需要监听所有子数据字段的变化,可以使用通配符 **
'obj.**': function(newAge) {
console.log(newAge)
},
'arr[0]': function (val) {}
}
})
使用 Component 构造页面
📌 注意事项:
要求对应 json 文件中包含 usingComponents 定义段
页面使用 Component 构造器创建,需要定义与普通组件一样的字段与实例方法
页面 Page 中的一些生命周期方法(如 onLoad() 等以“on”开头的方法),在 Component 中要写在 methods 属性中才能生效
组件的属性 Properties 可以用于接收页面的参数,在 onLoad() 中可以通过 this.data 拿到对应的页面参数
Component({
# Component 方法功能比 Page 方法强大很多
# 如果使用 Component 方法构造页面,可以实现更加复杂的页面逻辑开发,可以使用监听器
// 注意事项:
// 1. 要求 .json 文件中必须包含 usingComponents 字段
// 2. 里面的配置项需要和 Component 中的配置项保持一致
// 3. 页面中 Page 方法有一些钩子函数、事件监听方法,这些钩子函数、事件监听方法必须方法 methods 对象中
// 4. 组件的属性 properties 也可以接受页面的参数,在 onLoad 钩子函数中可以通过 this.data 进行获取
properties: {
id: String,
title: String
},
data: {
name: 'tom'
},
methods: {
// 更新 name
updateName() {
this.setData({
name: 'jerry'
})
},
onLoad (options) {
console.log(this.data.id)
console.log(this.data.title)
console.log(this.properties.id)
},
}
})
插槽
#custom01.wxml
<view>
<slot name="slot-top" /> //具名
<view><slot /></view> // 默认
<slot name="slot-bottom" /> //具名
</view>
#custom01.js
Component({
options: {
multipleSlots: true //开启多插槽的支持
}
})
#.json文件中注册
{
"usingComponents": {
"自定义组件的标签名": "自定义组件文件路径"
}
}
#使用
<custom01>
<text slot="slot-top">我需要显示到顶部</text>
我是子节点内容 //显示到默认的位置
<text slot="slot-bottom">我需要显示到低部</text>
</custom01>
通过npm安装第三方vant组件库
#项目根目录
npm init -y
npm i @vant/weapp -S --production
#在app.json中去除styleV2
#构建--如果要自定义构建,这边就先别构建
工具---构建npm
自定义npm构建
将所有代码都移入新建的miniprogram中,并且在project.config.json中的setting配置项内进行配置
微信小程序分包
- 在
app.json
中,通过subPackages
字段声明分包结构- 一个分包配置一个对象,分包+主包规定目前不能超过20MB
- 主包不能引用分包资源,分包可以引用主包资源,分包与分包资源不能相互引用
root
字段指定了分包的根目录,该目录下的所有文件都会被打包成一个独立的包name
字段为分包的名称,用于在代码中引用该分包pages
字段指定了该分包中包含的页面,可以使用通配符*
匹配多个页面
#跳转方式 / + 分包路径 + 页面地址
<navigator url="/modules/goods/pages/list/list">toListPage</navigator>
分包预下载(含独立分包配置)
需要在
app.json
中通过preloadRule
字段设置预下载规则。
{
#分包
"subPackages": [
{
"root": "modules/goods", #分包根路径
"name": "goods",#分包别名
"pages": [
"pages/list/list",#分包页面
"pages/detail/detail"
]
},
{
"root": "modules/marketModule",
"name": "marketModule",
"pages": [
"pages/market/market"
],
"independent": true #开启独立分包
}
],
"preloadRule": {
"pages/index/index": { #访问此页面会预下载下方配置的页面
"network": "all", #网络条件
"packages": ["modules/goodModule"] #可配置分包根路径(root)或者是name
},
"modules/marketModule/pages/market/market": { #访问独立分包下载主包
"network": "all",
"packages": ["__APP__"] #主包特有的写法
}
}
}
框架接口-getApp 全局共享数据
➡️ app.js
App({
// 全局共享的数据
globalData: {
token: ''
},
// 全局共享的方法
setToken (token) {
// 如果想获取 token,可以使用 this 的方式进行获取
this.globalData.token = token
// 在 App() 方法中如果想获取 App() 实例,可以通过 this 的方式进行获取
}
})
➡️ pages/index/index.js
// getApp() 方法用来获取全局唯一的 App() 实例
const appInstance = getApp()
Page({
login () {
console.log(appInstance)
appInstance.setToken('fghioiuytfghjkoiuytghjoiug')
}
})
微信小程序事件总线pubSub
用于组件之间的相互通信
# npm install pubsub-js
# 构建npm
#发布事件的组件
import pubSub from 'pubsub-js'
Component({
properties: {},
data: {
name:'tom'
},
methods: {
sendData(){
//发布事件
pubSub.publish('pubSendData',{name:this.data.name,age:18})
}
}
})
#接收事件的组件
import pubSub from 'pubsub-js'
Component({
properties: {},
data: {
name:''
},
methods: {},
lifetimes:{
attached(){
pubSub.subscribe('pubSendData',(msg,data)=>{
console.log(msg,data);//pubSendData {name: "tom", age: 18}
this.setData({
name:data.name
})
})
}
}
})
uniapp也可以用vue的生命周期,在是组件的情况下推荐用vue的,在是页面的情况下推荐用uniapp的
小程序适配刘海屏
import { xxx } from '@dcloudio/uni-app' //uniapp的生命周期引入方式
方法1
@media screen and (min-height: 812px) and (min-width: 375px) {
/* 在iPhone X及以上设备上应用样式 */
.header {
padding-top: constant(safe-area-inset-top); /* 适配刘海屏的安全区域 */
}
}
方法2:通过 uni.getSystemInfoSync()来解构出safeAreaInsets安全区域,这个解构出来的对象内有上下左右四个边距值,通过动态绑定style样式的paddingTop来解决刘海屏问题