使用背景
随着各类小程序API不断的更新,现有的Taro2版本部分功能已不满足开发需求,例如Taro2对小程序独立分包不支持,那么Taro3通过配置项就能快速解决,像Taro3.3还添加了对html元素的支持。在这个背景下开始产生了萌发了使用Taro3的想法。
Taro原理对比
Taro2(重编译时,轻运行时)
分为两个部分,第⼀部分是编译时,第⼆部分是运⾏时。编译时会先对⽤户的React代码进⾏编译,转换成各个端上的⼩程序都可以运⾏的代码,然后再在各个⼩程序端上⾯都配上⼀个对应的运⾏时框架进⾏适配,最终让这份代码运⾏在各个⼩程序端上⾯。
编译时是使用 babel-parser 将 Taro 代码解析成抽象语法树,然后通过 babel-types 对抽象语法树进行一系列修改、转换操作,最后再通过 babel-generate 生成对应的目标代码。
缺点:
- Taro 对 JSX 的⽀持是通过编译时的适配去实现的,由于jsx的灵活性太强。不能100%支持jsx。
- 不⽀持 source-map,对源码进行编译转换之后。用户不方便使用和调试
- 运⾏时的缺陷。对于每个⼩程序平台,都会提供对应的⼀份运⾏时框架进⾏适配。当修改⼀些 Bug 或者新增⼀些特性的时候,需要同时去修改多份运⾏时框架。不宜维护
Taro3(重运行时)
Taro3则可以大致理解为解释型架构(相对于Taro1/2而言),主要通过在小程序端模拟实现DOM、BOM API来让前端框架直接运行在小程序环境中,从而达到小程序和H5统一的目的,而对于生命周期、组件库、API、路由等差异,依然可以通过定义统一标准,各端负责各自实现的方式来进行抹平。而正因为Taro3的原理,在Taro3中同时支持React、Vue等框架,甚至还支持了jQuery,还能支持让开发者自定义地去拓展其他框架的支持,比如Angular,Taro3整体架构如下
Taro3之后⼩程序端的整体架构。⾸先是⽤户的React或Vue的代码会通过CLI进⾏ Webpack 打包,其次在运⾏时会提供React和Vue对应的适配器进⾏适配,然后调⽤Taro提供的DOM和BOM API, 最后把整个程序渲染到所有的⼩程序端上⾯。
Taro3新特性
Taro3新特性参考文档:docs.taro.zone/blog/2021-0…
- 支持跨框架开发,React、Nerv、Vue 2、Vue 3
- 跨端:h5,微信,支付宝,百度,字节跳动等小程序
- 解决穿透问题,可以通过catchMove属性解决,
<View catchMove/>,增加虚拟列表组件VirtualList,不限宽高,列表底部renderBottom={<View>我就是底线</View>};并同步更新了最新微信官方api - 支持小程序独立分包功能,使用方式:在对应分包配置项中使用 independent: true即可,注意:独立分包中使用的代码不能使用依赖主包相应的工具类,否则报错
- 支持渲染Html字符串,可集成weui和antd Design Mobile
标签支持参考文档: github.com/NervJS/taro… 其中几个点说下:
- 元素标签转换规则:
-
由于小程序
<Text>不能够嵌套<View>,<Image>等块级元素,和html<span>标签冲突,所以转化为view块级元素.需要将span开启默认行内样式,<i>等行内元素嵌套块级元素的写法不被兼容。所以在开发过程中需要规范写法。 -
表单元素checkbox/radio元素需要使用
<CheckboxGroup>/<RadioGroup>包裹方可正常使用。下拉选择框select+option不做映射,直接使用代替,具体使用详见demo
- 元素属性转换规则:
- 事件映射
- 部分h5样式兼容问题,对标签选择器不兼容,可通过标签类名:h5-${tagName} ,使用postcss插件处理后使用类选择器进行操作 。
- 获取元素尺寸不兼容。h5获取是同步获取而小程序是异步获取,无法兼容,需要如下处理下:
*// h5*
const el = document.getElementById('#inner')
const res = el.getBoundingClientRect()
console.log(res)
*// 小程序*
const query = Taro.createSelectorQuery()
query.select('#inner')
.boundingClientRect()
.exec(res => {
console.log(res)
})
<canvas>、<video>、<audio>等DOM API差异
- 部分样式或 CSS 选择器在小程序中不支持
- 通配符 *
- 媒体查询
- 属性选择器,当属性不是对应小程序组件的内置属性时
缺点
- 打包后文件过大,导致无法扫码预览
- 开启线上压缩打包后调试不方便
- taro1/2不能平滑升级到taro3.升级工作量大
Taro3 Demo:
1、 安装依赖:
npm intsall @tarojs/plugin-html antd-mobile@2.3.4
2、 在config下的index.js中 plugins中加入配置项:
['@tarojs/plugin-html', {
pxtransformBlackList: [/am-/, /demo-/, /^body/]
}]
3、 使用html例子
import Taro from "@tarojs/taro"
import { Component } from "react"
import { Button } from 'antd-mobile'
import { CheckboxGroup, RadioGroup, Picker, View } from "@tarojs/components"
import styles from './index.module.less'
export default class HtmlDemo extends Component {
state = {
selector: ['中国', '美国', '巴西', '日本'],
selectorChecked: '中国',
timeSel: '12:01',
dateSel: '2018-04-22'
}
onChange = e => {
this.setState({
selectorChecked: this.state.selector[e.detail.value]
})
}
render() {
return (
<div>
<Button type='primary'>Ant-primary</Button>
<a href="/ybsc/pages/order/index" target='_blank'>a标签使用</a>
<div>div标签使用</div>
<h5>h5标签中使用</h5>
<p>p标签使用</p>
<span>span标签使用</span>
<br />
<span>inputText标签使用:</span>
<input type='text' className={styles.h5Input}></input>
<span>inputPassword使用:</span>
<input type='password' className={styles.h5Input}></input>
<CheckboxGroup>
box1:<input type='checkbox' className={styles.h5Input}></input>
box2:<input type='checkbox' className={styles.h5Input}></input>
box3:<input type='checkbox' className={styles.h5Input}></input>
</CheckboxGroup>
<br />
<RadioGroup>
rdio1:<input type='radio' name='daido' value='1'></input>
rdio2:<input type='radio' name='radio' value='2'></input>
</RadioGroup>
<Picker mode='selector' range={this.state.selector} onChange={this.onChange}>
<View className='picker'>
当前选择:{this.state.selectorChecked}
</View>
</Picker>
</div>
)
}
}
整体运行效果如下:
Taro2.0升级Taro3.0
升级前准备
由于升级过程中可能需要开发旧版本功能迭代。不能影响之前的开发环境,所以本次采用nvm(nvm使用文档)管理多个node版本,在不同的node环境中(如果已经安装过node需要卸载)。
windows安装nvm参考链接: blog.csdn.net/lewky_liu/a…
mac安装nvm参考链接:segmentfault.com/a/119000001…
升级步骤:全局升级taro,删除项目中node_modules和package-lock.json重新安装依赖。具体依赖如下:
-
升级全局环境:
- node: nvm install v14.17.0 ;
- tarojs: npm i -g @tarojs/cli@3.3.7 ;
-
升级项目所需依赖项
- runtime : npm i @tarojs/runtime@3.3.7
- mini-runner: npm i @tarojs/mini-runner@3.3.7
- components : npm i @tarojs/components@3.3.7
- taro : npm i@tarojs/taro@3.3.7
- webpack: npm i @tarojs/webpack-runner@3.3.7
- react: npm i react@17.0.0
- mobx: npm i mobx-react@6.7.1
- babel: npm i @babel/core@7.8.0 @babel/runtime@7.7.7 babel-preset-taro@3.3.7
- 新建babel.config.js,内容如下:
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
module.exports = {
presets: [
['taro', {
framework: 'react',// 开发语言框架
ts: true // 是否支持ts
}]
]
}
- 在项目根config 目录下的index.js文件中加上framework: 'react',配置项,配置开发框架(支持react, nerv, vue, vue3)
- 将已有的配置项app.jsx中分离出来放入app.config.js中,页面组件中每个config配置项需新建*.config.js配置文件将其配置项放入其中
- 将所有 Compontent从tarojs引入方式更换为从react导入。如下所示:
将Component 导入方式由
import Taro, { Component } from '@tarojs/taro'
更换为react导
import Component from '@react'
- 如果使用了mobx管理全局状态,需要将所有从tarojs/mobx引入更换为 'mobx-react'
import {observer,inject} from 'tarojs/mobx => import {observer,inject} from 'mobx-react'
//如果注入变量为 const store = {userstore,toolstore} 在使用注入时应为:
<Provider store={store}>this.props.children}</Provider>
//获取时应为
const {userstore}= this.props.store
- 支持typescript (tsc -v 查看当前安装版本):
npm install -g typescript
npm install @typescript-eslint/eslint-plugin@4.15.1 --save-dev
npm install @typescript-eslint/parser4.15.1 --save-dev
新建tsconfig.json文件/或用命令执行tsc --init 初始化 ,内容可根据需要选取配置:
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"removeComments": false,
"preserveConstEnums": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"noImplicitAny": false,
"allowSyntheticDefaultImports": true,
"outDir": "lib",
"noUnusedLocals": true,
"noUnusedParameters": true,
"strictNullChecks": true,
"sourceMap": true,
"baseUrl": ".",
"rootDir": ".",
"jsx": "react-jsx",
"allowJs": true,
"resolveJsonModule": true,
"typeRoots": [
"node_modules/@types",
"global.d.ts"
]
},
"exclude": [
"node_modules",
"dist"
],
"compileOnSave": false
}
升级后遇到的问题
升级后遇到得问题(报错问题)
-
问题:TypeError: Cannot call a class as a function。
原因: Compontent没有从react引入
解决:将Compontent从react中引入
- 问题:taro3 does not contain an export named :
原因:导出组件方式为单个
解决:
组件引入方式由
import { XxxxxXxxx } from '../../component/xxxxxx'
变为
import XxxxxXxxx from '../../component/xxxxxx'
方式引入或者导出文件采用多文件对象导出方式
- 问题:Cannot read property this.$router of undefined
原因:this.$router属性删除。
解决:将this.$router获取路由参数的方式需更换为 getCurrentInstance().router方式获取,
getCurrentInstance从tarojs中导入
- 问题:项目组件config中配置顶部栏样式不生效
原因:移除在组件中config配置项
解决:需要在组件页面文件中使用config配置需新建* *.config.js文件中导出(注意 ** 表示文件目录名称与文件入口同级)
- 问题:没有使用 .module.less 创建样式,在使用同名的类时,样式错乱
原因:没有使用 *.module.less 创建样式文件会挂载到全局作用域中*
解决:未使用css module的页面,对父元素加一个唯一class进行包裹或者改写未css模块化包裹
- 问题:在组件中定义的样式或者元素选择器样式不生效
原因:taro2编译后的和taro3编译的dom节点有差异,如<Header/>taro2编译后:<header>....</header>。
taro3编译后为....,导致header上的定义的样式找不到
解决:组件使用时在外包裹一层view.如<view><header/></view>,将样式移动至外层view中处理
- 问题:页面中点击跳转无反应
原因:taro升级后数据接口改变导致。用taro2方式获取不到
解决方案,分两种情况:
1. 点击页面报错this.$router.params undefined:将this.$router.* 获取方式变更为getCurrentInstance().router.*获取//import { getCurrentInstance } from '@tarojs/taro'
2. this丢失,组件中添加的事件点击无反应或者绑定的事件没反应: 将 onClick={this._handleBtn} 更换为 onClick={(e) => { this._handleBtn(e) }}即可(或使用bind改变this指向)(或采用hooks写法)
- 问题:开发环境阅览时无法阅览
解决:开发时启用生产压缩 set NODE_ENV=production && taro build --type weapp --watch
- 问题:chunk common [mini-css-extract-plugin] 开发启动警告 :
解决方案:搜索使用组件的位置,将引入顺序更换为正确优先级导入
- 编译警告: 'mobx' does not contain an export named '_allowStateReadsEnd'.;
'mobx' does not contain an export named '_allowStateReadsStart'.
解决方案:安装依赖问题,删除依赖重新安装,删除package-lock.json ,mobx-react版本和官方创建模板保持一致
- 问题:Cannot set property 'state' of undefined、
原因:组件中使用了constructor()没有调用super(props)
解决:在constructor中首行加入super(props)
- 问题:关于原生属性dataset获取不到问题(不能支持用户自定义设置
data-*属性
原因:taro3数据结构发生改变
解决:参考[event.atrget.dataset获取不到问题issue](https://github.com/NervJS/taro/issues/7313),如果需要,则通过document.getElementById('xxx').prop获取
- 问题:event数据结构发生改变。获取对应的属性需更换 taro2 event数据结构如下:
taro3后event数据结构如下:
点击触发事件后,taro2通过e.target获取target中dataset等属性,taro3 target属性包含在mpEvent中,并且target中的dataset是空。taro3需要避免在target中获取dataset属性
参考链接
- Taro3.0官方文档
- Taro github地址入口
- taro3参考文章
- taro3官方博客说明文档
- windows安装nvm参考链接: blog.csdn.net/lewky_liu/a…
- mac安装nvm参考链接:segmentfault.com/a/119000001…