Taro原理|原理篇
30 秒速记
- 核心判断:小程序通过逻辑层、渲染层与宿主桥接实现跨端运行,通信与序列化成本决定交互上限
- 原理主线:围绕 「一、Taro 的安装与使用」、「二、Taro 开发说明与注意事项」、「三、Taro 设计思想及架构」 建立输入、状态变化与输出之间的因果关系
- 文章范围:介绍了 Taro 框架的原理、安装方法、项目初始化流程,以及如何编译和预览多端小程序,帮助开发者快速上手并理解 Taro 的核心机制。
- 边界与代价:不同平台组件、线程模型和包体限制并不完全一致,跨端抽象无法抹平所有能力差异
- 工程落地:实现时控制跨层数据量、拆分包体、减少频繁 setData,并在目标真机验证
Taro 的跨端运行依赖逻辑层、渲染层和宿主环境之间的桥接,通信及序列化成本会直接影响交互上限。 工程上可以通过 @tarojs/cli 创建项目,再针对微信小程序等目标端完成编译和预览。由于文中实现对应特定版本,我一般会先确认工具主版本,并用实际交互验证正常路径和边界行为。
这篇文章不要按 API 清单来背。先用上面的 Mind Map 建立全局结构,再通过交互 DEMO 观察正常路径和边界路径如何改变状态;阅读正文时重点核对每一步的输入、负责执行的参与者、产生的中间状态以及最终可观察结果。遇到版本敏感结论,要把“历史实现”“当前行为”和“工程兼容策略”分开说明;遇到性能或架构取舍,则用实际指标、失败现象和验证手段支撑判断。
版本校准: 原理文章中的代码代表特定实现与写作时间。应用到当前项目时,应先确认浏览器、框架或工具的主版本,再区分稳定的规范语义、可变化的内部实现和项目自身约束。
# 一、Taro 的安装与使用
# 1.2.1 微信小程序
选择微信小程序模式,需要自行下载并打开微信开发者工具,然后选择项目根目录进行预览
微信小程序编译预览及打包
# npm script
$ npm run dev:weapp
$ npm run build:weapp
# 1.2.3 支付宝小程序
选择支付宝小程序模式,需要自行下载并打开支付宝小程序开发者工具,然后在项目编译完后选择项目根目录下 dist 目录进行预览
支付宝小程序编译预览及打包:
# npm script
$ npm run dev:alipay
$ npm run build:alipay
# 1.2.4 H5
H5 编译预览及打包:
# npm script
$ npm run dev:h5
# 仅限全局安装
$ taro build --type h5 --watch
# 1.3 更新 Taro
Taro提供了更新命令来更新CLI工具自身和项目中Taro相关的依赖。
更新 taro-cli 工具
# taro
$ taro update self
# npm
更新项目中
Taro相关的依赖,这个需要在你的项目下执行
$ taro update project
# 二、Taro 开发说明与注意事项
# 2.1 微信小程序开发工具的配置
由于
Taro编译后的代码已经经过了转义和压缩,因此还需要注意微信开发者工具的项目设置
- 设置关闭
ES6转ES5功能 - 设置关闭上传代码时样式自动补全
- 设置关闭代码压缩上传

# 2.2 Taro 与 React 的差异
由于微信小程序的限制,
React中某些写法和特性在Taro中还未能实现,后续将会逐渐完善。 截止到本小册发布前,Taro的最新版本为1.1,因此以下讲解默认版本为1.1
# 2.2.1 暂不支持在 render() 之外的方法定义 JSX
由于微信小程序的
template不能动态传值和传入函数,Taro暂时也没办法支持在类方法中定义JSX
无效情况
class App extends Component {
_render() {
return <View />
}
}
class App extends Component {
renderHeader(showHeader) {
return showHeader && <Header />
}
}
class App extends Component {
renderHeader = (showHeader) => {
return showHeader& & <Header />
}
}...
解决方案
在 render 方法中定义
class App extends Component {
render () {
const { showHeader, showMain } = this.state
const header = showHeader && <Header />
const main = showMain && <Main />
return (
<View>
{header}
{main}
</View>
)
}
}...
# 2.2.2 不能在包含 JSX 元素的 map 循环中使用 if 表达式
无效情况
numbers.map((number) => {
let element = null
const isOdd = number % 2
if (isOdd) {
element = <Custom />
}
return element
})
numbers.map((number) => {
let isOdd = false
if (number % 2) {
isOdd = true
}
return isOdd && <Custom />
})...
解决方案
尽量在 map 循环中使用条件表达式或逻辑表达式。
numbers.map((number) => {
const isOdd = number % 2
return isOdd ? <Custom /> : null
})
numbers.map((number) => {
const isOdd = number % 2
return isOdd && <Custom />
})...
# 2.2.3 不能使用 Array.map 之外的方法操作 JSX 数组
Taro 在小程序端实际上把 JSX 转换成了字符串模板,而一个原生
JSX表达式实际上是一个React/Nerv元素(react - element)的构造器,因此在原生 JSX 中你可以对任何一组 React 元素进行操作。但在 Taro 中你只能使用 map 方法,Taro 转换成小程序中wx:for…
无效情况
test.push(<View />)
numbers.forEach(numbers => {
if (someCase) {
a = <View />
}
})
test.shift(<View />)
components.find(component => {
return component === <View />
})
components.some(component => component.constructor.__proto__ === <View />.constructor)
numbers.filter(Boolean).map((number) => {
const element = <View />
return <View />
})...
解决方案
先处理好需要遍历的数组,然后再用处理好的数组调用 map 方法。
numbers.filter(isOdd).map((number) => <View />)
for (let index = 0; index < array.length; index++) {
// do you thing with array
}
const element = array.map(item => {
return <View />
})...
# 2.2.4 不能在 JSX 参数中使用匿名函数
无效情况
<View onClick={() => this.handleClick()} />
<View onClick={(e) => this.handleClick(e)} />
<View onClick={() => ({})} />
<View onClick={function () {}} />
<View onClick={function (e) {this.handleClick(e)}} />...
解决方案
使用 bind 或 类参数绑定函数。
<View onClick={this.props.hanldeClick.bind(this)} />
# 2.2.5 不能在 JSX 参数中使用对象展开符
微信小程序组件要求每一个传入组件的参数都必须预先设定好,而对象展开符则是动态传入不固定数量的参数。所以
Taro没有办法支持该功能
无效情况
<View {...this.props} />
<View {...props} />
<Custom {...props} />
解决方案
开发者自行赋值:
render () {
const { id, title } = obj
return <View id={id} title={title} />
}...
# 2.2.6 不允许在 JSX 参数(props)中传入 JSX 元素
由于微信小程序内置的组件化的系统不能通过属性(props) 传函数,而 props 传递函数可以说是 React 体系的根基之一,我们只能自己实现一套组件化系统。而自制的组件化系统不能使用内置组件化的 slot 功能。两权相害取其轻,我们暂时只能不支持该功能…
无效情况
<Custom child={<View />} />
<Custom child={() => <View />} />
<Custom child={function () { <View /> }} />
<Custom child={ary.map(a => <View />)} />...
解决方案
通过
props传值在JSX模板中预先判定显示内容,或通过props.children来嵌套子组件

