从旧版本迁移到 Taro Next
这是一篇针对旧版本用户升级到 Taro Next 的迁移指南。因为本章内容包含了许多详尽的阐述和迁移例子,所以看起来有一些长。但请不要担心,Taro Next 大部分用法还是和旧版本一样的。本章没有提到的内容,你可以像旧版本的 Taro 一样操作或使用。
事实上,你并不需要去更改任何业务的逻辑代码,许多更改使用编辑器的「查找/替换」就可以完成。你甚至不需要完整地阅读整章内容(重点在 1,2 小节, API 和 项目/页面配置),只有当出问题时定位到具体的小节即可。
更新到 Taro Next 首先需要更新项目依赖:
API
在旧版本 Taro 中,我们把所有面向应用开发者的 API 都放在 @tarojs/taro
里,一个典型的 Taro 组件/页面会像这样:
在 Taro Next 中,属于框架本身的 API 从框架自己的包中引入,其它的 API 仍然从 @tarojs/taro
引入。使用哪个框架来进行开发完全由开发者来决定。
Nerv 是凹凸实验室的一个开源类 React 框架,体积比 React 更小,多数情况性能表现也比 React 更好。但某些 React 生态的库兼容性可能会出现问题。
项目/页面配置
在旧版本 Taro 中,页面/项目的配置挂载在类组件的类属性或函数式的属性上,通过 AST 分析取出来,然后生成 JSON 文件。但这样做,项目页面的配置就无法动态地生成:
在 Taro Next 中,会有一个新的文件:*.config.js
,*
代表你页面/项目文件的文件名,config
文件必须和页面/项目文件在同一文件夹。在这个文件里你可以使用任意合法的 JavaScript 语法,只要最终把配置作为对象通过 export default
出去即可:
一个完整的项目文件结构示例会像这样:
使用第三方 React 库
如果你需要引入 React 相关生态的库,直接通过 npm install
安装然后引入使用即可,Taro 不会再维护类似于 taro-redux
、taro-mobx
之类的库。
路由
在旧版本中可以通过 this.$router
访问当前组件/页面路由的详情。在 Taro Next 对应的 API 是在 @tarojs/taro
中的 Current.router
,两者的属性一模一样。
而对于项目入口组件而言,路由信息我们推荐在 componentDidShow
生命周期的参数中直接读取。
聪明的读者已经猜到了,
Current.router
其实是访问小程序当前页面onLoad
生命周期参数的快捷方式。
样式
在 Taro Next 中,没有 组件的外部样式和全局样式 的概念,组件的配置(config.js
)是无效的,页面和入口文件引入的 CSS 都会变成全局 CSS ,没有了 externalClasses
和 addGlobalClass
这两个概念。
如果你需要带作用域的 CSS,可以考虑使用 CSS Modules。
编译配置
jsxAttributeNameReplace 配置已被移除。因为我们不需要配置 externalClasses
,这个属性也失去了它存在的意义。
编译依赖库
Webpack
升级到 Webpack@4
,Babel
升级到 babel@7
。Webpack 升级是在 taro@2
中完成的,如果你是从 taro@1
升级上来的话,或许需要去看看 Taro 2 更改 查看使用 Webpack 编译后带来的变化。
升级到 babel@7
意味着你的项目文件全部都会通过根目录的 babel.config.js
的配置进行编译。
ESLint 和最佳实践
eslint-plugin-taro
已被废弃,你不再需要遵循它所规定的种种限制。你可以发挥你的创造力使用任何合法的 JSX 语法:
旧版本文档所提到的最佳实践也不必再遵循。也就是说,即便你不给组件设置 defaultProps
,自定义事件名不以 on
开头(还有其它的旧版本代码风格最佳实践),你的代码也能运行。但值得注意的是,遵循这样的 代码风格最佳实践 可以让你的代码更健壮,你的应用也会因此而收益。而对于另外的一些由于旧版本 Taro 执行机制的 hack(例如 render 调用两次,state 和 props 无法重名,不要打印组件),这类最佳实践可以不必理会。
Ref & DOM
Taro Next 在底层会维护一个精简的 DOM 系统,在框架中使用 ref
链接到的是一个 Taro Element 实例,因此你直接可以使用 HTMLElement
的部分方法直接操作它。如果你需要获取原生小程序 DOM 实例,那需要使用原生小程序的 SelectorQuery
来获取。
大部分和渲染相关的 DOM 属性你都可以通过像 Web 开发一样获取或设置(如果有必要的话你甚至可以通过
parentNode
和childNodes
访问元素的父元素和子元素!),但元素的位置你还是必须通过原生小程序 DOM 实例的boundingClientRect()
和scrollOffset()
方法获取。
另外,如果你使用的是 React,就将无法使用字符串的形式来使用 ref
。(Nerv 不受此影响)
在未来,我们可能会在 Taro Element 上提供一个可以快速访问小程序 DOM 实例的属性。目前请按照上述例子使用。
生命周期
当你使用 React 时(使用 Nerv 不受此影响),以下生命周期被更名:
componentWillMount()
->UNSAFE_componentWillMount()
componentWillReceiveProps
->UNSAFE_componentWillReceiveProps()
componentWillUpdate
->UNSAFE_componentWillUpdate()
新增一个生命周期: componentDidCatch(err, info)
,这是由框架本身(React 或 Nerv)提供的。componentDidCatch(err, info)
会在组件和它的子孙抛出错误时触发,第一个参数 err
指向抛出的错误,第二个参数 info
是组件的调用信息。
componentDidCatch
和原有的componentDidCatchError
共同存在,区别在于componentDidCatchError
只能在入口组件(App)中使用,对应原生小程序的生命周期onError()
,componentDidCatch
可以在任何 React/Nerv 类组件中使用(包括入口组件)。
Hooks
在 Taro Next,Taro 的专有 Hooks(例如 usePageScroll
, useReachBottom
)从 @tarojs/taro
中引入,框架自己的 Hooks (例如 useEffect
, useState
)从对应的框架引入。
另外,旧版本的 Taro 可以在 Class Component 中使用 Hooks,但 React 是不允许这样的行为的。
$scope 和 $componentType
由于 Taro Next 没有自定义组件,所以也没有了 this.$scope
和 this.$componentType
的概念。Current.page
可以返回当前小程序页面的实例。