- 给HTML元素添加data-*属性来传递我们需要的值,然后通过e.currentTarget.dataset或onload的param参数获取,但data-名称不能有大写字母和不可以存放对象
- 设置id 的方法标识来传值通过e.currentTarget.id获取设置的id的值,然后通过设置全局对象的方式来传递数值
- 在navigator中添加参数传值,但需要注意navigateTo等进行参数传递的时候有长度的限制,如果传递的参数是对象,首先需要转化数据类型JSON.stringify、JSON.parse,再则需要进行编码类型的转化encodeURIComponent、decodeURIComponent
- 使用组件模板template传递参数
- 可以利用globalData进行全局数据的设置以及在各个页面的获取处理
- 可以利用数据缓存的功能进行setStorage、getStorage的设值与获取
- 使用后端程序进行不同页面之间的传递数据
小程序不能直接this.data.xxx进行数据值的修改,Vue可以直接this.xxx进行数据值的修改
小程序需要利用this.setData进行数据值的修改,而React则是利用this.setState进行数据值的修改
小程序利用this.setData进行状态值的修改模式是同步及异步的,而React的this.setState是异步函数
this.setState({ name:'zhang' }) console.log(this.state.name);//不能立马获取到新的state值
this.setData({ name:'zhang' }) console.log(this.data.name);//可以立马获取到新的data值
- 可以看到 setData函数过程是:
- 将数据从逻辑层发送到视图层是异步
- 改变this.data是同步的
- 也就是说改变值是同步的,改变值之后渲染页面是异步的。如此操作的目的是为了提高性能,不可能改变一次数据渲染一次页面,等所有data改变完之后一块渲染页面
- 首先需要思考的是操作的对象不同,有页面级的下拉刷新与上拉加载操作,也有scroll-view组件级的下拉刷新和上拉加载处理
- 针对于页面级:
- 可以在全局 config 中的 window 配置中设置 enablePullDownRefresh 属性,当然建议 enablePullDownRefresh 属性是在页面级配置中设置, 在 Page 中定义 onPullDownRefresh 事件函数
- 到达下拉刷新条件后,该事件函数执行,发起请求方法,下拉刷新请求返回后,调用 wx.stopPullDownRefresh 停止下拉刷新。
- 至于上拉加载则可以利用 onReachBottom 事件函数来确认后续的功能操作,一般它与 onReachBottomDistance 进行配合处理,确认距离底部的距离,而它的单位是px。
- 针对scroll-view组件级:
- 下拉刷新需要利用 refresher-enabled 开启,对应的阈值设置是 refresher-threshold
- 需要利用 refresher-triggered 来确认刷新的状态,在下拉刷新结束以后需要设置为 false 状态
- 利用 bindscrolltolower 实现上拉加载的功能处理
- 纵向滚动时需要给scroll-view设置具体的高度值
- 相同点:首先他们都是作为点击事件函数,就是点击时触发。在这个作用上他们是一样的,可以不做区分
- 不同点:他们的不同点主要是bindtap是不会阻止冒泡事件的,catchtap是阻值冒泡的
- 导航相关的API主要包括:wx.navigateTo()、wx.redirectTo()、wx.switchTab()、wx.navigateBack()、wx.reLaunch()
- wx.navigateTo():保留当前页面,跳转到应用内的某个页面,但是不能跳到 tabbar 页面
- wx.redirectTo():关闭当前页面,跳转到应用内的某个页面,但是不允许跳转到 tabbar 页面
- wx.switchTab():跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
- wx.navigateBack():关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层
- wx.reLaunch():关闭所有页面,打开到应用内的某个页面
- npm init项目的初始化操作
- npm install lodash --save等模块安装操作
- 微信开发者工具->详情->本地设置->使用npm模块
- 微信开发者工具->工具->构建npm
- API简易地图:先可以利用wx.getLocation获取位置的经纬度等信息,再使用wx.openLocation打开微信内置地图查看位置,不过获取的信息只有经纬度,所以像name,address等内容没有更好的办法进行显示,而且wx.openLocation仅限于查看地图查看位置,其它更多的地图内容不能够处理。
- 组件功能地图:如果需要标注、路线、俯视、旋转更多的地图操作功能,则需要利用map组件进行地图内容的展示操作
需要通过第三方地图API接口进行地理信息的获取,比如腾讯地图、百度地图、高德地图等,但不管哪个第三方地图应用,其操作过程基本雷同
因为要请求第三方地图API接口,所以需要在微信平台的授权请求地址中将第三方地图API的请求地址内容进行授权设置,否则正式环境将无法允许应用请求对应的地址
如果没有在微信平台的授权请求地址,那么无法进行真机预览操作,但可以进行真机调试处理
第三方地图API接口的一般操作流程如下(以百度地图为例):
创建地图应用
选择正确的应用类型以及设置小程序的AppID
获取AK信息
查看对应的文档资料
下载相应支持小程序的第三方地图库文件
利用第三方地图API进行地图内容的获取以及利用小程序map组件显示对应的地图信息
var bmap = require('../../utils/bmap-wx.min.js'); // 支持小程序的地图类库文件 var wxMarkerData = []; Page({ data: { markers: [], latitude: '', longitude: '', }, onLoad() { var that = this; var BMap = new bmap.BMapWX({ ak: 'jU4Ww0DiPzXUZmCshR6XjcH5Y3AG6GCE' // AK信息 }); var fail = function (err) { console.log(err) }; var success = function (data) { wxMarkerData = data.wxMarkerData; that.setData({ markers: wxMarkerData, latitude: wxMarkerData[0].latitude, longitude: wxMarkerData[0].longitude }); } // 发起regeocoding检索请求 BMap.regeocoding({ fail: fail, success: success, }); }, })
<view class="container"> <map id="map" longitude="{{longitude}}" latitude="{{latitude}}" scale="10" show-location style="width: 100%; height: 300px;"> map> view>
省市区及详情地址信息在返回的百度地图信息中都已经包含,如果想显示标记信息等内容,可以利用map组件的markers等属性
源码示例:小程序地图调用百度地图API显示地理信息
- 利用第三方插件wxParse: 微信小程序富文本解析,https://github.com/csonchen/wxParse
- Towxml:是一个可将
HTML
、Markdown
转为微信小程序WXML
(WeiXin Markup Language)的渲染库。用于解决在微信小程序中Markdown
、HTML
不能直接渲染的问题。https://github.com/sbfkcel/towxml
源码示例:小程序中使用echart图表功能
- 在页面中如果不设置 onShareAppMessage 分享的事件回调函数,那么小程序右上角三个点的操作中不包含分享功能
- 通过button按钮的open-type属性设置为share则将调用页面中的 onShareAppMessage 事件,可以通过事件的 res中的 from 内容来判断是按钮button的分享处理还是右上角三个点menu的页面分享操作
- 微信现已开放小程序内搜索,开发者可以通过
sitemap.json
配置,或者管理后台页面收录开关来配置其小程序页面是否允许微信索引。- 当开发者允许微信索引时,微信会通过爬虫的形式,为小程序的页面内容建立索引。
- 当用户的搜索词条触发该索引时,小程序的页面将可能展示在搜索结果中。
- 小程序的sitemap类似网页的sitemap概念,提供的是可被抓取的页面内容,主要针对的是“小程序搜索引擎的SEO”优化操作
支持双向数据绑定
但仅限于简易双向数据绑定,绑定的对象只能是一个单一字段的绑定,不支持对象等形式的数据路径设置操作
在自定义组件中也可以实现传递双向绑定操作
它的基本语法操作是
<input model:value="{{value}}" />
- wx.login获取到一个code,拿这code去请求后台得到openId, sessionKey, unionId。
- 调wx.getUserInfo获取用户信息内容
- 一次性授权:每次授权都需要与后台进行权限认证操作
- 永久授权:调取授权登录接口并把获取到的用户公开信息存入数据库
- 按钮触发的,open-type指定为getUserInfo类型,可以从bindgetuserinfo回调中获取到用户信息
- 授权验证操作只执行一次,不会二次执行
- 授权以后可以通过wx.getUserInfo获取基础的用户信息
用户授权包括很多内容:用户信息、地理位置、后台定位、录音功能、保存到相册、摄像头等
授权有效期:一旦用户明确同意或拒绝过授权,其授权关系会记录在后台,直到用户主动删除小程序。
授权操作主要分两种不同的情况:
- 弹出授权框用户点击允许,授权信息会直接记录,后续不再确认授权操作
- 弹出授权框用户点击拒绝,授权信息会直接记录,但用户还想再次操作对应功能,需要弹窗再次授权
- 查看所拥有权限
- wx.authorize 发起请求用户授权,利用 wx.showModal 弹窗授权确认
- wx.showModal 确认后利用 wx.openSetting 打开授权设置
- 确认授权设置打开授权信息
示例源码:位置授权示例,功能授权流程版
示例源码:位置授权示例,具体地理位置获取
节点布局相交状态 API 可用于监听两个或多个组件节点在布局位置上的相交状态。这一组API常常可以用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。
节点布局相交状态 API中有一个 wx.createIntersectionObserver(Object this, Object options) Api (支持版本 >= 1.9.3),它的作用是创建并返回一个 IntersectionObserver 对象实例(交叉区域),这个对象实例在小程序的解说如下:
IntersectionObserver 对象,用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见,它有:relativeTo、relativeToViewport、observe、disconnect等方法
由此我们可以设置图片进入可见界面某一区域时的监听回调事件,以此实现图片的懒加载
Page({ data: { group: [ { src: "https://csdnimg.cn/feed/20180914/c67d9521db939fc8beb9a27b046ef1a3.jpg", show: false, def: "https://img.alicdn.com/tps/i3/T1QYOyXqRaXXaY1rfd-32-32.gif" }, ...... // 更多图片信息 ] }, onLoad: function () { let group = this.data.group // 获取原数据 for (let i in group) { // 设置监听回调事件,当元素 .loadImg{{i}},进入页面20px内就触发回调事件,设置图片为真正的图片,通过show控制 wx.createIntersectionObserver().relativeToViewport({ bottom: 20 }).observe('.loadImg' + i, (ret) => { if (ret.intersectionRatio > 0) { group[i].show = true } this.setData({ // 更新数据 group }) }) } } })
<block wx:for="{{group}}" wx:key="1"> <view class="loadImg loadImg{{index}} {{item.show? 'active' : ''}}" > <image wx:if='{{item.show}}' style='width:100%;height:100%;' src='{{item.src}}'>image> <image wx:else style='width:20%;height:20%;margin:0 auto;margin-top:50%;transform:translateY(-50%);' src='{{item.def}}' mode='aspectFit'>image> view> block>
.loadImg{ width:100vw; height:46.3vw; transition: all .2s ease-in-out; opacity: 0; } .loadImg.active{ opacity: 1 }
示例源码:利用createIntersectionObserver实现图片懒加载
- 节点信息查询 API 可以用于获取节点属性、样式、在界面上的位置等信息
- 最常见的用法是使用这个接口来查询某个节点的当前位置,以及界面的滚动位置
- 可以利用获取节点信息动态计算scroll-view(纵向滚动需要定高)等组件的高度等内容
- 可以利用获取节点信息来确定页面中的元素显示与不显示,比如控制sticky吸顶操作
示例源码:通过查询节点信息确定页面中的元素显示与不显示
示例源码:通过查询节点信息动态计算scroll-view的高度值
- 需要判断用户是否授权了保存到本地的权限,通过getSetting可以获取authSetting,确认scope.writePhotosAlbum确认是否拥有
- 利用authorize进行授权请求操作,这是首次授权处理
- 如果拥有权限,则利用downLoadFile下载图片文件,再使用saveImageToPhotosAlbum进行图片保存相册的操作
- 如果没有授权,还想再次保存图片到相册操作,需要利用showModal进行对话框弹出确认操作,再次确认openSetting中的authSetting内容(需要用showModal),这是再次授权操作
示例源码:保存图片到手机相册
- 全局样式在app.wxss中设置,不管如何,一般会设置page的高度为100%
- 一般iconfont字图体标的内容在app.wxss中就已经@import引入了
- 访客AppId没有预览与真机调试功能
- 点击微信开发者工具上的真机调试,可以同步打开真机微信调试小程序应用
- 在真机上点击右上角的三个点,可以“打开调试/关闭调试”,“显示性能面板”等操作
- 真机上会出现vConsole控制台以及性能面板内容
- 查看console内容可以在电脑端进行查看,并且打开wxml元素审核,在电脑端选择相应的内容,在真机上则会选中相应的内容
- 如果小程序中的接口请求地址为localhost,那么真机调试时将无法调用到数据接口
- 简易处理方案是将手机与小程序开发设备调节至同一局域网络,然后将接口设置成ip地址形式,那么真机调试则可以正常请求接口
- 如果在微信管理平台将某人加入了小程序开发或者测试成员,并且该人员网络并不在公司局域网内,那么设置ip形式的模式也将无法进行真机调试操作
- 这种情况则可以利用内网穿透技术进行接口地址域名模式的转化:
- 打开http://u.tools,下载安装utools工具
- 然后再利用utools安装内网穿透插件
- 配置内网穿透插件,主要是外网域名需要设置一个唯一名称,而且内网地址及端口号需要设置正确,特别是端口号,如果现在是3000,那么设置3000端口
- 修改小程序中的config.js中的host地址为内网穿透插件所提供的地址内容
- 在真机上进行测试,则可以正常访问,但需注意可能略损耗一些网络速度,毕竟第三方做了中间处理
- 单行文本溢出
.scrollItem text { font-size: 26rpx; /* 单行文本溢出省略号代替 */ /* 不换行 */ white-space: nowrap; /* 内容隐藏 */ overflow: hidden; /* 省略号代替 */ text-overflow: ellipsis; /* overflow隐藏只对块级元素进行作用,所以需要将行内元素转成块级元素 */ display: block; }
- 多行文本溢出
.scrollItem text { font-size: 26rpx; /* 多行文本溢出省略号代替 */ /* 浏览器厂商前缀,webkit内核 */ display: -webkit-box; /* 内容隐藏 */ overflow: hidden; /* 省略号代替 */ text-overflow: ellipsis; /* 对齐的方向 */ -webkit-box-orient: vertical; /* 行数 */ -webkit-line-clamp: 2; }
个人类型的小程序暂不支持使用
H5地址需要在小程序后台添加H5域名白名单,如果webview里面还有跳转到其他的H5页面,也是需要添加域名白名单的
在网页内可通过
window.__wxjs_environment
变量判断是否在小程序环境webview内可以通过桥接方式进行监听,监听事件onPageStateChange可以确认小程序是否在前台
每个页面只能有一个 web-view,web-view 会自动铺满整个页面,并覆盖其他组件
避免在链接中带有中文字符,在 iOS 中会有打开白屏的问题,建议加一下 encodeURIComponent
web-view 网页与小程序之间不支持除 JSSDK 提供的接口之外的通信
在 iOS 中,若存在JSSDK接口调用无响应的情况,可在 web-view 的 src 后面加个#wechat_redirect解决
开发者工具上,可以在 web-view 组件上通过右键 - 调试,打开 web-view 组件的调试
webview中可以利用wx.miniProgram.navigateTo等方式跳转回小程序,跳转方法与小程序一致
跳转回小程序如果通过switchTab等方式进行操作,默认情况是不会重新加载数据,可以尝试如下方式:
- 利用onShow生命周期钩子函数,跳转之前设置全局变量,在onShow中进行条件判断是否进行业务逻辑操作(减少操作次数,优化性能)
- 页面重新加载
wx.miniProgram.switchTab({ url: '/pages/index/index' success: function(e) { var page = getCurrentPages().pop(); if (page == undefined || page == null) return; page.onLoad(); } })
- 利用button按钮进行用户授权及授权信息的获取,将userInfo基础信息进行本地缓存存储
- 利用wx.login获取登录凭证code,通过code与开发者服务器交互获取加密后的openId,并将openId与session_key进行服务器数据库信息存储
- 将加密后的openId信息进行本地缓存存储
- 用户进行后续请求,可以将userInfo以及openId信息进行发送,服务器端将openId进行解密,再对照数据库内容进行验证筛选与后续操作
目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体)
在微信小程序管理平台设置->基本信息的微信认证中进行确认,是否已经进行认证,认证过程需要提供公司相关信息,并且涉及到一定费用问题(微信公众平台申请微信认证,需支付300元/次认证费)
利用wx.login获取登录凭证code,通过code与开发者服务器交互获取加密后的openId,并将openId与session_key进行服务器数据库信息存储(后台利用nodejs、php、java等操作,具体参见:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html)
利用jsonwebtoken(或者其它加密方式,前后端人员需要确认)对openId进行加密传递回小程序端
利用button进行open-type的类型设置,值为getPhoneNumber,并且需要进行bindgetphonenumber事件绑定
绑定回调getPhoneNumber中可以找到手机加密数据
将加密的openId、encryptedData、iv等数据发送至服务器端
服务器端通过解密openId,查询sesskon_key,获取encryptedData、iv以后(4个内容),需要对加密手机等信息数据进行解密处理
解密介绍以及对应后台程序语言解密算法示例,https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html#%E5%8A%A0%E5%AF%86%E6%95%B0%E6%8D%AE%E8%A7%A3%E5%AF%86%E7%AE%97%E6%B3%95
通过解密以后的数据类似
可以将解密信息等内容进行返回小程序端处理
- 在列表中进行音、视频播放控制的时候不能创建多个音、视频播放器的实例对象
- 实例对象创建的多,性能极其低下
- 在功能操作的时候并不容易找到需要操作的实例对象
- 每个实例对象的状态不好控制与保持
- 需要利用单例来进行性能的优化处理,而且通过单例可以不需要查找实例对象,因为需要操控的只有一个实例
- 至于每个内容的状态可以保存在缓存数据中,在需要调用的时候从缓存数据中获取,将赋值给单一实例对象中
- 可以利用this.instance进行单例的设置,将实例对象挂载于当前页面的实例对象上
在进行多个对象进行同一事件绑定的时候需要进行目标对象的识别与获取数据操作,比如表单数据的统一获取处理(多个input框等数据内容的获取)
需要给多个对象设置区别的标识,比如id或者data-key等内容
给多个对象进行相同事件绑定操作
利用event获取区别标识以及数据信息
利用[]的方式进行动态赋值操作(不能使用对象路径形式)
handleInput(event) { let type = event.target.id; // 区别标识 this.setData({ [type]: event.detail.value, // 动态赋值 }); },
- 一般并不建议使用index下标作为循环的key值(虚拟DOM的Diff算法原理)
- 强烈建议使用唯一值进行循环中的key的属性设置
- 如果没有唯一值,则可以利用代码方式创建其唯一值,可以利用map循环生成新的数组对象
// 利用map循环进行唯一id的生成,需要注意的是map循环需要return返回加工以后的数组元素对象 let index = 0; let recentList = recentListData.weekData.map((item) => { item.id = index++; return item; }); this.setData({ recentList });
- 利用+号转换
- 利用*1转换
- 利用parseInt转换
- 还可以利用>>>0转换
小程序中唯一可以实现换行的标签组件是text。
注:text中不支持
只能使用n进行换行。
利用函数节流(throttle):函数在一段时间内多次触发只会执行第一次,在这段时间结束前,不管触发多少次也不会执行函数。
节流函数
const throttle=(fn, gapTime)=> { if (gapTime == null || gapTime == undefined) { gapTime = 1500 } let _lastTime = null // 返回新的函数 return function () { let _nowTime = + new Date() if (_nowTime - _lastTime > gapTime || !_lastTime) { fn.apply(this, arguments) //将this和参数传给原函数 _lastTime = _nowTime } } } module.exports = { throttle: throttle }
页面按钮
<button bindtap="handleTap">节流避免多次触发button>
脚本控制
import {throttle} from '../../utils/util.js'; Page({ handleTap:throttle(function(e){ console.log(this) console.log(e) console.log((new Date()).getSeconds()) },1000) })
示例源码:节流避免多次触发
通过设置button的伪元素样式进行去除: button::after{ display: none;}
惯性滚动会使滚动比较顺畅,在安卓下默认有惯性滚动,而在 iOS 下需要额外设置
-webkit-overflow-scrolling: touch
的样式
自定义组件向父组件进行事件发送操作,有些类似于Vue中的emit
在子组件中,可以利用this.triggerEvent(‘myevent’, myEventDetail, myEventOption)进行向上事件发送操作,myevent是事件名称,myEventDetail是附带事件参数,而myEventOption则是触发事件的选项包括:bubbles、composed、capturePhase等参数。
父组件中,则需要利用bind+myevent进行事件绑定操作
<my-component bindmyevent="myEventListener">my-component>
- 在开发过程中需要对数据请求进行统一的功能封装,但请求封装的操作过程也比较复杂,考虑的点与面也非常的多,如果没有极强的业务分析与代码编写能力,一般不考虑自行封装
- wx.request中没有interceptors拦截器操作,对于这部分内容需要自行考虑
- 可以利用flyio第三方请求类库进行数据请求的操作,包括拦截器等操作的设置,https://wendux.github.io/dist/#/doc/flyio/wx
配置信息
- 在
app.json
中的tabBar
项指定custom
字段,同时其余tabBar
相关配置也补充完整。- 所有 tab 页的 json 里需声明
usingComponents
项,也可以在app.json
全局开启。添加 tabBar 代码文件,在根目录下新建custom-tab-bar目录,并创建index.js、index.wxss、index.json、index.wxml等文件,目录结构与文件结构不可变
编写 tabBar 代码
用自定义组件的方式编写即可,该自定义组件完全接管 tabBar 的渲染。另外,自定义组件新增
getTabBar
接口,可获取当前页面下的自定义 tabBar 组件实例。
- pages字段:用于描述当前小程序所有页面路径,这是为了让微信客户端知道当前你的小程序页面定义在哪个目录。
- window字段:小程序所有页面的顶部背景颜色,文字颜色定义在这里的
- tabBar字段:小程序全局顶部或底部tab
- subpackages:分包结构配置
- requiredBackgroundModes:申明需要后台运行的能力,类型为数组
- sitemapLocation:指明 sitemap.json 的位置
- onLoad:页面加载,调一次
- onShow:页面显示,每次打开页面都调用
- onReady:初次渲染完成,调一次
- onHide:页面隐藏,当navigateTo或底部tab切换时调用
- onUnload:页面卸载,当redirectTo或navigateBack时调用
都是用来描述页面的结构;
都由标签、属性等构成;
标签名字不一样,且小程序标签更少,单一标签更多;
多了一些 wx:if 这样的属性以及 {{ }} 这样的表达式
WXML仅能在微信小程序开发者工具中预览,而HTML可以在浏览器内预览
组件封装不同, WXML对组件进行了重新封装,
小程序运行在JS Core内,没有DOM树和window对象,小程序中无法使用window对象和document对象。
都是用来描述页面的样子;
WXSS 具有 CSS 大部分的特性,也做了一些扩充和修改;
WXSS 新增了尺寸单位,WXSS 在底层支持新的尺寸单位 rpx,规定屏幕宽为750rpx;
WXSS 仅支持部分 CSS 选择器,类、ID、元素、层级、after和before伪类选择器
WXSS 提供全局样式与局部样式
- 分包主要包括:使用分包、独立分包、分包预下载
- 分包:主包添加跳转路径,分包放内容,在app.json配置subpakeages声明项目分包结构。代码包总包大小为20M,单个主包/分包大小不能超过2M。
- 按照功能划分的打包原则:可以按照功能的划分,拆分成几个分包,当需要用到某个功能时,才加载这个功能对应的分包;公共逻辑、组件放在主包内。
- 首次启动时,先下载小程序主包,显示主包内的页面;如果进入了某个分包的页面,再下载这个对应分包,下载完毕后,显示分包的页面,
- 总结:首先配置好打包路径,tabbar页面必须在主包内,各分包之间不能互相调用,能调用的都在主包内
- 小程序中不存在跨域的问题,所以可以进行授权地址的请求处理
- 小程序中需要在管理平台设置对应可访问的授权地址,可以设置多个,最多20个域名设置
- 只能支持https协议
- 最大并发数为10个,socket的并发限制为5个
- 查看当前小程序所有打开页面的数据信息,方便开发人员进行程序调试操作
- 可以以tree树形结构以及code编码两种不同的模式进行查看,能够利用搜索快速找到对应的数据信息
- 可以对数据信息进行人员手动修改,以便确认当前程序运行的过程与结果是否匹配,减少不断重复代码调试的步骤
- 不管是nodejs的express、koa,还是vue或者是react,包括小程序,这些应用框架中都包含了一个基本核心概念也就是路由
- 所有应用框架中的路由都有共通性,主要包括:静态路由表、分配地址、统一入口、寻址以及过滤5大部分内容
- 小程序因为针对的主要是移动端应用,所以其路由操作相对比较简单,在app.json项目全局配置文件中通过pages节点内容进行设置
- pages是一个单一数组,数组内容是路由地址信息,而这个数组内容就是路由概念中的静态路表表概念
- 分配地址是pages中所设置的地址,对应的是地址所指向的目录与页面
- 因为同一个小程序项目内容都是由一个全局配置文件分配,所以对应的入口操作是唯一的
- 利用switchTab、reLaunch、redirectTo、navigateTo、navigateBack可以实现路由导航跳转操作,而跳转的过程实质就是寻址过程,寻址过程就是指向地址与路由地址的匹配操作
- 因为小程序页面结构相对简单,用户没有手动输入页面地址的操作,所以类似404这样的路由过滤操作并不明显
- 应用是完成一整套复杂的功能,包含众多的页面,页面中会使用很多的组件
- 页面是一个功能整体,一个页面是由一个至多个组件组成
- 组件再复杂也不能代表页面,只能代表页面中的一部分
- 同一个邮箱只能申请注册1个小程序
- 个人和个体工商户可以注册5个小程序
- 企业资质可以注册50个小程序
- 在小程序后台添加位置,展示这个小程序。当用户在此地点的周围,可在微信小程序入口中“附近的小程序”发现并使用小程序提供的服务
- 附近的小程序地点创建要求:
- 地点的经营主体跟小程序帐号主体一致或相关
- 能提供经营资质信息,如营业执照或组织机构代码证等
- 一个经营资质只能添加一个地点,一个地点只能展示一个小程
可以,登陆公众号点击自定义菜单即可设置
小程序只支持一种支付方式,也就是微信支付
不支持支付宝支付,微信与支付宝属于互相竞争的关系,是两个不同的支付平台,目前是不支持互相通用的。微信小程序里面的程序软件属于内嵌于微信的服务,支持微信支付,但不能使用支付宝支付。也就是说:
在小程序中生成支付宝二维码的方式,不可行
在小程序中内嵌H5网页后调用支付宝支付接口,也不可行,由于支付协议
那么我通过诱导的方式直接在浏览器使用支付呢?也就是:
通过点击某个链接直接跳出小程序自动跳转到系统浏览器的方式,也不可行,原因:
微信小程序没办法直接跳转打开app、网址、手机浏览器,但是可以直接打开其他的小程序并跳转到指定的小程序页面
微信公众号可以直接打开app或app指定页面,可以直接打开手机浏览器并跳转指定网址,可以打开小程序或进入小程序指定页面。
一定要实现支付宝支付:
- 通过诱导的方式在小程序中生成你需要在浏览器中打开使用支付页面的链接地址
- 诱导用户手动复制网址并手动切换到系统浏览器中使用,该地址有订单Id等参数信息
- 将小程序的订单内容切换至网页端,利用网页端支付流程序去实现支付宝订单支付操作
线下扫二维码,好友、群、朋友圈分享二维码,公众号关联进入等60多个入口
小程序的排名规则:
- 小程序上线时间越早,排名越靠前
- 描述中出现完全匹配出现关键词次数越多,排名靠前
- 标题中关键词出现1次,且整体标题的字数越短,排名靠前
- 微信小程序用户使用数量越多,排名靠前
- 小程序的名称作为核心关键词语排名
- 关键词必须为小程序提供的服务,或小程序提供服务的品牌
- 禁止使用其他品牌名称
- 禁止使用未经授权的名人名称
- 禁止涉及色情、暴力、政治敏感
- 禁止使用单字符
- 禁止在关键词中使用特殊符号
- 企业、政府、媒体、其他组织主体可以注册50个小程序,个体户和个人类型主体可注册5个小程序
- 公众号可关联同一主体的10个小程序,不同主体的3个小程序
- 小程序可最多被50个公众号关联
- 公众号一个月可新增关联同主体的10个小程序、不同主体的3个小程序
- 一个小程序一个月内可被公众号关联50次
开发版:本地代码进行上传提交以后会发布到开发版本
体验版:可以将指定的开发版本设置成体验版本
审核版本:将对应的开发版本进行提交审核操作,审核版本需要小程序官网审核确认
线上版:最终终端用户可以看到的线上应用版本
通过 __wxConfig.envVersion 能判断用户所在的小程序版本
console.log('envVersion',__wxConfig.envVersion);
微信小程序项目结构主要有四个文件类型,如下
- WXML (WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。内部主要是微信自己定义的一套组件。
- WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式,
- js 逻辑处理,网络请求
- json 小程序设置,如页面注册,页面标题及tabBar。
- 5app.json
- 必须要有这个文件,如果没有这个文件,项目无法运行,因为微信框架把这个作为配置文件入口,整个小程序的全局配置。包括页面注册,网络设置,以及小程序的window背景色,配置导航条样式,配置默认标题。
- app.js
- 必须要有这个文件,没有也是会报错!但是这个文件创建一下就行 什么都不需要写以后我们可以在这个文件中监听并处理小程序的生命周期函数、声明全局变量。
- app.wxss
优势:
无需下载,通过搜索和扫一扫就可以打开。
- 良好的用户体验:打开速度快。
开发成本要比App要低。
安卓上可以添加到桌面,与原生App差不多。
为用户提供良好的安全保障。小程序的发布,微信拥有一套严格的审查流程, 不能通过审查的小程序是无法发布到线上的。
不足:
- 限制较多。页面大小不能超过2M,不能打开超过5个层级的页面。
- 样式单一,小程序的部分组件已经是成型的了,样式可改进的内容比较少,例如:幻灯片、导航。
- 推广面窄,不能分享朋友圈,只能通过分享给朋友,附近小程序推广,其中附近小程序也受到微信的限制。
- 依托于微信,无法开发后台管理功能。
- 运行环境的不同:传统的HTML5的运行环境是浏览器,包括webview。微信小程序的运行环境并非完整的浏览器,是微信开发团队基于浏览器内核完全重构的一个内置解析器,针对小程序专门做了优化,配合自己定义的开发语言标准,提升了小程序的性能。
- 开发成本的不同:只在微信中运行,所以不用再去顾虑浏览器兼容性,不用担心生产环境中出现不可预料的奇妙BUG
- 获取系统级权限的不同:系统级权限都可以和微信小程序无缝衔接
- 应用在生产环境的运行流畅度:长久以来,当HTML5应用面对复杂的业务逻辑或者丰富的页面交互时,它的体验总是不尽人意,需要不断的对项目优化来提升用户体验,但是由于微信小程序运行环境独立。
- 一般情况在onLoad中进行数据请求,onLoad钩子函数在生命周期过程中最先触发,但在视图层也可以查看到渲染的数据,所以建议在onLoad中进行请求
- onLoad钩子函数只触发一次,如果想要多次触发并且进行对应的数据请求,则需要在onShow钩子函数中进行处理,比如通过navigateTo进行路由跳转以后,再返回页面,那么onLoad中的数据请求操作将不会触发,只能在onShow中进行请求
- onShow在每次页面打开以后都会触发,如果在该钩子函数中进行数据请求操作,一定需要注意条件判断的处理,以便实现最少请求次数进行性能优化
- 在进行事件绑定与触发的时候,通常event对象中会包含target与currentTarget,而绝大多数情况下,这两个对象内容是一样的,但在某些特定情况下会产生区别:
- target:触发事件的对象不一定是绑定事件的对象, 如: 事件委托
- currentTarget:绑定事件和触发事件的一定是一个对象
浏览器端的本地存储有哪些方式,主要包括:
- localStorage 持久化存储,一般大小是5M
- sessionStorage会话级存储,一般大小是5M
- IndexedDB类似mongodb是对象化存储,无限存储,有兼容性障碍
- Web SQL类似于MySql是关系型存储,无限存储,有兼容性障碍
- Cookie存储,一般大小是4K,可能会被用户禁用
小程序的存储方式只有storage,需要注意的事项:
- 将数据存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容。除非用户主动删除或因存储空间原因被系统清理,否则数据都一直可用。
- 单个 key 允许存储的最大数据长度为 1MB,所有数据存储上限为 10MB。
- 页面下拉刷新
- 对于Page可以实现下拉刷新操作,但需要设置enablePullDownRefresh的属性
- 页面的onPullDownRefresh可以进行下拉刷新的事件监听,wx.startPullDownRefresh可以开始下拉刷新,而wx.stopPullDownRefresh则可以停止下拉刷新,实现回弹操作
- scroll-view下拉刷新
- scroll-view的下拉刷新事件绑定可以利用bindrefresherrefresh实现
- 要实现回弹得先声明一个trigger布尔数据值
- 然后再给scorll-view设置refresher-triggered的属性值为trigger数据值
- 在完成bindrefresherrefresh下拉刷新任务内容以后,对trigger布尔值设值为false实现下拉刷新的回弹
- id是唯一值的传递
- id的获取可以利用event.target.id进行接收
- data-kay可以进行多个属性设置与传递操作
- data-key的获取可以利用event.currentTarget.dataset.keyName进行接收
比较项 | 小程序 | Wepay | Mpvue | mpx | Uniapp |
---|---|---|---|---|---|
语法规范 | 小程序开发规范 | 类Vue规范 | Vue规范 | 小程序+Vue+自定义规范 | Vue规范 |
标签集合 | 小程序标签 | 小程序标签 | html+小程序标签 | 小程序标签 | html+小程序标签 |
样式规范 | wxss | sass、less、stylus | sass、less、postcss | sass、less等 | sass、less、stylus |
组件化 | 小程序组件 | 自定义组件 | vue组件 | 自定义组件 | vue组件 |
多端复用 | 不支持 | 转H5 | 转H5 | 多端(微信,支付宝,百度,qq和头条…) | 多端(微信,支付宝,百度,qq和头条…) |
自动构建 | npm包使用 | npm包使用 | webpack | webpack | webpack+vue.config.js |
上手成本 | 全新 | 熟悉vuejs | 熟悉vuejs | 小程序+vue+自已语法 | 熟悉vuejs |
集中数据管理 | 不支持 | 不支持 | vuex | vuex | vuex |
生产商 | 微信 | 微信 | 美团(停更) | 滴滴 | dcloud |
- 微信小程序采用JavaScript、WXML、WXSS三种技术进行开发,从技术讲和现有的前端开发差不多,但深入挖掘的话却又有所不同。
- JavaScript:首先JavaScript的代码是运行在微信App中的,并不是运行在浏览器中,因此一些H5技术的应用,需要微信App提供对应的API支持,而这限制住了H5技术的应用,且其不能称为严格的H5,可以称其为伪H5,同理,微信提供的独有的某些API,H5也不支持或支持的不是特别好。
- WXML:WXML微信自己基于XML语法开发的,因此开发时,只能使用微信提供的现有标签,HTML的标签是无法使用的。
- WXSS:WXSS具有CSS的大部分特性,但并不是所有的都支持,而且支持哪些,不支持哪些并没有详细的文档。
- 微信的架构,是数据驱动的架构模式,它的UI和数据是分离的,所有的页面更新,都需要通过对数据的更改来实现。
- 小程序分为两个部分webview和appService。其中webview主要用来展现UI,appService有来处理业务逻辑、数据及接口调用。它们在两个进程中运行,通过系统层JSBridge实现通信,实现UI的渲染、事件的处理
- 提高页面加载速度
- 用户行为预测
- 减少默认data的大小
- 组件化方案
- 控制包的大小
- 压缩代码,清理无用代码
- 采用分包策略
- 启用本地缓存
- 参考地址:https://blog.csdn.net/wu_xianqiang/article/details/108037685
- wx:if 通过条件判断确认对象的显示与否,有更高的切换消耗。
- hidden利用样式来控制对象的显示与隐藏,有更高的初始渲染消耗。
- 因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好。
- 对比v-if和v-show,性质雷同,但小程序是通过hidden作为条件,vue里是show作为条件
- 大数据量,特别是循环遍历数组追加的时候,进行的是一次性单个setData的数据设值,前期等待时间比较长,用户体验相对较弱,但应用的整体性能比较好
- 对于同样的情况,如果在循环体内进行setData的多性设值与页面渲染操作,那么应用实现的是多次渲染处理,界面内容逐步更新,用户体验相对较好,但对应用的整体性能损耗较大
- 如果多个页面都需要获取系统信息,那么wx.getSystemInfo是否在多个页面不断调用(不需要)
- 可以在app.js的onLaunch生命周期钩子函数中进行调用,然后将系统信息存储于globalData中,这样所有页面可以直接获取全局的globalData数据内容,以减少wx.getSystemInfo内容的重复调用
- 有三个点的白屏(左侧): 下载代码包的阶段
- 没有三个点的白屏(中间): 业务代码注入和渲染的阶段
- 加载中(右边): 业务代码中异步请求数据
- 总的来说,小程序呈现到用户面前,实际上经历了下面两个阶段:
- 运行环境的加载:这步是微信做的,微信会在用户打开小程序之前就已经准备好环境,用户点击小程序入口后,直接下载小程序的代码包即可。
- 下载代码包:小程序代码包里面的代码,不是小程序的源代码,而是编译、压缩、打包之后的代码包。
下图中,左侧的“预加载”对应的是运行环境的预加载,右侧的“小程序启动” 对应的是下载代码包启动小程序。
小程序提供的运行环境,分为逻辑层(AppService)和 视图层(webView),逻辑层是执行javascript的地方,视图层是渲染页面的地方。当小程序的代码包下载完毕后,业务代码分别注入逻辑层和渲染层。
提升加载性能的最最最关键性一点是,控制包的大小,这个也是微信官方的说法。
- 压缩代码,清理无用的代码
- 图片放在cdn
- 利用iconfont进行图标应用,并且图标操作只留css样式文件,其它文件则删除不使用
- 如果使用echart图表,可以下载echart源码,利用配置操作发布指定功能的自定义的echart图表文件
- 采用分包策略
- 分包预加载
- 独立分包(版本要求有点高)
- onLoad 阶段就可以发起请求,不用等ready
- 如果业务要求在ready中进行数据请求,需要利用条件判断减少请求次数
- 请求结果放在缓存中, 下次接着用
- 请求中可以先展示骨架图
- 先反馈,再请求。比如说,点赞的按钮,可以先改变按钮的样式,再发起异步请求。
- 每调用一次setData, 都是逻辑层向渲染层的一次通讯,这个通信还不是直接传给webView, 而是通过走了native层,通讯的开销很大。
- 渲染层收到通讯后,还需要重新渲染出来,所以一次setData带来两次开销:通信的开销 + webview更新的开销。
- 在数据传输时,逻辑层会执行一次
JSON.stringify
来去除掉setData
数据中不可传输的部分,之后将数据发送给视图层。同时,逻辑层还会将setData
所设置的数据字段与data
合并,使开发者可以用this.data
读取到变更后的数据。
**减少setData的数据量:**如果一个数据不会影响渲染层,则不用放在setData里面
合并setData的请求,减少通讯的次数
列表的局部更新:
- 在一个列表中,有
n
条数据,采用上拉加载更多的方式,假如这个时候想对其中某一个数据进行点赞操作,还能及时看到点赞的效果。- 此时,可以采用setData全局刷新,点赞完成之后,重新获取数据,再次进行全局重新渲染,这样做的优点是:方便,快捷!缺点是:用户体验极其不好,当用户刷量100多条数据后,重新渲染量大会出现空白期(没有渲染过来)。
- 如果采用布局刷新,将点赞的
id
传过去,知道点的是那一条数据, 将点赞的id
传过去,知道点的是那一条数据。- 重新获取数据,查找相对应id的那条数据的下标(
index
是不会改变的),用setData进行局部刷新this.setData({ list[index] = newList[index] })
**小心后台页面的js:**定时器、事件监听、长连接等会影响性能的js操作对象需要在页面跳转的时候进行清除。原因是:小程序中可能有n个页面,所有的这些页面,虽然都拥有自己的webview(渲染层), 但是却共享同一个js运行环境。也就是说,当你跳到了另外一个页面(假设是B页面),本页面(假设是A页面)的定时器等js操作仍在进行,并且不会被销毁,并且会抢占B页面的资源。
**小心onPageScroll:**pageScroll 事件,也是一次通讯,是webview层向js逻辑层的通讯。这次通讯也是开销较大,如果考虑到这个事件被频繁的调用,回调函数如果有复杂的setData的话, 性能就会很差了。
- 只有在必要的时候监听onPageScroll事件
- 避免在onPageScroll中进行复杂的逻辑处理
- 避免在onPageScroll中频繁的setData调用
- 避免频繁查询节点信息selectQuery操作
**小心获取节点位置:**少用selectQuery,利用intersectionObject进行节点信息获取的替代
**尽可能使用小程序组件:**自定义组件的更新只在组件内部进行,不受页面其他不能分内容的影响;比如一些运营活动的定时模块可以单独抽出来,做成一个定时组件,定时组件的更新并不会影响页面上其他元素的更新;各个组件也将具有各自独立的逻辑空间。每个组件都分别拥有自己的独立的数据、setData调用。
- 在微信开发者工具没有办法复现某些性能问题,是因为从逻辑层到webview的通讯,开发者工具底层是通过onpostMessage, 微信ios好像是微信自己实现的桥接,所以强烈建议使用真机进行调试
- 微信开发者工具,没有办法在【network】里面看到图片资源的加载,通过【trace】面板连接安卓真机也没有办法看到。如果想测试懒加载的效果,就比较麻烦,需要通过设置微信开发者工具的代理到127.0.0.1,通过charles可以抓包看到
体验评分是一项给小程序的体验好坏打分的功能,它会在小程序运行过程中实时检查,分析出一些可能导致体验不好的地方,并且定位出哪里有问题,以及给出一些优化建议。
使用流程:在调试器区域切换到
Audits
面板。 点击”开始“按钮,然后自行操作小程序界面,运行过的页面就会被“体验评分”检测到。点击 “停止" 则结束检测,在当前面板显示相应的检测报告,开发者可根据报告中的建议对相应功能进行优化。 如需再次运行体验评分,可点击报告上方的“清空体验评分”恢复初始状态。请注意,目前系统不提供报告存储服务,一旦清空体验评分,将无法再查看本次评分结果。自动运行:为了方便开发者能够及时发现小程序的体验问题,小程序还支持体验评分的 “自动运行” 功能。该功能会在开发调试小程序时,实时检查,一旦发现体验分数低于
70
分时,系统会在console
面板打印一个warning
信息提示开发者,此时开发者可以切到Audits
面板查看详情。开发者在工具的右上角 “详情” 面板的 本地设置 中勾选 “自动运行体验评分” 选项即可开启。
- 我们的功能里面有个滚动到底部加载的功能,优化前我们的做法是这样的:
- 大部分人面对长列表滚动的时候,一开始的处理方式都是这样的,如果数据不多,只有几页可能不会太暴露问题,如果页数过多,几十页甚至上百页的情况,list的数据会越来越大,每次setData的数据就会越来越多,因而每次页面重新渲染的节点就会越来越多,从而导致滚动到后面,加载越来越慢。
- 另外,由于小程序的视图渲染层和数据逻辑处理层是分开的,不是在同一个线程上面的,从用户触发页面交互,到处理数据逻辑,最后层现页面,数据到视图是需要传输的,因而小程序本身对数据大小也有限制,不能超过1M。
// 只阐述逻辑,非真实代码 // 1: 初始一个list,存储列表数据 data = startList // 2: 监听滚动事件,滚动到底部获取新数据,并追加到list尾部,最后重新setData onReachBottom:()=>{ const {list} = this.datajs fetchNewData().then((res)=>{ list.push(res.list); this.setData({list}) // 数据更新操作(注意的重点) } }
- 利用setData数据路径优化:可以通过数据路径的写法来将数据分批的传输到视图层中,减少一次性setData的数据大小。具体写法如下:
// 1.通过一个二维数组来存储数据 let feedList = [[array]]; // 2.维护一个页面变量值,加载完一次数据page++ let page = 1 // 3.页面每次滚动到底部,通过数据路径更新数据 onReachBottom:()=>{ fetchNewData().then((newVal)=>{ // 利用数据路径分批设置数据进行传递 this.setData({ ['feedList[' + (page - 1) + ']']: newVal, }) } } // 4.最终我们的数据是[[array1],[array2]]这样的格式,然后通过wx:for遍历渲染数据
- 就是渲染页面时,一次性发送了过多的图片请求,导致了同一时间发起了过多的http请求,http连接是非常耗时的,尤其是一次性发起这么多,并且一次性发起的http链接也是有限制的,比如chrome浏览器就限制一次性最多6个。
- 所以在渲染页面时,不在视图范围内的图片我们不加载,只有元素出现在视图范围内了,再渲染。
- 常规的做法是,通过
getBoundingClientRect()
获取元素的位置,然后与页面滚动位置比较,如果出现在视图内,就将img
显示。这种方式有2个问题
- getBoundingClientRect()方法调用本身容易引起页面重排
- 监听滚动事件本身就频繁触发,虽然可以通过节流的方式来减少,但还是容易增加无谓代码处理
- 这个问题就是指图片尺寸太大了,而页面上我们显示的尺寸又太小了,图片尺寸大,请求图片就越慢,导致页面渲染速度下降。
- 对于页面里面的图片,最好都把图片存储在cdn服务器上,一个是能充分利用cdn缓存来加快请求速度,另外一个就是cdn上能够将图片进行一定的处理,比如裁剪。就是通过cdn来响应图片处理,然后请求图片时告诉cdn服务器需要什么要的尺寸图片,由cdn服务器响应对应尺寸图片。
- 比如阿里云oss图片缩放:https://help.aliyun.com/document_detail/44688.html?spm=5176.13910061.sslink.1.1a38601648eLCx
key值在列表渲染的时候,能够提升列表渲染性能,为什么呢?首先得想想小程序的页面是如何渲染的,主要分为以下几步:
- 将wxml结构的文档构建成一个vdom虚拟数
- 页面有新的交互,产生新的vdom数,然后与旧数进行比较,看哪里有变化了,做对应的修改(删除、移动、更新值)等操作(对比vue、react)
- 最后再将vdom渲染成真实的页面结构
key值的作用就在第二步,当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。key值如果不指明,默认会按数组的索引来处理,因而会导致一些类似input等输入框组件的值出现混乱的问题。
- 不加key,在数组末尾追加元素,之前已渲染的元素不会重新渲染。但如果是在头部或者中间插入元素,整个list被删除重新渲染,且input组件的值还出现了混乱,值没有正常被更新
- 添加key,在数组末尾、中间、或者头部插入元素,其它已存在的元素都不会被重新渲染,值也能正常被更新
因而,在做list渲染时,如果list的顺序发生变化时,最好增加key,且不要简单的使用数组索引当做key,需要用唯一值当成key。
使用 WebP 格式,WebP 是 Google 推出的一种支持有损/无损压缩的图片文件格式,得益于更优的图像数据压缩算法,其与 JPG、PNG 等格式相比,在肉眼无差别的图片质量前提下具有更小的图片体积(据官方说明,WebP 无损压缩体积比 PNG 小 26%,有损压缩体积比 JPEG 小 25-34%)
需注意android设备支持webp格式,但ios设备不支持webp格式
- 可以从降低网络请求时延、减少关键渲染的节点数这两个角度出发,缩短完成 FMP(首次有效绘制)的时间。
- 骨架屏的应用从用户感知的角度可以优化加载体验。
- 列表循环的时候,每个子元素如果都需要进行事件绑定将会损耗大量的属性设置以及事件绑定操作,降低应用的性能
- 可以将事件委托于父元素,这样就只需要进行一个事件对象的绑定操作即可,性能可以得到极大的提升
- 而且子元素不管是固定还是动态追加,都可以利用事件冒泡触发委托于父元素的事件回调函数
在屏幕滚动与拖拽的时候,经常会用到一些持续触发的事件,而这类事件不可控触发频率非常高,大大影响了性能,而我们想要让其变得可控,就可以用到节流和防抖两种方案。
- 防抖:指的是事件在高频触发状态时,只收集事件最后一次执行的结果。例如滚动时候产生的scrollTop,只收集停止滚动时候的scrollTop,实现原理是每次滚动触发时,都清除定时器队列,只执行最后一个定义的定时器。
// 由于作用域的原因,let timer必须放在页面构造器Page外边,否则无法清除定时器队列,导致重复触发! let timer; Page({ debounce(e){ clearTimeout(timer); timer = setTimeout(() => { console.log(e.detail.scrollTop) }, 500); } })
- 节流:指的是降低事件的触发频率,周期性获取事件的执行结果,例如滚动1像素便会触发的滚动事件,我们可以让它周期性每隔一段时间执行一次。实现原理是下一个定时器任务必须等待当前定时器任务执行完才执行。
Page({ data: { lock: true }, throttling(e){ let timer if(this.data.lock){ this.setData({ lock: false }) setTimeout(()=>{ this.setData({ lock: true }) console.log(e.detail.scrollTop) },500) } } })
- 利用事件总线替代组件间数据绑定的通信方式,WXML 数据绑定是小程序中父组件向子组件传递动态数据的较为常见的方式,在此过程中,不可避免地需要经历一次组件的 setData 调用方可完成任务,这就会产生线程间的通信。通过事件总线(EventBus),也就是发布/订阅模式,来完成由父向子的数据传递。子组件被创建时事先监听数据下发事件,当父组件获取到数据后触发事件把数据传递给子组件,这整个过程都是在小程序的逻辑层里同步执行,比数据绑定的方式速度更快。
- 不过需要注意事件发布与订阅的次数的合理性问题,如果在不合适的位置进行订阅操作可能会出现多次重复订阅同一事件问题
- 在合适的位置进行订阅取消操作,防止无效订阅操作
- 小程序request请求最大并发数为10个,需要合理控制最大并发数
- 超出并发限制数目的 HTTP 请求将会被阻塞,需要在队列中等待前面的请求完成,从而一定程度上增加了请求时延。
- 对于职责类似的网络请求,最好采用节流的方式,先在一定时间间隔内收集数据,再合并到一个请求体中发送给服务端,以便实现请求合并操作
视频列表多个video视频播放器性能极差(视频播放器本身占用资源大)
优化方案:
- 将列表中的视频组件更换成image组件,列表中没有视频组件
- 要对某个视频进行播放,选中时再将image替换成video,这样列表中的视频组件有且只有一个,可以极大提升列表及播放器等性能
如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过
unionid
来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的unionid
是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid
是相同的。
- WeUI:WeUI 是微信官方出品的组件库,它沿用了微信的视觉设计与交互设计,提供了各类原生组件的基础样式,风格简约大方。选用这一套组件库,可以让你的小程序与微信本身保持一致的界面风格。
- Vant-Weapp:适用于电商、餐饮、外卖平台、票务预订等购物类小程序
- ColorUI:ColorUI 是由文晓港发布的高颜值组件库,侧重于视觉交互,适用于日记类、记账类、博客、Vlog 类小程序
- iView-Weapp:了解vue技术,使用iview进行后台管理系统开发人员应该对iview的UI框不会陌生
- TaroUI:TaroUI 是由京东·凹凸实验室发布的多端 UI 组件库。这套组件库,可以在 H5、微信小程序、支付宝小程序、百度小程序多端适配运行,适用小程序:工具、读书、资讯、教育、商务等,但Taro主要的技术体系是React技术方向
- WuxUI:适用于开发工具类小程序,项目更新还是比较及时的
- 准备工作:收集表单项数据
- 验证过程主要分成两大部分,一部分是对前端数据有效性的认证,主要通过正则等方式进行操作处理,第二部分是对后台返回的数据进行验证,通常利用的是状态进行判断
- 前端验证
- 用户输入的内容是否合法(利用正则表达式对不同的表单数据进行条件判断)
- 前端验证通过才发请求进行后端验证
- 后台开发操作
- 收集请求的参数
- 根据用户的信息查询数据库
- 如果查不到到该用户,该用户不存在,直接返回
- 如果查到该用户,匹配用户密码,如果密码正确返回对应的数据
- 后端验证
- 对后台返回的数据进行获取
- 先判断正常的状态码信息,比如200状态码
- 然后对指定的非正常状态码进行逐一判断,该状态码由后台开发接口进行指定,并不是标准http的状态码
- 对除上述两种状态以外的状态作统一操作,以减少状态码判断操作的类型
- 需求: 某些项目后台接口需要利用header头信息中的cookie内容进行是否为合法用户的判断操作,所以在指定接口请求的时候需要前端传递合法cookie有效值
- 小程序端cookie的获取与传递实现:
- 用户登录的时候获取到用户的cookie,将用户的cookie存入至本地
- 在统一的请求接口封装函数中对request部分设置header属性,并且设置其cookie值
- 只需要进行统一设置即可,因为如果接口不需要cookie,我们进行传递也不会有任何影响,但需要cookie的时候,则需要一定传递
- 注意点:
- 只有在登陆的时候存cookie
- 读取cookie设置header的时候注意数据类型
- cookie要求必须是字符串
- 导航切换时通常会进行不同的数据列表获取,则需要添加Loading加载指示器以便进行用户体验的提升
- 导航切换的时候就需要开始Loading加载指示器
- 在数据获取并进行setData设值以后再进行Loading加载指示器的隐藏操作
- 在切换导航的时候,一般会考虑将之前的数据信息进行清除,这样有利于用户体验的提升
- 在进行音、视频播放的时候会涉及到播放不同的音、视频内容
- 一般会要求应用能够记录每一个音、视频播放的历史记录点,以便于下次播放可以从指定位置开始
- 我们可以将音、视频播放的记录存储于本地缓存当中,存储的方式是数组对象
- 要求是每个对象只保留一条信息记录,需要记录音、视频的唯一标识以及音、视频的播放进度时间等信息
- 再次播放的时候可以先通过音、视频唯一标识进行数据匹配,找到对应的播放进度时间,然后再进行播放操作
- 不管是新闻列表、产品列表、订单列表等内容都有可能会导航跳转至对应的详情页
- 因为要显示指定的详情信息,所以需要进行参数的相应操作
- 一般来讲涉及到参数包括:设参、传参、接参、用参等4个部分,但是到底是需要将列表中的整个数据对象进行传递还是只传唯一标识是需要思考的问题
- 一般情况并不会将整个对象进行传递,因为这种传递模式数据量比较大,而且导航参数传递又只支持字符串模式,所以需要进行数据类型转化操作,转化过程也会出现一定的问题
- 而且导航参数一般会有长度的限制
- 关键的因素是列表页只会显示一部分关键信息,它们与详情页的数据并不是完整对应的,详情页的数据一般会比较完整,字段信息内容会更多
- 所以会考虑传递唯一标识符的传递,这样传递的数据内容比较少,速度比较快,但是在详情页则需要进行与后台的交互进行进一步的数据接口请求
- 需要考虑详情页数据请求操作在哪个钩子函数中进行处理,如果在onLoad或者onReady中,只会执行一次,在onShow中又是多次查询,所以需要条件判断来确认是否有必要进行再次请求操作,以优化性能
- 订单中心界面中订单的状态包含多种多样
- 用户可以在不同的状态订单下进行滑动切换以及上拉加载等操作
- 在不同状态订单列表切换过程中,需要查看到的是之前界面中原来查看的数据与状态
- 基于性能优化的考虑,需要将每个状态的数据进行单独的存储与记录,这里就涉及到选项卡循环与定位、当前的选项卡下标、订单列表、分页、加载状态等信息。
- 为了实现左右滑动手势操作等,可以利用swiper组件进行不同订单状态的列表功能
- 对于数据部分需要利用二维数组进行存放,这样每个状态订单的数据都不会产生冲突:
- 订单数据:将每个状态下的订单根据tabs做对应,存放于orders对象当中
- 分页码:可以以一维数组进行不同tabs分页码的记录
- 加载状态:确认每个状态下的订单数是否是,不可载加、可加载、加载完毕等不同加载状态
data: { mainHeight: 0, // swiperCurrentIndex: 0, // 当前swiper的下标 tabs: ['全部', '待付款', '待收货', '已完成', '已取消'], // 订单数据 订单数组和订单状态数组元素一致 orders: [[], [], [], [], []], // 订单页码 pages: [1, 1, 1, 1, 1], // 加载状态 loadingTypes: [3, 3, 3, 3, 3], },
注意:可能需要利用createSelectorQuery获取swiper以及scroll-view的高度,因为它们的高度都是定高的,所以可以动态计算与赋值
- 购物车数据本地缓存存储模式,单设备存储与应用,切换设备将无法同步,但性能优良
- 以id为参数模式的操作方式
- 用户查看产品详情,将产品添加到购物车,而购物车中生成的是一个单一数组,类似[1,2,1,1,3,4,4]
- 1,2,3,4为产品id,出现的次数为购买的数量
- 在购物车清单页面需要进行再次的数据请求与查询
- 选中购物车产品等操作则增加程序复杂层度
- 以对象为参数模式的操作方式
- 用户查看产品详情,将产品添加到购物车,而购物车中生成的是一个对象数组,将会把产品整体对象传递并存储于数组当中
- 可以给数组对象添加count(购买数量),selected(是否选中)等属性值
- 在购物车清单页面不再需要进行数据请求与查询操作,减少性能开销
- 选中购物车产品等操作简化程序复杂层度
- 购物车数据远程序服务器存储模式,与本地设备无关,切换设备也可以同步数据,请求次数多,服务器压力大,性能略低下
- 将用户信息、产品id以及购买数量等信息作为参数进行订单接口的请求操作
- 由服务器端进行订单内容的查询、新增、更新与删除的操作
- 订单列表页则需要进行订单列表接口的请求获取与显示操作
- 每个商品信息任何一次变化都需要与后台接口进行交互,http请求次数巨大
不管是小程序还是支付宝以后其它的第三方支付,其支付的主要操作流程由后台开发工程师负责,前端部分主要负责产品信息的收集、预支订单的发送、资金支付的发起、订单结果的回调等操作,并不处理负责复杂的业务逻辑操作。
- 用户下单以后客户端需要发请求给商家服务器端,请求下单支付
- 商家服务器发请求给微信服务器获取当前用户的唯一标识,生成商户订单
- 商家服务器端发请求给微信服务器端请求统一下单支付(获取最终的预支付订单信息)
- 商家服务器收到预支单的信息对该信息进行签名和加密处理
- 商家服务器端签名以后将支付的参数的信息返回给客户端
- 客户端展示给用预支单信息
- 用户确认支付,授权掉起支付的API(wx.requestPayment),直接发请求给微信服务器请求扣款
- 微信服务器扣款结束以后将支付的结果返回给客户端,客户端需要将支付的结果展示给用户看
- 微信服务器将支付的结果推送给商家服务器端,用于更新订单状态
- 实现类似功能的方法都差不多,就是调用小程序的 Canvas 模块
- 可以利用第三方插件,比如:小程序海报组件https://www.npmjs.com/package/wxa-plugin-canvas进行功能处理
在小程序中可以进行直接功能的开启,但需要注意一些条件限制
- 小程序直接只支持单设备直播,不支持多镜头多设备切换直播,但它是免费的
- 如果需要多设备多镜头切换直接,需要自己搭建或利用第三方流媒体服务器做支撑,这将耗费极大成本
- 在小程序管理平台功能->直播模块可以开启直播功能
- 直播功能需要有小程序应用存有支付操作行业,否则不能申请直接
如果申请通过,小程序管理平台可以进行直播间的管理操作
小程序端直接间的引入与使用操作,具体:https://developers.weixin.qq.com/miniprogram/dev/framework/liveplayer/live-player-plugin.html
直播组件引入:分包与主包引入需要在不同配置文件引入配置,而且provider编号是不变的,就是wx2b03c6e691cd7370
获取直播房间列表:该接口仅供商家后台调用,调用限额500次/天,建议开发者自己做缓存(后台开发人员处理),开发者自己公司的服务器上再进行自己服务器接口的开发与提供
利用路由跳转进入直播间:
<navigator url="plugin-private://wx2b03c6e691cd7370/pages/live-player-plugin?room_id={{roomId}}&custom_params={{customParams}}">navigator>
let roomId = [直播房间id] // 填写具体的房间号,可通过下面【获取直播房间列表】 API 获取 let customParams = encodeURIComponent(JSON.stringify({ path: 'pages/index/index', pid: 1 })) wx.navigateTo({ url: `plugin-private://wx2b03c6e691cd7370/pages/live-player-plugin?room_id=${roomId}&custom_params=${customParams}` }) // 其中wx2b03c6e691cd7370是直播组件appid不能修改
将支付的结果返回给客户端,客户端需要将支付的结果展示给用户看
- 微信服务器将支付的结果推送给商家服务器端,用于更新订单状态
- 实现类似功能的方法都差不多,就是调用小程序的 Canvas 模块
- 可以利用第三方插件,比如:小程序海报组件https://www.npmjs.com/package/wxa-plugin-canvas进行功能处理
在小程序中可以进行直接功能的开启,但需要注意一些条件限制
- 小程序直接只支持单设备直播,不支持多镜头多设备切换直播,但它是免费的
- 如果需要多设备多镜头切换直接,需要自己搭建或利用第三方流媒体服务器做支撑,这将耗费极大成本
- 在小程序管理平台功能->直播模块可以开启直播功能
[外链图片转存中…(img-hWPHowG0-1694341453735)]
- 直播功能需要有小程序应用存有支付操作行业,否则不能申请直接
[外链图片转存中…(img-8KqMzLzX-1694341453738)]
如果申请通过,小程序管理平台可以进行直播间的管理操作
[外链图片转存中…(img-z8NrP8Yx-1694341453743)]
小程序端直接间的引入与使用操作,具体:https://developers.weixin.qq.com/miniprogram/dev/framework/liveplayer/live-player-plugin.html
直播组件引入:分包与主包引入需要在不同配置文件引入配置,而且provider编号是不变的,就是wx2b03c6e691cd7370
获取直播房间列表:该接口仅供商家后台调用,调用限额500次/天,建议开发者自己做缓存(后台开发人员处理),开发者自己公司的服务器上再进行自己服务器接口的开发与提供
利用路由跳转进入直播间:
<navigator url="plugin-private://wx2b03c6e691cd7370/pages/live-player-plugin?room_id={{roomId}}&custom_params={{customParams}}">navigator>
let roomId = [直播房间id] // 填写具体的房间号,可通过下面【获取直播房间列表】 API 获取 let customParams = encodeURIComponent(JSON.stringify({ path: 'pages/index/index', pid: 1 })) wx.navigateTo({ url: `plugin-private://wx2b03c6e691cd7370/pages/live-player-plugin?room_id=${roomId}&custom_params=${customParams}` }) // 其中wx2b03c6e691cd7370是直播组件appid不能修改