概述

Taro 3 支持将 Web 框架直接运行在各平台,开发者使用的是真实的 Vue/Vue3 和 React 等框架。

但是 Taro 在组件、API、路由等规范上,遵循微信小程序规范,所以在 Taro 中使用 Vue/Vue3 和开发者熟悉的 Web 端有一些差异,以下将详细列出。

入口组件和页面组件

因为 Taro 遵循小程序的路由规范,所以引入了入口组件页面组件的概念,分别对应小程序规范的入口组件 app 和页面组件 page

一个 Taro 应用由一个入口组件和至少一个页面组件所组成。

内置组件

自 Taro v3.3+,支持使用 H5 标签进行开发,详情请见 使用 HTML 标签

Taro 中可以使用小程序规范的内置组件进行开发,如 <view><text><button> 等。

Taro 规范

  1. 组件名遵从小程序规范(全小写,kebab-case)。
  2. 组件属性遵从小程序规范(全小写,kebab-case)。
  3. Boolean 值的组件属性需要显式绑定为 true,不支持简写。
  4. 事件规范请看下一节:组件事件

示例代码

  1. <template>
  2. <swiper
  3. class="box"
  4. :autoplay="true"
  5. :interval="interval"
  6. indicator-color="#999"
  7. @tap="handleTap"
  8. @animationfinish="handleAnimationFinish"
  9. >
  10. <swiper-item>
  11. <view class="text">1</view>
  12. </swiper-item>
  13. <swiper-item>
  14. <view class="text">2</view>
  15. </swiper-item>
  16. <swiper-item>
  17. <view class="text">3</view>
  18. </swiper-item>
  19. </swiper>
  20. </template>
  21. <script>
  22. export default {
  23. data () {
  24. return {
  25. interval: 1000
  26. }
  27. },
  28. methods: {
  29. handleTap () {console.log('tap')},
  30. handleAnimationFinish () {console.log('finish')}
  31. }
  32. }
  33. </script>

注意:如果某平台新增的组件或组件的属性还没被 Taro 支持,可以提交 Issues,我们会尽快修复。

事件

事件和 Web 端一样。在事件回调函数中,第一个参数是事件对象,回调中调用 stopPropagation 可以阻止冒泡。

Taro 规范

  1. 使用 @ 修饰符(或 v-on:,更多用法可以参考Vue文档)替代小程序事件名中的 bind(替代支付宝小程序事件名中的 on)。
  2. Vue 中点击事件使用 @tap

示例代码

  1. <template>
  2. <!-- 注意,Vue 中点击事件需要绑定 @tap,-->
  3. <!-- 其余小程序事件名把 bind 换成 @ 即是 Taro 事件名(支付宝小程序除外,它的事件就是以 on 开头,需要把 on 换成 @)-->
  4. <scroll-view
  5. style="height: 300px"
  6. :scroll-y="true"
  7. @tap="handleClick"
  8. @scroll="handleScroll"
  9. @scrolltoupper="handleScrollToUpper"
  10. >
  11. <view style="height: 200px">1</view>
  12. <view style="height: 200px">2</view>
  13. <view style="height: 200px">3</view>
  14. </scroll-view>
  15. </template>
  16. <script>
  17. export default {
  18. methods: {
  19. handleClick(e) {console.log('handleClick')
  20. e.stopPropagation() // 阻止冒泡
  21. },
  22. handleScroll () {console.log('handleScroll')},
  23. handleScrollToUpper () {console.log('handleScrollToUpper')}
  24. }
  25. }
  26. </script>

Taro 3 在小程序端的事件机制

在 Taro 1 & 2 中,Taro 会根据开发者是否使用了 e.stopPropagation(),来决定在小程序模板中绑定的事件是以 bind 还是以 catch 形式。因此事件冒泡是由小程序控制的。

但是在 Taro 3,我们在小程序逻辑层实现了一套事件系统,包括事件触发和事件冒泡。在小程序模板中绑定的事件都是以 bind 的形式。

一般情况下,这套在逻辑层实现的小程序事件系统是可以正常工作的,事件回调能正确触发、冒泡、停止冒泡。

但是,小程序模板中绑定的 catchtouchmove 事件除了可以阻止回调函数冒泡触发外,还能阻止视图的滚动穿透,这点 Taro 的事件系统是做不到的。

阻止滚动穿透

上一点中,我们介绍了 Taro 3 的事件机制。因为事件都以 bind 的形式进行绑定,因此不能使用 e.stopPropagation() 阻止滚动穿透。

针对滚动穿透,目前总结了两种解决办法:

一、样式

使用样式解决:禁止被穿透的组件滚动

这也是最推荐的做法。

二、catchMove

Taro 3.0.21 版本开始支持

但是地图组件本身就是可以滚动的,即使固定了它的宽高。所以第一种办法处理不了冒泡到地图组件上的滚动事件。

这时候可以为 view 组件增加 catch-move 属性:

  1. // 这个 View 组件会绑定 catchtouchmove 事件而不是 bindtouchmove
  2. <view :catch-move="true"></view>

dataset

一般情况

我们建议按 Vue、 React 的 DSL 特性进行思考,因为 dataset 是小程序的特性。

dataset

dataset 是特别的模版属性,主要作用是可以在事件回调的 event 对象中获取到 dataset 相关数据。

这点 Taro 是支持的,在事件回调对象中可以通过 event.target.datasetevent.currentTarget.dataset 获取到。

模板属性

上一点所说的,Taro 对于小程序 dataset 的模拟是在小程序的逻辑层实现的。并没有真正在模板设置这个属性

但在小程序中有一些 API(如:createIntersectionObserver)获取到页面的节点的时候,由于节点上实际没有对应的属性而获取不到。

这时可以考虑使用 taro-plugin-inject 插件注入一些通用属性,如:

config/index.js

  1. const config = {
  2. plugins: [
  3. ['@tarojs/plugin-inject', {
  4. components: {
  5. View: {
  6. 'data-index': "'dataIndex'"
  7. },
  8. ScrollView: {
  9. 'data-observe': "'dataObserve'",
  10. }
  11. }
  12. }]
  13. ]
  14. }

生命周期触发机制

Taro 3 在小程序逻辑层上实现了一份遵循 Web 标准 BOM 和 DOM API。因此 Vue 使用的 document.appendChilddocument.removeChild 等 API 其实是 Taro 模拟实现的,最终的效果是把 Vue 的虚拟 DOM 树渲染为 Taro 模拟的 Web 标准 DOM 树。

因此在 Taro3 Vue 的生命周期触发时机和我们平常在 Web 开发中理解的概念有一些偏差。

Vue 的生命周期

Vue 组件的生命周期方法在 Taro 中都支持使用。

触发时机:

1. beforeMount ()

onLoad 之后,页面组件渲染到 Taro 的虚拟 DOM 之前触发。

2. mounted ()

页面组件渲染到 Taro 的虚拟 DOM 之后触发。

此时能访问到 Taro 的虚拟 DOM(使用 Vue ref、document.getElementById 等手段),并支持对其进行操作(设置 DOM 的 style 等)。

但此时不代表 Taro 的虚拟 DOM 数据已经完成从逻辑层 setData 到视图层。因此这时无法通过 createSelectorQuery 等方法获取小程序渲染层 DOM 节点。 只能在 onReady 生命周期中获取。

小程序页面的方法

小程序页面的方法,在 Taro 的页面中同样可以使用:在 Vue 对象中书写同名方法。

注意:小程序页面方法在各端的支持程度不一,请查阅对应小程序的文档。

Ref

在 Taro 中 ref 的用法和 Vue 完全一致,但是获取到的 “DOM” 和浏览器环境还有小程序环境都有不同。

Vue Ref

使用 Vue Ref 获取到的是 Taro 的虚拟 DOM,和浏览器的 DOM 相似,可以操作它的 style,调用它的 API 等。

但是 Taro 的虚拟 DOM 运行在小程序的逻辑层,并不是真实的小程序渲染层节点,它没有尺寸宽高等信息。

  • Vue2
  • Vue3

示例代码

  1. <template>
  2. <view id="only" ref="el" />
  3. </template>
  4. <script>
  5. export default {
  6. mounted () {
  7. // 获取到的 DOM 具有类似 HTMLElement 或 Text 等对象的 API
  8. console.log(this.$refs.el)
  9. }
  10. }
  11. </script>

示例代码

  1. <template>
  2. <view id="only" ref="el" />
  3. </template>
  4. <script>
  5. import { ref, onMounted } from 'vue'
  6. export default {
  7. setup () {
  8. const el = ref(null)
  9. onMounted(() => {
  10. // 获取到的 DOM 具有类似 HTMLElement 或 Text 等对象的 API
  11. console.log(el.value)
  12. })
  13. return { el }
  14. }
  15. }
  16. </script>

获取小程序 DOM

获取真实的小程序渲染层节点,需要在 onReady 生命周期中,调用小程序中用于获取 DOM 的 API。

  • Vue2
  • Vue3

示例代码

  1. <template>
  2. <view id="only" />
  3. </template>
  4. <script>
  5. import Taro from '@tarojs/taro'
  6. export default {
  7. onReady () {
  8. // onReady 触发后才能获取小程序渲染层的节点
  9. Taro.createSelectorQuery().select('#only')
  10. .boundingClientRect()
  11. .exec(res => console.log(res))
  12. }
  13. }
  14. </script>

示例代码

  1. <template>
  2. <view id="only" />
  3. </template>
  4. <script>
  5. import Taro from '@tarojs/taro'
  6. export default {
  7. onReady () {
  8. // onReady 触发后才能获取小程序渲染层的节点,Vue3 需要使用 Taro.nextTick 确保已经渲染完成
  9. Taro.nextTick(() => {
  10. Taro.createSelectorQuery().select('#only')
  11. .boundingClientRect()
  12. .exec(res => console.log(res))
  13. })
  14. }
  15. }
  16. </script>

v-html

在小程序端,使用 v-html 时有一些额外的配置选项和需要注意的地方,详情请参考《渲染 HTML》

兼容 <transition>

<transition> 组件内部使用了 getComputedStyle,用于嗅探组件上的动画样式。但是在小程序中没有办法实现 getComputedStyle,可以通过以下方法进行 hack:

为元素的 style 设置 transitionDurationanimationDuration 指定过渡时间,即可兼容 <transition>

  1. <transition>
  2. <view style="animationDuration: 0.5s" />
  3. </transition>

其它限制

  • 由于小程序访问元素位置为异步 API,因此小程序中无法使用内置的 transition-group 组件。
  • 小程序中不支持 <style scoped>,建议使用 cssModules 代替。#6662
  • 所有组件的 id 必须在整个应用中保持唯一(即使他们在不同的页面),否则可能导致事件不触发的问题,#7317