摘要:作为两个小程序开发框架都使用过,并应用在生产环境里的人,自然是要比较一下两者的异同点。在这里与当前很流行的小程序开发框架之一进行简单对比,主要还是为了方便大家更快速地了解,从而选择更适合自己的开发方式。
前言
前阵子,来自我们凹凸实验室的遵循 React 语法规范的多端开发方案 - Taro终于对外开源了,欢迎围观star(先打波广告)。作为第一批使用了Taro开发的TOPLIFE小程序的开发人员之一,自然是走了不少弯路,躺了不少坑,也帮忙找过不少bug。现在项目总算是上线了,那么,也是时候给大家总结分享下了。
与wepy比较当初开发TOPLIFE第一期的时候,用的其实是wepy(那时Taro还没有开发完成),然后在第二期才全面转换为用Taro开发。作为两个小程序开发框架都使用过,并应用在生产环境里的人,自然是要比较一下两者的异同点。
相同点组件化开发
npm包支持
ES6+特性支持,Promise,Async Functions等
CSS预编译器支持,Sass/Stylus/PostCSS等
支持使用Redux进行状态管理
…..
相同的地方也不用多说什么,都2018年了,这些特性的支持都是为了让小程序开发变得更现代,更工程化,重点是区别之处
不同点开发风格
实现原理
wepy支持slot,taro暂不支持直接渲染children
开发风格
最大的不同之处,自然就是开发风格上的差异,wepy使用的是类Vue开发风格, Taro使用的是类React开发风格,可以说开发体验上还是会有较大的区别。贴一下官方的demo简单阐述下
wepy demo
view(class="container") view(class="userinfo" @tap="tap") mycom(:prop.sync="myprop" @fn.user="myevent") text {{now}}
taro demo
import Taro, { Component } from "@tarojs/taro" import { View, Button } from "@tarojs/components" export default class Index extends Component { constructor () { super(...arguments) this.state = { title: "首页", list: [1, 2, 3] } } componentWillMount () {} componentDidMount () {} componentWillUpdate (nextProps, nextState) {} componentDidUpdate (prevProps, prevState) {} shouldComponentUpdate (nextProps, nextState) { return true } add = (e) => { // dosth } render () { return () } } {this.state.title} {this.state.list.map(item => { return ( {item} ) })}
可以见到在wepy里,css、template、script都放在一个wepy文件里,template还支持多种模板引擎语法,然后支持computed、watcher等属性,这些都是典型的vue风格
而在taro里,就是彻头彻尾的react风格,包括constructor,componentWillMount、componentDidMount等各种react的生命周期函数,还有return里返回的jsx,熟悉react的人上手起来可以说是非常快了
除此之外还有一些细微的差异之处:
wepy里的模板,或者说是wxml,用的都是小程序里原生的组件,就是小程序文档里的各种组件;而taro里使用的每个组件,都需要从@tarojs/components里引入,包括View,Text等基础组件(这种做其实是为了转换多端做准备)
事件处理上
taro中,是用click事件代替tap事件
wepy使用的是简写的写法@+事件;而taro则是on+事件名称
阻止冒泡上wepy用的是@+事件.stop;而taro则是要显式地使用e.stopPropagation()来阻止冒泡
事件传参wepy可以直接在函数后面传参,如@tap="click({{index}})";而taro则是使用bind传参,如onClick={this.handleClick.bind(null, params)}
wepy使用的是小程序原生的生命周期,并且组件有page和component的区分;taro则是自己实现了类似react的生命周期,而且没有page和component的区分,都是component
总的来说,毕竟是两种不同的开发风格,自然还是会有许多大大小小的差异。在这里与当前很流行的小程序开发框架之一wepy进行简单对比,主要还是为了方便大家更快速地了解taro,从而选择更适合自己的开发方式。
实践体验taro官方提供的demo是很简单的,主要是为了让大家快速上手,入门。那么,当我们要开发偏大型的项目时,应该如何使用taro使得开发体验更好,开发效率更高?作为深度参与TOPLIFE小程序开发的人员之一,谈一谈我的一些实践体验及心得
如何组织代码使用taro-cli生成模板是这样的
├── dist 编译结果目录 ├── config 配置目录 | ├── dev.js 开发时配置 | ├── index.js 默认配置 | └── prod.js 打包时配置 ├── src 源码目录 | ├── pages 页面文件目录 | | ├── index index页面目录 | | | ├── index.js index页面逻辑 | | | └── index.css index页面样式 | ├── app.css 项目总通用样式 | └── app.js 项目入口文件 └── package.json
假如引入了redux,例如我们的项目,目录是这样的
├── dist 编译结果目录 ├── config 配置目录 | ├── dev.js 开发时配置 | ├── index.js 默认配置 | └── prod.js 打包时配置 ├── src 源码目录 | ├── actions redux里的actions | ├── asset 图片等静态资源 | ├── components 组件文件目录 | ├── constants 存放常量的地方,例如api、一些配置项 | ├── reducers redux里的reducers | ├── store redux里的store | ├── utils 存放工具类函数 | ├── pages 页面文件目录 | | ├── index index页面目录 | | | ├── index.js index页面逻辑 | | | └── index.css index页面样式 | ├── app.css 项目总通用样式 | └── app.js 项目入口文件 └── package.json
比较常见的一种项目目录组织方式,相比初始模板多了几个文件夹,用于存放redux相关的内容及其他的一些东西,整个项目结构相信还是比较直观,简单明了的
更好地使用reduxredux大家应该都不陌生,一种状态管理的库,通常会搭配一些中间件使用。我们的项目主要是用了redux-thunk和redux-logger中间件,一个用于处理异步请求,一个用于调试,追踪actions
相信大家都遇到过这种时候,接口返回的数据和页面显示的数据并不是完全对应的,往往需要再做一层预处理。那么这个业务逻辑应该在哪里管理,是组件内部,还是redux的流程里?
举个例子:
例如上图的购物车模块,接口返回的数据是
{ code: 0, data: { shopMap: {...}, // 存放购物车里商品的店铺信息的map goods: {...}, // 购物车里的商品信息 ... } ... }
对的,购车里的商品店铺和商品是放在两个对象里面的,但视图要求它们要显示在一起。这时候,如果直接将返回的数据存到store,然后在组件内部render的时候东拼西凑,将两者信息匹配,再做显示的话,会显得组件内部的逻辑十分的混乱,不够纯粹。
所以,我个人比较推荐的做法是,在接口返回数据之后,直接将其处理为与页面显示对应的数据,然后再dispatch处理后的数据,相当于做了一层拦截,像下面这样:
const data = result.data // result为接口返回的数据 const cartData = handleCartData(data) // handleCartData为处理数据的函数 dispatch({type: "RECEIVE_CART", payload: cartData}) // dispatch处理过后的函数 ... // handleCartData处理后的数据 { commoditys: [{ shop: {...}, // 商品店铺的信息 goods: {...}, // 对应商品信息 }, ...] }
可以见到,处理数据的流程在render前被拦截处理了,将对应的商品店铺和商品放在了一个对象了.
这样做有几个好处
一个是组件的渲染更纯粹,在组件内部不用再关心如何将数据修修改改而满足视图要求,只需关心组件本身的逻辑,例如点击事件,用户交互等
二是数据的流动更可控,假如后续后台返回的数据有变动,我们要做的只是改变handleCartData函数里面的逻辑,不用改动组件内部的逻辑。
后台数据——>拦截处理——>期望的数据结构——>组件
实际上,不只是后台数据返回的时候,其它数据结构需要变动的时候都可以做一层数据拦截,拦截的时机也可以根据业务逻辑调整,重点是要让组件内部本身不关心数据与视图是否对应,只专注于内部交互的逻辑,这也很符合react本身的初衷,数据驱动视图
connect大家都知道是用来连接store、actions和组件的,很多时候就只是根据样板代码复制一下,改改组件各自的store、actions。实际上,我们还可以做一些别的处理,例如:
export default connect(({ cart, }) => ({ couponData: cart.couponData, commoditys: cart.commoditys, editSkuData: cart.editSkuData }), (dispatch) => ({ // ...actions绑定 }))(Cart) // 组件里 render () { const isShowCoupon = this.props.couponData.length !== 0 return isShowCoupon &&}
上面是很普通的一种connect写法,然后render函数根据couponData里是否数据来渲染。这时候,我们可以把this.props.couponData.length !== 0这个判断丢到connect里,达成一种computed的效果,如下:
export default connect(({ cart, }) => { const { couponData, commoditys, editSkuData } = cart const isShowCoupon = couponData.length !== 0 return { isShowCoupon, couponData, commoditys, editSkuData }}, (dispatch) => ({ // ...actions绑定 }))(Cart) // 组件里 render () { return this.props.isShowCoupon &&}
可以见到,在connect里定义了isShowCoupon变量,实现了根据couponData来进行computed的效果
实际上,这也是一种数据拦截处理。除了computed,还可以实现其它的功能,具体就由各位看官自由发挥了
一些需要注意的地方那taro,或者是小程序开发,有没有什么要注意的地方?当然有,走过的弯路可以说是非常多了
估计是每个页面的数据在小程序内部都有缓存,所以做了10层的限制。带来的问题就是假如页面存在循环跳转,即A页面可以跳到B页面,B页面也可以跳到A页面,然后用户从A进入了B,想返回A的时候,往往是直接在B页面里点击跳转到A,而不是点返回回到A,如此一来,10层很快就突破了。所以我们自己对navigateTo函数做了一层封装,防止溢出
上面说到,页面内容有缓存。所以假如某个页面是根据不同的数据渲染视图,新渲染时会有上一次渲染的缓存,导致页面看起来有个闪烁的变化,用户体验非常不好。其实解决的办法也很简单,每次在componentWillUnmount生命周期中清理一下当前页面的数据就好了。小程序说到底不是h5,不会说每次进入页面就会刷新,也不会离开就销毁,刷新,清理数据的动作都需要自己再生命周期函数里主动触发
页面的滚动事件只能通过onPageScroll来监听,所以当我想在组件里进监听操作时,要将该部分的逻辑提前到onPageScroll函数,提高了抽象成本。例如我需要开发一个滚动到某个位置就吸顶的tab,本来可以在tab内部处理的逻辑被提前了,减少了其可复用性
本来也想详细描述下的,不过在我们几位大佬的努力,加班加点下,已经开发出eslint插件,及补充完整了taro文档。大家只要遵循eslint插件规范,查看文档,应该不会有太大问题,有问题欢迎提issue
总结总的来说,用taro来开发小程序体验还是很不错的,最重要的是,可以使用jsx写小程序了!!!作为react粉的一员,可以说是相当的兴奋了~
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/95813.html
摘要:多端统一开发框架优秀学习资源汇总官方资源项目仓库官方文档项目仓库官方文档微信小程序官方文档百度智能小程序官方文档支付宝小程序官方文档字节跳动小程序官方文档文章教程不敢阅读包源码带你揭秘背后的哲学从到构建适配不同端微信小程序等的应用小程序最 Awesome Taro 多端统一开发框架 Taro 优秀学习资源汇总 showImg(https://segmentfault.com/img/r...
摘要:所以在小程序出现之后,一股框架之风也很快的出现,微信小程序刚推出之后,就出现了两个比较出名的小程序开发框架,。 原文地址:https://ant-move.github.io/we... 这里说的去除小程序框架其实并不严谨,因为小程序本身也算是一个框架,而且是一个功能更加完善的框架系统。在前端的概念中,我们一般说一个框架是指一个用来帮助开发者构建用户界面的框架,而小程序框架本身不仅仅包...
摘要:前言是一个可以很好实现一次开发,多端统一的框架,本文只介绍它小程序端开发的一些内容。 前言:taro是一个可以很好实现一次开发,多端统一的框架,本文只介绍它小程序端开发的一些内容。小程序项目搭建gitup已经有很清楚的说明:https://github.com/NervJS/taro 一.主要操作步骤及命令: 1.cnpm install -g @tarojs/cli 全局安装taro...
阅读 1245·2021-09-04 16:41
阅读 2403·2021-09-02 10:18
阅读 915·2019-08-29 16:40
阅读 2613·2019-08-29 16:14
阅读 897·2019-08-26 13:41
阅读 1298·2019-08-26 12:24
阅读 729·2019-08-26 10:24
阅读 2868·2019-08-23 17:54