<p class="p1" style="text-align: left">? ?
<img src="https://www.52php.cn/res/2019/02-18/17/15b768dd4ae96309bb8553e33b5efb7c.png" alt="" width="1037" height="417">
<p style="text-align: left"><span style="font-size: 16px">? ? ?众所周知如今市面上端的形态多种多样,手机Web、ReactNative、微信小程序,支付宝小程序,快应用等,每一端都是巨大的流量入口,当业务要求同时在不同的端都要求有所表现的时候,针对不同的端去编写多套代码的成本显然非常高,这时候只编写一套代码就能够适配到多端的能力就显得极为需要。但面对目前市面上成熟的小程序第三方框架如何针对自己的需求进行选择也是一个麻烦事,本文针对当前市面上的三大转译框架进行一个综合对比,希望能对大家的技术选择有所帮助,如有哪里不妥的地方希望指正;
<h2 style="text-align: left"> 小程序开发有哪些痛点?
? ? 第三方框架对比 wepy mpvue taro
在这里我通过对目前已开源的三种常用小程序框架做一个综合对比,还有一个叫nanchi的基于react的小程序转译框架,由于没来的及研究暂不做比较;
腾讯团队开源的一款类vue语法规范的小程序框架,借鉴了Vue的语法风格和功能特性,支持了Vue的诸多特征,比如父子组件、组件之间的通信、computed属性计算、wathcer监听器、props传值、slot槽分发,还有很多高级的特征支持:Mixin混合、拦截器等;WePY发布的第一个版本是2016年12月份,也就是小程序刚刚推出的时候,到目前为止,WePY已经发布了52个版本,最新版本为1.7.2;?
? 京东凹凸实验室开源的一款使用 React.js 开发微信小程序的前端框架。它采用与 React 一致的组件化思想,组件生命周期与 React 保持一致,同时支持使用 JSX 语法,让代码具有更丰富的表现力,使用?Taro?进行开发可以获得和 React 一致的开发体验。,同时因为使用了react的原因所以除了能编译h5,小程序外还可以编译为ReactNative;
? ? ? ? ? ?
生命周期
wepy生命周期基本与原生小程序相同,再此基础上糅合了一些vue的特性; 对于WePY中的methods属性,因为与Vue中的使用习惯不一致,非常容易造成误解,这里需要特别强调一下:WePY中的methods属性只能声明页面wxml标签的bind、catch事件,不能声明自定义方法,这与Vue中的用法是不一致的。
import wepy from 'wepy'export <span style="color: #0000ff">default<span style="color: #000000"> class MyPage extends wepy.page {
<span style="color: #008000">//<span style="color: #008000"> export default class MyComponent extends wepy.component {
customData = {} <span style="color: #008000">//<span style="color: #008000"> 自定义数据
<span style="color: #000000">
customFunction () {} <span style="color: #008000">//<span style="color: #008000">自定义方法
<span style="color: #000000">
onLoad () {} <span style="color: #008000">//<span style="color: #008000"> 在Page和Component共用的生命周期函数
<span style="color: #000000">
onShow () {} <span style="color: #008000">//<span style="color: #008000"> 只在Page中存在的页面生命周期函数
<span style="color: #000000">
config = {}; <span style="color: #008000">//<span style="color: #008000"> 只在Page实例中存在的配置数据,对应于原生的page.json文件
<span style="color: #000000">
data = {}; <span style="color: #008000">//<span style="color: #008000"> 页面所需数据均需在这里声明,可用于模板数据绑定
<span style="color: #000000">
components = {}; <span style="color: #008000">//<span style="color: #008000"> 声明页面中所引用的组件,或声明组件中所引用的子组件
<span style="color: #000000">
mixins = []; <span style="color: #008000">//<span style="color: #008000"> 声明页面所引用的Mixin实例
<span style="color: #000000">
computed = {}; <span style="color: #008000">//<span style="color: #008000"> 声明计算属性(详见后文介绍)
<span style="color: #000000">
watch = {}; <span style="color: #008000">//<span style="color: #008000"> 声明数据watcher(详见后文介绍)
<span style="color: #000000">
methods = {}; <span style="color: #008000">//<span style="color: #008000"> 声明页面wxml中标签的事件处理函数。注意,此处只用于声明页面wxml中标签的bind、catch事件,自定义方法需以自定义方法的方式声明
<span style="color: #000000">
events = {}; <span style="color: #008000">//<span style="color: #008000"> 声明组件之间的事件处理函数
}
onTabItemTap,当前是 tab 页时,点击 tab 时触发 (mpvue 0.0.16 支持)
简单示例
1
console.log('a is: ' +
console.log('a is: ' + .a,'小程序触发的 onshow' "a is: 1"
.state = { date: <span style="color: #ff0000">componentDidMount () {
}
<span style="color: #ff0000">componentWillUnmount
() {
}
render () {
<span style="color: #0000ff">return<span style="color: #000000"> (
Hello,world!
现在的时间是 {.state.date.toLocaleTimeString()}.
列表渲染
当需要循环渲染WePY组件时(类似于通过wx:for
循环渲染原生的wxml标签),必须使用WePY定义的辅助标签
使用与vue一致,只是需要注意一点,!
>
="(item,itemIndex) in card">
的列表循环用法基本与react相同,有一点需要注意,在 React 中,JSX 是会编译成普通的 JS 的执行,每一个 JSX 元素,其实会通过?createElement
?函数创建成一个 JavaScript 对象(React Element),因此实际上你可以这样写代码 React 也是完全能渲染的:
const list = .state.list.map(l => {l.text}
但是 Taro 中,JSX 会编译成微信小程序模板字符串,因此你不能把?map
?函数生成的模板当做一个数组来处理。当你需要这么做时,应该先处理需要循环的数组,再用处理好的数组来调用 map 函数。例如上例应该写成:
const list = =>=> {l.text}
})
事件处理
目前全支持小程序的事件处理器,引入了 Vue.js 的虚拟 DOM ,在前文模版中绑定的事件会被挂在到 vnode 上,同时 compiler 在 wxml 上绑定了小程序的事件,并做了相应的映射,所以你在真实点击的时候通过 runtime 中?handleProxy
?通过事件类型分发到 vnode 的事件上,同 Vue 在 WEB 的机制一样,所以可以做到无损支持。同时还顺便支持了自定义事件和?$emit
?机制
'tap''touchstart''touchmove''touchcancel''touchend''tap''longtap''input''change''submit''blur''focus''reset''confirm''columnchange''linechange''error''scrolltoupper''scrolltolower''scroll'
列表中没有的原生事件也可以使用例如 bindregionchange 事件直接在 dom 上将bind改为@?@regionchange
,同时这个事件也非常特殊,它的 event type 有 begin 和 end 两个,导致我们无法在handleProxy
?中区分到底是什么事件,所以你在监听此类事件的时候同时监听事件名和事件类型既?
小程序能力所致,bind 和 catch 事件同时绑定时候,只会触发 bind,catch 不会被触发,要避免踩坑。
事件修饰符
.stop
?的使用会阻止冒泡,但是同时绑定了一个非冒泡事件,会导致该元素上的 catchEventName 失效!
.prevent
?可以直接干掉,因为小程序里没有什么默认事件,比如submit并不会跳转页面
.capture
?支持?1.0.9
.self
?没有可以判断的标识
.once
?也不能做,因为小程序没有 removeEventListener,虽然可以直接在 handleProxy 中处理,但非常的不优雅,违背了原意,暂不考虑
其他 键值修饰符 等在小程序中压根没键盘,所以。。。
事件绑定区别于vue,根据原生小程序事件提供了语法优化
<p class="p1" style="text-align: left"><span class="s1" style="font-size: 14px">绑定事件 <span class="s2"><span class="Apple-converted-space">?bindtap="click" 替换为 <span class="s3">@tap<span class="s2">="click",<span class="s1" style="font-size: 14px"><span style="color: #000000">取消冒泡 <span class="s2"><span style="color: #000000">原catchtap="click"替换为<span class="s3">@tap.stop<span class="s2">="click"。
<p class="p1" style="text-align: left"><span class="s1" style="font-size: 14px">捕获监听事件 <span class="s2"><span class="Apple-converted-space">?capture-bind:tap="click" 替换为 <span class="s3">@tap.capture<span class="s2">="click",<span class="s1" style="font-size: 14px"><span style="color: #000000">中断捕获监听 <span class="s2"><span style="color: #000000">capture-catch:tap=“click"替换为 <span class="s3">@tap.capture.stop<span class="s2">="click"。
元素的事件处理和 DOM 元素的很相似。但是有一点语法上的不同:
Taro 事件绑定属性的命名采用驼峰式写法,而不是小写。 如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串 (DOM 元素的写法)。 例如,传统的微信小程序模板:
Taro 中稍稍有点不同:
.activateLasers}>
在 Taro 中另一个不同是你不能使用?catchEvent
?的方式阻止事件冒泡。你必须明确的使用?stopPropagation
。例如,阻止事件冒泡你可以这样写:
.state = {isToggleOn: onClick = (e) =><span style="color: #000000"> {
e.stopPropagation()
<span style="color: #0000ff">this .setState(prevState =><span style="color: #000000"> ({
isToggleOn: !<span style="color: #000000">prevState.isToggleOn
}))
}
render () {
<span style="color: #0000ff">return<span style="color: #000000"> (
<button onClick={<span style="color: #0000ff">this.onClick}><span style="color: #000000">
{<span style="color: #0000ff">this.state.isToggleOn ? 'ON' : 'OFF'<span style="color: #000000">}
<span style="color: #000000"> )
}
}
?request请求
对wx.request做了接受参数的修改,值得一提的是它提供了针对全局的intercapter拦截器
'xxx' <span style="color: #008000">// <span style="color: #008000"> WePY 使用方式,需要开启 Promise 支持,参考开发规范章节
wepy.request('xxxx').then((d) =><span style="color: #000000"> console.log(d));
<span style="color: #008000">// <span style="color: #008000"> async/await 的使用方式,需要开启 Promise 和 async/await 支持,参考 WIKI
async <span style="color: #0000ff">function<span style="color: #000000"> request () {
let d = await wepy.request('xxxxx'<span style="color: #000000">);
console.log(d);
}
拦截器
import wepy from 'wepy'export <span style="color: #0000ff">default<span style="color: #000000"> class extends wepy.app {
constructor () {
<span style="color: #008000">//<span style="color: #008000"> this is not allowed before super()
<span style="color: #000000"> super();
<span style="color: #008000">//<span style="color: #008000"> 拦截request请求
<span style="color: #0000ff">this.intercept('request'<span style="color: #000000">,{
<span style="color: #008000">//<span style="color: #008000"> 发出请求时的回调函数
<span style="color: #000000"> config (p) {
<span style="color: #008000">//<span style="color: #008000"> 对所有request请求中的OBJECT参数对象统一附加时间戳属性
p.timestamp = +<span style="color: #0000ff">new<span style="color: #000000"> Date();
console.log('config request: '<span style="color: #000000">,p);
<span style="color: #008000">//<span style="color: #008000"> 必须返回OBJECT参数对象,否则无法发送请求到服务端
<span style="color: #0000ff">return<span style="color: #000000"> p;
},<span style="color: #008000">//<span style="color: #008000"> 请求成功后的回调函数
<span style="color: #000000"> success (p) {
<span style="color: #008000">//<span style="color: #008000"> 可以在这里对收到的响应数据对象进行加工处理
console.log('request success: '<span style="color: #000000">,p);
<span style="color: #008000">//<span style="color: #008000"> 必须返回响应数据对象,否则后续无法对响应数据进行处理
<span style="color: #0000ff">return<span style="color: #000000"> p;
},<span style="color: #008000">//<span style="color: #008000">请求失败后的回调函数
<span style="color: #000000"> fail (p) {
console.log('request fail: '<span style="color: #000000">,<span style="color: #008000">//<span style="color: #008000"> 请求完成时的回调函数(请求成功或失败都会被执行)
<span style="color: #000000"> complete (p) {
console.log('request complete: '<span style="color: #000000">,p);
}
});
}
}
taro Taro.request(OBJECT)发起网络请求,支持?Promise
?化使用。
import Taro from '@tarojs/taro'Taro.request({
url: 'http://localhost:8080/test'<span style="color: #000000">,data: {
foo: 'foo'<span style="color: #000000">,bar: 10<span style="color: #000000">
},header: {
'content-type': 'application/json'<span style="color: #000000">
}
})
.then(res => console.log(res.data))
没有对request做特殊优化,与原生相同,可以自己根据需要进行封装
状态管理
可引用Redux和Mbox,目前wepy的脚手架内已经集成了redux,选择需要即可;
使用vuex
使用Redux
如果只需要做一个微信小程序则根据自己的擅长框架选择mpvue或taro
如果是当前老项目想像向程序迁移同时老项目又是使用vue开发,建议使用mpvue或wepy
如果是老项目使用react开发且需要部分迁移小程序,建议使用taro
如果是新项目且新项目需要同时支持微信小程序和支付宝小程序,建议使用原生开发,因为目前框架的转译支付宝小程序支持并不是很好,且出了问题不好定位修改,但如果是小demo不涉及太多逻辑的项目都可以使用框架作为尝鲜; 但如果是涉及太多交互逻辑的则不建议使用框架转译,由于支付宝小程序在视图层基本与小程序一致所以建议手动更改替换部分方法和全局替换一些属性或文件名,如wxml替换为axml这种,手动转换时间比大概是四比一; 当然如果人手足够一端开发一个是最好的...
时刻前端新鲜技术推送,定期前端精品文章分享,欢迎关注公众号前端小苑。
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!