blog's People
blog's Issues
小程序用户登录
小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。
基础知识
登录流程
API
1.wx.login()
调用接口获取登录凭证 code
,进而获取用户登录信息,包含用户的唯一标签 openid
及本次登录的会话密钥 session_key
。
2.code2Session
开发者服务器调用 jscode2session
获取登录信息。
GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
请求参数:
- appid: 小程序的appId
- secret: 小程序的 appSecret
js_code
:wx.login()
获取的 codegrant_type
: 授权类型,填写authorization_code
即可
返回参数:
- openid: 用户唯一标识
session_key
: 会话密钥- unionid: 用户在开放平台的唯一标识符
3.wx.checkSession(Object object)
通过 wx.login()
接口获得的用户登录态拥有一定的时效性。用户越久未使用小程序,用户登录态越有可能失效。反之如果用户一直在使用小程序,则用户登录态一直保持有效。具体时效逻辑由微信维护,对开发者透明。
开发者只需要调用 wx.checkSession
接口检测当前用户登录态是否有效。登录态过期后开发者可以再调用 wx.login
获取新的用户登录态。调用成功说明当前 session_key
未过期,调用失败说明 session_key
已过期。
4.wx.getUserInfo(Object object)
调用前需要 用户授权 scope.userInfo
。
主要参数:
- withCredentials: 是否带上登录态信息,当 withCredentials 为 true 时,要求此前有调用过
wx.login()
且登录态尚未过期,此时返回的数据会包含 encryptedData, iv 等敏感信息;当 withCredentials 为 false 时,不要求有登录态,返回的数据不包含 encryptedData, iv 等敏感信息。
返回值:
- userInfo: 用户信息,不包含 openid 等敏感信息
- rawData: 不包括敏感信息的原始数据字符串,用于计算签名
- signature: 使用 sha1(rawData + sessionkey) 得到字符串,用于校验用户信息
- encryptedData: 包括敏感数据在内的完整用户信息的加密数据
- iv: 加密算法的初始向量
wx.getUserInfo({
success: function(res) {
var userInfo = res.userInfo
var nickName = userInfo.nickName
var avatarUrl = userInfo.avatarUrl
var gender = userInfo.gender //性别 0:未知、1:男、2:女
var province = userInfo.province
var city = userInfo.city
var country = userInfo.country
}
})
// encryptedData 解密后为以下 json 结构
{
"openId": "OPENID",
"nickName": "NICKNAME",
"gender": GENDER,
"city": "CITY",
"province": "PROVINCE",
"country": "COUNTRY",
"avatarUrl": "AVATARURL",
"unionId": "UNIONID",
"watermark": {
"appid": "APPID",
"timestamp": TIMESTAMP
}
}
在用户未授权过的情况下调用此接口,将不再出现授权弹窗,会直接进入 fail 回调。
授权处理:
<!-- 如果只是展示用户头像昵称,可以使用 <open-data /> 组件 -->
<open-data type="userAvatarUrl"></open-data>
<open-data type="userNickName"></open-data>
<!-- 需要使用 button 来授权登录 -->
<button wx:if="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">授权登录</button>
<view wx:else>请升级微信版本</view>
Page({
data: {
canIUse: wx.canIUse('button.open-type.getUserInfo')
},
onLoad: function() {
// 查看是否授权
wx.getSetting({
success (res){
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称
wx.getUserInfo({
success: function(res) {
console.log(res.userInfo)
}
})
}
}
})
},
bindGetUserInfo (e) {
console.log(e.detail.userInfo)
}
})
5.getPhoneNumber
获取微信用户绑定的手机号,需先调用 wx.login()
接口。由于需要用户主动触发才能发起获取手机号接口,只能通过 <button>
组件的点击来触发。
需要将 <button>
组件 open-type
的值设置为 getPhoneNumber
,当用户点击并同意之后,可以通过 bindgetphonenumber
事件回调获取到微信服务器返回的加密数据, 然后在第三方服务端结合 session_key
以及 app_id
进行解密获取手机号。
代码实例:
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>
Page({
getPhoneNumber (e) {
console.log(e.detail.errMsg)
console.log(e.detail.iv)
console.log(e.detail.encryptedData)
}
})
// encryptedData 解密后数据结构是这样的
{
"phoneNumber": "13580006666",
"purePhoneNumber": "13580006666",
"countryCode": "86",
"watermark":
{
"appid":"APPID",
"timestamp": TIMESTAMP
}
}
名称解释
code
临时登录凭证, 有效期五分钟, 通过 wx.login()
获取
session_key
会话密钥, 开发者服务端通过 code2Session
获取。session_key
是对用户数据进行加密签名的密钥。
openId
用户在该小程序下的用户唯一标识, 永远不变, 开发者服务端通过 code2Session
获取
unionId
用户在同一个微信开放平台帐号(公众号, 小程序, 网站, 移动应用)下的唯一标识, 永远不变
appId
小程序唯一标识
appSecret
小程序的 app secret, 可以和 code, appId 一起换取 session_key
userInfo
通过 wx.getUserInfo()
获取的用户信息,不包含 openid 等敏感信息
rawData
通过 wx.getUserInfo()
获取的信息,不包括敏感信息的原始数据字符串,用于计算签名
signature
通过 wx.getUserInfo()
获取的信息,使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息
encryptedData
通过 wx.getUserInfo()
获取的信息,包括敏感数据在内的完整用户信息的加密数据
iv
通过 wx.getUserInfo()
获取的信息,加密算法的初始向量
数据校验和解密
签名校验以及数据加解密涉及用户的会话密钥 session_key
,开发者应该先通过 wx.login()
登录流程获取会话密钥 session_key
并保存到服务器。
数据签名校验
- 1.通过调用接口(如:
wx.getUserInfo()
)获取用户数据,接口会同时返回 rawData、signature,其中signature = sha1(rawData + session_key)
- 2.开发者将 signature、rawData 发送到开发者服务器进行校验,服务器利用用户对应的
session_key
进行数据校验
会话密钥 session_key 有效性
- 1.微信不会把
session_key
的有效期告知开发者,用户越频繁使用小程序,session_key
有效期越长 - 2.开发者可以通过
wx.checkSession
校验session_key
是否有效
项目实战
一个简单的用户系统需要关注至少这些层面。
- 安全性(加密)
- 持久化登录态(类似cookie)
- 登录过期处理
- 确保用户唯一性, 避免出现多账号
- 授权
- 绑定用户昵称头像等信息
- 绑定手机号(实名和密保方式)
小程序运行机制
小程序架构
小程序的框架包含两部分:view 视图层、AppService 逻辑层。view 层用来渲染页面结构,AppService 层用来逻辑处理、数据请求、接口调用,它们在两个线程里运行。
逻辑层把数据变化通知给视图层,触发视图层更新,视图层把触发的事件通知到逻辑层进行业务处理。渲染 view 线程和 AppServcie 是相互独立的,对于 AppServcie 中 JavaScript 运行不会阻塞 view 的渲染。
视图层使用 WebView 渲染,逻辑层使用 JSCore 运行。WebView 和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上通过两边提供的 evaluateJavascript 所实现。即用户传输的数据,需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立环境。
evaluateJavascript 的执行会受很多方面的影响,数据到达视图层并不是实时的。所以频繁的去 setData及大量传输数据会导致性能问题。
视图层
视图层由 WXML 与 WXSS 编写,由组件来进行展示。将逻辑层的数据反应成视图,同时将视图层的事件发送给逻辑层。
1.View - WXML
支持数据绑定、逻辑运算、模板引用、事件绑定
WXML(WeiXin Markup Language)
wxml 编译器:wcc 把 wxml 文件转为 js
2.View - WXSS
支持大部分 CSS 特性、支持 rpx、支持 @import 导入方式
WXSS(WeiXin Style Sheets)
wxml 编译器:wcc 把 wxss 文件转为 js
3.View - WXSS Selectors
WXSS 目前只支持类选择器、ID选择器、元素选择器、伪元素选择器
4.View - Component
小程序的组件是基于 Web Component 标准,基于 Polymer 框架实现的 Web Component。
<!-- add style to your element -->
<dom-module is="my-styled-namecard">
<template>
<style>
span: {
color: red;
}
</style>
<div>Hi, My name is <span>{{name}}</span><div>
</template>
<script>
Polymer({
is: 'my-styled-namecard',
properties: {
name: {
type: String
}
}
})
</script>
</dom-module>
5.View - Native Component
目前 Native 实现的组件有 <canvas/> <video/> <map/> <textarea/>
Native 组件层在 WebView 层之上
逻辑层
逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。
- App() 小程序入口,Page() 页面入口
- 丰富的API
- 独立的页面作用域,提供模块化能力
- 数据绑定、事件分发、生命周期管理、路由管理
运行环境
- IOS:JavaScript 代码是运行在 JavaScriptCore 中,是由 WKWebView 来渲染的
- Android:JavaScript 代码是通过 X5 JSCore来解析,是由 X5 基于 Mobile Chrome 53/57 内核来渲染的
- DevTool:JavaScript 代码是运行在 nwjs 中,是由 Chrome Webview 来渲染的
数据绑定
数据绑定使用 Mustache 语法(双大括号)将变量包起来,动态数据均来自对应 Page 的 data,可以通过 setData 方法修改数据。
App实例生命周期
- onLaunch: 监听小程序初始化,全局只会触发一次
- onShow: 简单小程序显示或者从后台进入前台显示
- onHide: 监听小程序隐藏 当小程序从前台进入后台
前台、后台定义: 当用户点击左上角关闭,或者按了设备 Home 键离开微信,小程序并没有直接销毁,而是进入了后台;当再次进入微信或再次打开小程序,又会从后台进入前台。需要注意的是:只有当小程序进入后台一定时间,或者系统资源占用过高,才会被真正的销毁。
Page实例生命周期
View Thread 有四大状态:
- 初始化状态:界面线程初始化工作,包括工作机制,等初始化完成后向逻辑层发送初始化完毕信号,然后进入等待状态
- 初次渲染:收到逻辑层发来的初始化数据后(json和js中的data)。开始进行渲染,渲染完成后给逻辑层发送首次渲染完成信号,同时将页面呈现给用户
- 持续渲染状态:界面线程一直等待逻辑层发送数据,收到数据就进行局部渲染
- 结束状态
AppService Thread 有五大状态
- 初始化状态:启动逻辑层所需要的基本功能,初始化完成调用 onLoad 和 onShow
- 等待激活状态:接收到
界面线程发送初始化完成
信号后,将初始化数据发生给界面线程,等待界面线程完成初次渲染 - 激活状态:收到界面线程发送的
首次渲染完成
信号后,进入激活状态,并调用 onReady,此状态下可以通过 this.setData 函数发送数据更新界面 - 后台运行状态:界面进入后台,逻辑层也进入后台运行状态,暂停之间的通信
- 结束状态
- View Thread 以及 AppSevice Thread 进入Start
- AppSevice Thread 调用 Page 方法传入配置 Created 后,调用 onLoad(监听页面加载)以及 onShow(监听页面显示)方法,AppSevice Thread 等待 View Thread 的通知
- View Thread 进入初始化阶段(Inited)后,通知(Notify)AppSevice Thread 已经初始化好了,然后 AppSevice Thread 传入 App 实例中的初始化数据, AppSevice Thread 等待 View Thread 的下一次通知
- View Thread 收到初始化的数据之后,第一次渲染页面(First Render),进入Ready 阶段,渲染完毕通知 AppSevice Thread,AppSevice Thread 调用 onReady 方法,进入 Active 阶段
- 在 AppSevice Thread Active 阶段,会调用一些 setData 的方法,就是传递数据给 View Thread 中的渲染器(Rerender),进行视图更新
- 当小程序切到后台或者当前 Page 跳转调用 onHide 方法,进入 Alive 阶段,再切回来前台调用 onShow 进入 Active 阶段
- 最后 Page 销毁,调用 onUnload 方法,页面卸载
API
API 通过 JSBridge 和 Native 进行通信。
路由
- navigateTo: 保留当前页面,打开新页面
- navigaterBack: 关闭当前页面,回到指定页面
- redirectTo: 关闭当前页面,打开新页面
运行机制
- 小程序没有重启的概念
- 小程序进入后台,客户端会维持一段时间的运行状态,超过一定时间(目前是5分钟),就会被销毁
- 当短时间内(5s)连续收到两次以上系统内存告警,小程序也会被销毁
冷启动
冷启动指的是用户首次打开或小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动。
热启动
假如用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时无需重新启动,只需将后台态的小程序切换到前台,这个过程就是热启动
更新机制
小程序冷启动时如果发现有新版本,将会异步下载新版本的代码压缩包,并同时用客户端本地的包进行启动,即新版本的小程序需要等下一个冷启动才会应用上。
如果需要应该最新版本,需要使用 wx.getUpdateManager()
进行处理。
参考文献
深入系列:原型链
prototype
每个函数都有一个 prototype 属性,函数的 prototype 属性指向了一个对象,该对象是调用构造函数而创建生成实例
的原型。
每一个 JavaScript 对象(null除外
)在创建时都会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型继承
属性。
function Person() {};
Person.prototype.name = 'slogeor';
const p1 = new Person();
p1.name;
// slogeor
Object.prototype.toString.call(Person.prototype)
// [object Object]
// 获取对象的原型
Object.getPrototypeOf(p1) === Person.prototype
// true
__ proto __
每一个 JavaScript 对象(除了 null
)都具有一个属性 __proto__
,这个属性指向了该对象的原型。
function Person() {}
const p1 = new Person();
p1.__proto__ === Person.prototype
// true
Person.__proto__ === Object.prototype
// false
Person.__proto__ === Function.prototype
// true
Person instanceof Object
// true
Person instanceof Function
// true
constructor
每个原型都有一个 constructor 属性指向关联的构造函数。
function Person() {}
Person === Person.prototype.constructor
// true
实例与原型
当读取实例对象的属性时,如果找不到,就会查找与其对象关联的原型中的属性。如果还找不到,就会找原型的原型,一直找到最顶层为止。
function Person() {}
Person.prototype.name = 'slogeor';
const p1 = new Person();
p1.name = 'mySlogeor';
p1.name; // mySlogeor
delete p1.name;
p1.name; // 'slogeor'
原型链
Object.prototype.__proto__ === null
// true
Object.prototype.__proto__
的值为 null 跟 Object.prototype 没有原型,其实表达了一个意思。
所以查找属性的时候查到 Object.prototype 就可以停止查找了。
参考链接
iframe
属性
- frameborder: 是否显示边框,1: 显示,0: 不显示
- name: 框架的名称,window.frames[name] 专用属性
- scrolling: 是否可以滚动,yes: 可以,no: 不可以,auto: 自动
- src: 框架地址
- allowtransparency: 是否允许 iframe 设置为透明,默认 false
- allowfullscreen: 是否允许 iframe 全屏,默认 false
获取 iframe 的内容
- ifr.contentWindow: 获取 iframe 的 window 对象
- ifr.contentDocument: 获取 iframe 的 document 对象
- window.frames[name].window: 通过 name 获取 iframe 的 window 对象
获取 iframe 父级
- window.parent: 获取上一级的 window 对象,如果还是 iframe 则是 iframe 的 window 对象
- window.top: 获取最顶级容器的 window 对象,即打开页面的文档
- window.self: 返回自身 window 引用, window === window.self
X-Frame-Options
X-Frame-Options 是一个响应头,主要描述服务器的网页资源 iframe 的权限。IE8+ 支持。
- DENY: 拒绝任何 iframe 的嵌套请求
- SAMEORIGIN: iframe 页面地址只能是同源域名下的页面
- ALLOW-FROM: 指定特定的 iframe 地址
应用场景
- 跨域
- 长轮询
- clickhacking
参考链接
WebSocket 概述
WebSocket 建立连接
这是一个 http get
请求报文,注意该报文中有一个 upgrade
首部,它的作用是告诉服务端需要将通信协议切换到 websocket
。
如果服务端支持 WebSocket 协议,那么它就会将自己的通信协议切换到 WebSocket,同时发给客户端一个响应报文头。
返回的状态码为 101,表示同意客户端协议转换请求,并将它转换为 WebSocket 协议。
以上过程都是利用 http 通信完成的,称之为 WebSocket 协议握手(WebSocket Protocol handshake)
总结: WebSocket 握手需要借助于 http 协议,建立连接后通信过程使用 WebSocket 协议。
WebSocket 原理
WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是。
- WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样
- WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信
客户端发送数据格式类似于下面的内容
GET /slogeor/websocket/ HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==
Origin: http://localhost:8080
Sec-WebSocket-Version: 13
客户端发起的 WebSocket 连接报文类似传统 HTTP 报文,Upgrade:websocket
参数值表明这是 WebSocket 类型请求。
Sec-WebSocket-Key
是 WebSocket 客户端发送的一个 base64 编码的密文,要求服务端必须返回一个对应加密的 Sec-WebSocket-Accept
应答。
服务端收到报文后返回的数据格式类似于如下内容
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=
Sec-WebSocket-Accept
的值是服务端采用与客户端一致的密钥计算出来后返回客户端的。
HTTP/1.1 101 Switching Protocols
表示服务端接受 WebSocket 协议的客户端连接。
经过这样的请求响应处理后,客户端服务端的 WebSocket 连接握手成功, 后续就可以进行 TCP 通讯了。
总结
在 WebSocket 中,浏览器和服务器只需要要做一个握手的动作(HTTP GET),然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接互相传送数据,改变了原有的B/S模式。
WebSocket 与 HTTP 比较
相同点
- 都是基于 TCP 的应用层协议
- 都使用 Request/Response 模型进行连接的建立
- 在连接的建立过程中对错误的处理方式相同,在这个阶段 WebSocket 可能返回和 HTTP 相同的返回码
- 都可以在网络中传输数据
不同点
- WebSocket 使用 HTTP 建立连接,但是定义了一系列新的 header 域,这些域在 HTTP 中并不会使用
- WebSocket 的连接不能通过中间人来转发,它必须是一个直接连接
- WebSocket 连接建立之后,通信双方都可以在任何时刻向另一方发送数据
- WebSocket 连接建立之后,数据的传输使用帧来传递,不再需要 Request 消息
- WebSocket 的数据帧有序
参考链接
whistle 安装配置
whistle
whistle 是基于 Node 实现的跨平台 web 调试代理工具,其功能类似于 windows 平台的 Fiddler 和 Mac 平台的 Charles。whistle 采用的是类似配置系统 hosts 的方式,一切操作都可以通过配置来实现,复杂功能还可以通过 Node 模块扩展实现。
软件安装
1.Node
whistle 支持 v0.10.0
以上版本,为了更好的性能,推荐安装最新版本的 Node,没有安装 Node,自行安装。
2.whistle
// 安装
js npm install -g whistle
// 直接指定镜像
$ npm install whistle -g --registry=https://registry.npm.taobao.org
常用命令
// 查看帮助
w2 help
// 启动
w2 start
// 重启
w2 restart
// 停止
w2 stop
// 调试模式
w2 run
配置代理
代理服务器默认是 127.0.0.1
,端口号默认是 8899
,如果端口号被暂用,可以在启动服务时通过 -p 8090
来指定新端口。
1.全局代理方式
Mac:系统偏好设置 --> 网络 --> 高级 --> 代理 --> HTTP or HTTPS
2.浏览器方式
安装 Chrome 插件:SwitchyOmega
3.手机设置
需要在设置中配置当前 WI-FI 的代理
4.小程序设置
设置 --> 代理设置
4. Mac 和 手机 安装 HTTPS 证书
Mac 安装证书后,需要手动信任证书。
iOS 10.3 之后需要手动信任自定义根证书。
具体安装步骤点击http://wproxy.org/whistle/webui/https.html查看。
如果配置完代理,手机还无法访问,可能是 whistle 所在的电脑防火墙限制了远程访问whistle 的端口,关闭防火墙即可。
访问配置页面
可以通过下面两种方式进行访问配置
- 域名访问 http://local.whistlejs.com/
- 通过ip+端口来访问,形式如 http://whistleServerIP:whistlePort+1/ [e.g. http://127.0.0.1:8900]
(https://github.com/slogeor/images/blob/master/other/2018/10/01.png?raw=true)
参考文献
小程序性能优化
setData 工作原理
小程序的视图层使用 WebView 作为渲染载体,逻辑层是由独立的 JavaScriptCore 作为运行环境。在架构上,WebView 和 JavaScriptCore 都是独立的模块,并不具备数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上通过两边提供的 evaluateJavascript 所实现。即用户传输的数据,需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立环境。
优化手段
- 启动加载优化
- 渲染优化
启动加载优化
首次加载
首次加载微信会在背后完成这些工作:下载小程序代码、加载小程序代码、初始化小程序首页。
加载顺序
微信会在小程序启动前为小程序准备好通用的运行环境。这个运行环境包括几个供小程序使用的线程,并在其中完成小程序基础库的初始化。
控制包大小
- 勾选开发者工具中
上传代码时,压缩代码
选项 - 及时清理无用的代码和资源文件(包括无用的日志代码)
- 减少资源包中的图片等资源的数量和大小
分包加载
根据业务场景,将用户访问率高的页面放在主包里,将访问率低的页面放入子包里,按需加载。
分包预加载
这种基于配置的子包预加载技术,是可以根据用户网络类型来判断的,当用户处于网络条件好时才预加载;是灵活可控的。
采用独立分包技术
采用独立分包技术,区别于子包,和主包之间是无关的,在功能比较独立的子包里,使用户只需下载分包资源。
首屏加载优化建议
- 提前请求数据
- 合理利用缓存
- 优化体验(骨架屏)
渲染性能优化
减少页面初始的数据量
页面初始化的时间大致由页面初始数据通信时间和初始渲染时间两部分构成。其中,数据通信的时间指数据从逻辑层开始组织数据到视图层完全接收完毕的时间,数据量小于 64KB 时总时长可以控制在 30ms 内。传输时间与数据量大体上呈现正相关,传输过大的数据将使这一时间显著增加。因而减少传输数据量是降低数据传输时间的有效方式。
避免使用不当的 setData
- 不要过于频繁的调用 setData
- 尽量将多次 setData 进行合并
- 正确使用 setData,与界面无关的数据不要放到 data 中
- 多利用 setData 进行局部刷新
- 切勿在后台页面进行 setData 操作
用户事件使用不当
- 去掉不必要的事件绑定,减少通信次数
- 事件绑定时需要传输 target 和 currentTarget 的 dataset,因而不要在节点的data 前缀属性中放置过大的数据
视图层渲染
首次渲染时间开销主要是与节点树中节点的总量成正相关,可以通过减少 WXML 中节点的数量可以有效降低初始渲染和重渲染的时间开销,提升渲染性能。
重新渲染会着重比较 setData 数据,可以通过去掉不必要设置的数据、减少 setData 的数据量也有助于提升这一个步骤的性能。
多使用自定义组件
自定义组件的更新只在组件内部进行,不受页面其他不能内容的影响。每个组件都有自己独立的数据。
总结
小程序启动加载性能
- 控制代码包的大小
- 分包加载
- 首屏体验
小程序渲染性能
- 避免不当的使用setData
- 合理利用事件通信
- 避免不当的使用onPageScroll
- 优化视图节点
- 使用自定义组件
补充
小程序为什么那么快
- Page Frame
- Native 预先额外加载一个 WebView
- 当打开指定页面时,用默认数据直接渲染,请求数据回来时局部更新
- 返回显示历史 view
- 退出小程序,view 状态不销毁
存在的问题
- 使用 WebView 渲染,非原生渲染
- 不可以扩展新组件
- 需要独立开发,只能运行在微信环境
- 依赖浏览器环境的 JS 库不能使用,因为是 JSCore,所有没有 window、document 对象
参考文献
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.