Taro 浅析用法与原理

json 配置

  "postcss": {
    "plugins": {
      "autoprefixer": {},
      "postcss-px2rem": {
        "remUnit": 75
      },
      "postcss-assets": {
        "loadPaths": "[path.resolve(__dirname, 'src/assets/img')]",
        "relative": true
      }
    }
  },
class Demo extends Component {
  constructor(props) {
    super(props);
  }
  componentWillMount() {
    window.temp = "demo";
  }
}

生命周期

页面切换的执行顺序:

  • 离开的顺序: index 的跳转方法 后面跟着 componentdDidHide

  • 进入的顺序: componentWillMount componentDidShow componentDidMount

15 版本的生命周期与方法

  • constructor,顾名思义,组件的构造函数。一般会在这里进行 state 的初始化,事件的绑定等等

  • componentWillMount,是当组件在进行挂载操作前,执行的函数,一般紧跟着 constructor 函数后执行

  • componentDidMount,是当组件挂载在 dom 节点后执行。一般会在这里执行一些异步数据的拉取等动作

  • shouldComponentUpdate,返回 false 时,组件将不会进行更新,可用于渲染优化

  • componentWillReceiveProps,当组件收到新的 props 时会执行的函数,传入的参数就是 nextProps ,你可以在这里根据新的 props 来执行一些相关的操作,例如某些功能初始化等

  • componentWillUpdate,当组件在进行更新之前,会执行的函数

  • componentDidUpdate,当组件完成更新时,会执行的函数,传入两个参数是 prevProps 、prevState

  • componentWillUnmount,当组件准备销毁时执行。在这里一般可以执行一些回收的工作,例如 clearInterval(this.timer) 这种对定时器的回收操作

16 版本的生命周期与方法

  • constructor,顾名思义,组件的构造函数。一般会在这里进行 state 的初始化,事件的绑定等等

  • componentDidMount,是当组件挂载在 dom 节点后执行。一般会在这里执行一些异步数据的拉取等动作

  • shouldComponentUpdate,返回 false 时,组件将不会进行更新,可用于渲染优化

  • componentDidUpdate,当组件完成更新时,会执行的函数,传入两个参数是 prevProps 、prevState

  • componentWillUnmount,当组件准备销毁时执行。在这里一般可以执行一些回收的工作,例如 clearInterval(this.timer) 这种对定时器的回收操作

taro 版本对应的是 16 之前

去对比了一下 react 16 的生命周期

挂载 当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:

  • constructor()

  • static getDerivedStateFromProps()

  • render()

  • componentDidMount(-

componentwillMount 将被舍弃

更新

当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:

  • static getDerivedStateFromProps()

  • shouldComponentUpdate()

  • render()

  • getSnapshotBeforeUpdate()

  • componentDidUpdate()

卸载

当组件从 DOM 中移除时会调用如下方法:

  • componentWillUnmount()

其他 APIs 组件还提供了一些额外的 API:

  • setState()

  • forceUpdate()

class 属性

  • defaultProps

  • displayName

如果 props.color 被设置为 null,则它将保持为 null render() {

实例属性

  • props

  • state

了解了一下小程序的生命周期:

  • 应用级别的生命周期 onLaunch onShow onHide

  • onLaunch 是当小程序初始化完成时,会触发 onLaunch(全局只触发一次)

  • onShow 是当小程序启动,或从后台进入前台显示,会触发 onShow;

  • onHide 是当小程序从前台进入后台,会触发 onHide;

页面的生命周期 onLoad、onReady、onShow、onHide、onUnload

  • onLoad 是监听页面加载的函数

  • onReady 是监听页面初次渲染完成的函数

  • onShow 是监听页面显示的函数

  • onHide 是监听页面隐藏的函数

  • onUnload 是监听页面卸载的函数

Taro.pxTransform(10) // 小程序:rpx,H5:rem

if 语句和 for 循环在 JavaScript 中不是表达式,因此它们不能直接在 JSX 中使用,所以你可以将它们放在周围的代码中。

布尔值、Null 和 Undefined 被忽略

props 只读性
  1. 不要直接更新状态

  2. 状态更新一定是异步的

Taro 可以将多个 setState() 调用合并成一个调用来提高性能。 因为 this.state 和 props 一定是异步更新的,所以你不能在 setState 马上拿到 state 的值,例如:

合并是浅合并,所以 this.setState({comments}) 不会改变 this.state.posts 的值,但会完全替换 this.state.comments 的值。

当你通过 bind 方式向监听函数传参,在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面。

然而,在 JSX 里使用 JS 是有限制的,只能使用一些表达式,不能定义变量,使用 if/else 等,你可以用提前定义变量;用三元表达式来达到同样的效果。

组件中如果收到了新的 props,就会重新执行一次 render 函数,也就是重新渲染一遍。

下面这种写法可以尝试下:

api

微信提供的回调是 bindgetuserinfo,但是 Taro 将 bind 事件都封装成了 on 事件,这个需要注意一下

遇到的坑

最佳实践

不能使用 wx:for , 只能使用 map 方法

无效使用方案

有效解决方案

解决方案:

不能在 jsx 参数中使用匿名函数

可以使用 bind 或者类参数

跟 vue 不同的点。不允许在 jsx 参数中传入 jsx 元素 不能使用内置组件化的 slot 功能

无效方案

解决方案

通过 props 传值在 JSX 模板中预先判定显示内容,或通过 props.children 来嵌套子组件。 小程序端不要在组件中打印传入的函数 this.props.onXxx && this.props.onXxx() 这种判断函数是否传入来进行调用的写法是完全支持的。

render () { // 增加一个兼容判断 return this.state.abc && }

在微信小程序中,从调用 Taro.navigateTo、Taro.redirectTo 或 Taro.switchTab 后,到页面触发 componentWillMount 会有一定延时。因此一些网络请求可以提前到发起跳转前一刻去请求。

样式层面

分享按钮 包裹图片时出现点击无效 要设置 z-index

结合云函数

这里我用到了上传文件的功能, 结合存储

文件主要分为两大类:代码包文件和本地文件(上限 50M)。

本地文件是通过调用接口本地生成,或通过网络下载后存储到本地的文件,包括本地临时文件、本地缓存文件和本地用户文件。

taro 组件使用 keys 小程序原生组件使用 taroKeys

Taro 中,JSX 会编译成微信小程序模板字符串,因此你不能把 map 函数生成的模板当做一个数组来处理。当你需要这么做时,应该先处理需要循环的数组,再用处理好的数组来调用 map 函数。例如上例应该写成:

在 Taro 中使用函数式组件有以下限制:

  1. 函数的命名需要遵循帕斯卡式命名法;

  2. 一个文件中只能定义一个普通函数式组件或一个 Class 组件

由于一个文件不能定义两个组件,但有时候我们需要组件内部的抽象组件

  1. 函数的命名必须以 render 开头,render 后的第一个字母需要大写

  2. 函数的参数不得传入 JSX 元素或 JSX 元素引用

  3. 函数不能递归地调用自身

报没有 jsx 错误

slot

Children 与组合 相当于 slot 请不要对 this.props.children 进行任何操作。 this.props.children && this.props.children、this.props.children[0] 在 Taro 中都是非法的。 this.props.children 无法用 defaultProps 设置默认内容。 不能把 this.props.children 分解为变量再使用

通过字符串创建 ref 只需要把一个字符串的名称赋给 ref prop

通过传递一个函数创建 ref, 在函数中被引用的组件会作为函数的第一个参数传递。

通过函数创建的 ref 是不是不能在函数式组件中使用 果然如此

你基本都能使用小程序本身提供的 API 达到同等的需求,其中就包括但不限于:

  1. 使用 this.$scope.triggerEvent 调用通过 props 传递的函数;

  2. 通过 this.$scope.selectComponent 和 wx.createSelectorQuery 实现 ref;

  3. 通过 getCurrentPages 等相关方法访问路由;

  4. 修改编译后文件 createComponent 函数创建的对象

尽量避免在 componentDidMount 中调用 this.setState 因为在 componentDidMount 中调用 this.setState 会导致触发更新

尽量避免,可以在 componentWillMount 中处理

不要在调用 this.setState 时使用 this.state 由于 this.setState 异步的缘故,这样的做法会导致一些错误,可以通过给 this.setState 传入函数来避免

不要在 componentWillUpdate/componentDidUpdate/render 中调用 this.setState

值为 true 的属性可以省略书写值

最后更新于

这有帮助吗?