前端【小程序】04-小程序基础篇【生命周期】【页面生命周期】【应用生命周期】【组件生命周期】
生命周期
生命周期是一些名称固定自动执行的函数。
页面生命周期
文档:https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html#%E5%8F%82%E6%95%B0
onLoad
在页面加载完成时执行,只会执行 1 次,常用于获取地址参数和网络请求,页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数。onShow
在页面处于可见状态时执行,常用于动态更新数据或状态onReady
在页面初次渲染完成时执行,只会执行 1 次,常用于节点操作或动画交互等场景onHide
在页面处于不见状态时执行,常用于销毁长时间运行的任务,如清理定时器
图书本地存储示例
index.wxml
1 <button class="button" size="mini" type="primary" bind:tap="getBooks">查询书单</button> 2 <view class="books"> 3 <view class="item"> 4 <text>序号</text> 5 <text>名称</text> 6 <text>作者</text> 7 <text>出版社</text> 8 <text>操作</text> 9 </view> 10 <view class="item" wx:for="{{books}}" wx:key="id"> 11 <text>{{index + 1}}</text> 12 <text>{{item.bookname}}</text> 13 <text>{{item.author}}</text> 14 <text>{{item.publisher}}</text> 15 <text>删除</text> 16 </view> 17 </view> 18 19 <!-- 本地存储 --> 20 <view class="storage"> 21 <button size="mini" type="primary" bind:tap="setStorageData">存数据</button> 22 <button size="mini" type="primary" bind:tap="getStorageData">读数据</button> 23 <button size="mini" type="primary" bind:tap="removeStorageData">删数据</button> 24 <button size="mini" type="primary" bind:tap="clearStorageData">清数据</button> 25 </view> 26 27 <view class="preview" bind:tap="onChoose"> 28 <image src="{{ avatar }}" mode="aspectFill" /> 29 </view> 30 31 <!-- 搜索历史 32 <view class="history"> 33 <view class="search-bar"> 34 <input type="text" model:value="{{ keyword }}" /> 35 <text class="label" bind:tap="onSearch">搜索</text> 36 </view> 37 <view class="title" wx:if="{{ keywords.length }}"> 38 历史搜索 <text class="icon-delete" bind:tap="onClear">x</text> 39 </view> 40 <view class="keywords"> 41 <navigator url="/pages/test/index" wx:for="{{ keywords }}" wx:key="*this"> 42 {{ item }} 43 </navigator> 44 </view> -->
index.wxss
1 /* pages/interface/index.wxss */ 2 .button { 3 margin-top: 10rpx; 4 } 5 6 .books { 7 padding: 0 20rpx; 8 margin-top: 20rpx; 9 border-radius: 10rpx; 10 background-color: #fff; 11 } 12 13 .books .item { 14 display: flex; 15 justify-content: space-between; 16 height: 44rpx; 17 padding: 20rpx 0; 18 text-align: center; 19 border-bottom: 1rpx solid #eee; 20 } 21 22 .books .item:last-child { 23 border-bottom: none; 24 } 25 26 .books .item text { 27 text-overflow: ellipsis; 28 white-space: nowrap; 29 overflow: hidden; 30 } 31 32 .books .item text:first-child { 33 width: 80rpx; 34 } 35 36 .books .item text:nth-child(2) { 37 width: 180rpx; 38 } 39 40 .books .item text:nth-child(3) { 41 width: 140rpx; 42 } 43 44 .books .item text:nth-child(4) { 45 flex: 1; 46 } 47 48 .books .item text:last-child { 49 width: 80rpx; 50 } 51 52 .storage { 53 display: flex; 54 justify-content: space-around; 55 padding: 20rpx 0; 56 margin-top: 20rpx; 57 border-radius: 10rpx; 58 background-color: #fff; 59 } 60 61 .storage button { 62 margin: 0; 63 } 64 65 66 .preview { 67 width: 200rpx; 68 height: 200rpx; 69 margin-top: 20rpx; 70 border-radius: 10rpx; 71 background-color: #fff; 72 background-image: url(https://lotjol.github.io/static-store/enjoy-plus/images/upload.png); 73 background-size: 80rpx; 74 background-position: center; 75 background-repeat: no-repeat; 76 } 77 78 .preview image { 79 width: 100%; 80 height: 100%; 81 } 82 83 .history { 84 margin-top: 20rpx; 85 padding: 30rpx 20rpx; 86 border-radius: 10rpx; 87 background-color: #fff; 88 } 89 90 .history .search-bar { 91 display: flex; 92 } 93 94 .history .search-bar .label { 95 width: 90rpx; 96 margin-right: 10rpx; 97 text-align: right; 98 line-height: 70rpx; 99 } 100 101 .history .search-bar input { 102 flex: 1; 103 padding-left: 40rpx; 104 border-radius: 60rpx; 105 } 106 107 .history .title { 108 display: flex; 109 justify-content: space-between; 110 margin-top: 30rpx; 111 padding-left: 20rpx; 112 font-size: 30rpx; 113 } 114 115 .history .title .icon-delete { 116 width: 36rpx; 117 height: 36rpx; 118 text-align: center; 119 line-height: 32rpx; 120 border-radius: 50%; 121 color: #fff; 122 transform: scale(0.9); 123 background-color: #ccc; 124 } 125 126 .history .keywords { 127 display: flex; 128 flex-wrap: wrap; 129 margin-top: 10rpx; 130 border-radius: 10rpx; 131 } 132 133 .history .keywords navigator { 134 margin-right: 20rpx; 135 margin-top: 20rpx; 136 padding: 8rpx 28rpx; 137 border-radius: 50rpx; 138 background-color: #f7f6f7; 139 font-size: 28rpx; 140 }
index.js
1 Page({ 2 data: { 3 books: [], 4 keyword:'', 5 keywords:[] 6 }, 7 // onSearch() { 8 // const keyword = this.data.keyword.trim() 9 10 // // 非空判断 11 // if(keyword === '') { 12 // return wx.showToast({ 13 // icon:'none', 14 // title: '请输入搜索内容', 15 // }) 16 // } 17 18 // const arr = [keyword,...this.data.keywords] 19 // this.setData({ 20 // keywords:Array.from(new Set(arr)), 21 // keyword:'' 22 // }) 23 // }, 24 // 调用数据接口的方法 25 getBooks() { 26 27 // 加载提示 28 wx:wx.showLoading({ 29 title: '疯狂加载中', 30 mask: true 31 }) 32 // 调用小程序的 API 发起请求 33 wx.request({ 34 url: 'https://hmajax.itheima.net/api/books', 35 method: 'GET', 36 data: { 37 creator: 'zhangsan', 38 }, 39 success: (result) => { 40 // 更新数据,渲染页面 41 this.setData({ books: result.data.data }) 42 43 // 轻提示 44 wx.showToast({ 45 icon:'success', 46 title: '查询成功' 47 }) 48 }, 49 complete() { 50 wx.hideLoading() 51 } 52 }) 53 }, 54 // 本地存储 - 存数据 55 setStorageData() { 56 // 🚨注意:小程序通过 this.data.xxx 获取 data 数据 57 wx.setStorageSync('list', this.data.list) 58 // 轻提示 59 wx.showToast({ icon: 'success', title: '存储成功' }) 60 61 // 同步写法 - 推荐,书写简洁方便 62 // wx.setStorageSync('key', data) 63 // 异步写法 64 // wx.setStorage({ key:'key', data: data, success(){} }) 65 66 // wx.setStorage({ 67 // key: 'list', 68 // data: this.data.list, 69 // success: () => { 70 // wx.showToast({ icon: 'success', title: '存储成功' }) 71 // } 72 // }) 73 }, 74 75 // 本地存储 - 取数据 76 getStorageData() { 77 const list = wx.getStorageSync('list') 78 console.log(list); 79 wx.showToast({ icon: 'none', title: '读取成功,看控制台' }) 80 81 // 异步写法 82 // wx.getStorage({ 83 // key: 'list', 84 // success: (res) => { 85 // console.log(res.data) 86 // wx.showToast({ icon: 'none', title: '读取成功,看控制台' }) 87 // } 88 // }) 89 }, 90 91 // 本地存储 - 删数据 92 removeStorageData() { 93 wx.removeStorageSync('logs') 94 wx.showToast({ icon: 'success', title: 'logs删除成功' }) 95 }, 96 97 // 本地存储 - 清数据 - 慎用 98 clearStorageData() { 99 wx.clearStorageSync() 100 wx.showToast({ icon: 'none', title: '清空了全部本地存储' }) 101 }, 102 103 // 选择图片 104 async onChoose() { 105 const { tempFiles} = await wx.chooseMedia({ 106 mediaType:['image'], 107 count:1, 108 }) 109 // console.log(tempFiles[0].tempFilePath); 110 this.setData({ 111 avatar:tempFiles[0].tempFilePath 112 }) 113 } 114 })
应用生命周期
App函数的文档:https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html
开发工具中,关闭小程序,会显示场景值查找
App.js
1 App({ 2 // 小程序初始化完成时触发,全局只触发一次 3 onLaunch(options) { 4 // 小程序启动时会执行一次,常用于获取场景值或参数 5 console.log("onLaunch", options); 6 console.log("场景值", options.scene); 7 console.log("query参数", options.query); 8 }, 9 // 小程序启动或从后台进入前台显示时 10 onShow(options) { 11 console.log("options", options); 12 console.log("场景值", options.scene); 13 console.log("query参数", options.query); 14 }, 15 // 小程序从前台进入后台时,点击关闭按钮其实也会进入后台,微信会保留几分钟 16 onHide() { 17 console.log("onHide"); 18 } 19 })
小程序启动后,打印日志:
小程序更新机制
开发者在管理后台发布新版本的小程序之后,微信客户端会有若干个时机去检查本地缓存的小程序有没有新版本,并进行小程序的代码包更新。但如果用户本地有小程序的历史版本,此时打开的可能还是旧版本。
1. 启动时同步更新
在以下情况下,小程序启动时会同步更新代码包。同步更新会阻塞小程序的启动流程,影响小程序的启动耗时。
如果更新失败或超时,为了保障小程序的可用性,还是会使用本地版本打开。
定期检查发现版本更新
微信运行时,会定期检查最近使用的小程序是否有更新。如果有更新,下次小程序启动时会同步进行更新,更新到最新版本后再打开小程序,尽可能保证用户能够尽快使用小程序的最新版本。
用户长时间未使用小程序
用户长时间未使用小程序时,为保障小程序版本的实时性,会强制同步检查版本更新,更新到最新版本后再打开小程序。
若用户处于弱网环境、下载最新版本失败等情况下,仍会启动本地的较低版本。
2. 启动时异步更新
即使启动前未发现更新,小程序每次冷启动时,都会异步检查是否有更新版本。如果发现有新版本,将会异步下载新版本的代码包。但当次启动仍会使用客户端本地的旧版本代码,即新版本的小程序需要等下一次冷启动才会使用。
开发者手动触发更新
在启动时异步更新的情况下,如果开发者希望立刻进行版本更新,可以使用 wx.getUpdateManager API 进行处理。在有新版本时提示用户重启小程序更新新版本。
1 // app.js 2 App({ 3 onLaunch() { 4 // 小程序启动时,检查更新 5 this.checkUpdate() 6 }, 7 checkUpdate() { 8 // 获取版本更新管理器 9 const updateManager = wx.getUpdateManager() 10 11 // 检查更新结果 12 updateManager.onCheckForUpdate(function (res) { 13 // 是否有更新 14 console.log(res.hasUpdate) 15 }) 16 17 // 监听小程序有版本更新事件 18 updateManager.onUpdateReady(function () { 19 // 客户端主动触发下载(无需开发者触发下载,只需要做引导重启的提示即可) 20 wx.showModal({ 21 title: '更新提示', 22 content: '新版本已经准备好,是否重启应用?', 23 success: function (res) { 24 if (res.confirm) { 25 // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启 26 updateManager.applyUpdate() 27 } 28 }, 29 }) 30 }) 31 32 updateManager.onUpdateFailed(function () { 33 // 新版本下载失败 34 console.log("新版本下载失败") 35 }) 36 }, 37 })
编译设置
编译然后从新进入小程序
组件生命周期
created:组件创建时触发
• 类似Vue 中的created
• 不能调用this.setData
attached:组件初始完毕时触发
• 类似于Vue 中的mounted
• 最常使用
应用示例:状态栏适配
• wx.getSystemInfoSync() 同步的方式获取系统信息,包含状态栏的高度(单位px)(statusBarHeight),系统版本,型号....
- created 组件创建时触发,类似于 Vue 中的 created 生命周期,该生命周期中不能调用 this.setData
- attached 组件初始化完毕时触发,类似于 Vue 中的 mounted 生命周期,该生命周期函数使用最频繁
小程序自定义组件的生命周期需要定义在 lifetimes 中:
组件的js中添加生命周期属性
1 // components/my-nav/my-nav.js 2 Component({ 3 4 options: { 5 // 方案1:addGlobalClass: true表示允许外部修改组件样式 6 addGlobalClass: true, 7 multipleSlots: true // 在组件定义时的选项中启用多slot支持 8 }, 9 10 // 方式2:自定义样式类 11 externalClasses: ['custom-class'], 12 13 // 组件生命周期 14 lifetimes: { 15 // 相当于vue的created 16 // 17 created() { 18 // 几乎不用,因为created()方法中使用this.setData()无效 19 }, 20 // 相当于vue的mounted 21 attached() { 22 // 获取屏幕刘海的高度 23 const {statusBarHeight} = wx.getSystemInfoSync(); 24 console.log(statusBarHeight); 25 this.setData({ 26 statusBarHeight: statusBarHeight // 将获取到的刘海高度,赋值给变量statusBarHeight 27 }); 28 } 29 }, 30 31 /** 32 * 组件的属性列表 33 */ 34 properties: { 35 36 }, 37 38 /** 39 * 组件的初始数据 40 */ 41 data: { 42 statusBarHeight: 0 43 }, 44 45 /** 46 * 组件的方法列表 47 */ 48 methods: { 49 50 } 51 })
组件增加行内样式来获取上面获取到的刘海高度
1 <!--components/my-nav/my-nav.wxml--> 2 <view class="navigation-bar custom-class" style="padding-top: {{ statusBarHeight }}px;"> // 刘海高度动态获取,在组件的生命周期函数中获取,单位是px,所以这里在大括号外面写上单位px 3 <view class="navigation-bar-title title-class"> 4 <!-- 指定多个插槽 --> 5 <slot name="left"></slot> 自定义标题 <slot name="right"></slot> 6 </view> 7 </view>
组件的样式
1 /* components/my-nav/my-nav.wxss */ 2 .navigation-bar { 3 background-color: #ffffff; 4 height: 88rpx; 5 /* 顶部刘海预留 */ 6 padding-top: 100rpx; 7 display: flex; 8 justify-content: center; 9 align-items: center; 10 } 11 12 .navigation-bar-title { 13 font-weight: bold; 14 }