前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版

Taro原理总结

首页2018-11-26 15:54:23Front-End
Taro

来自掘金小册笔记

# 一、Taro 的安装与使用

# 1.1 安装

$ npm install -g @tarojs/cli
@前端进阶之旅: 代码已经复制到剪贴板
taro -V
@前端进阶之旅: 代码已经复制到剪贴板

# 1.2 使用

使用命令创建模板项目

$ taro init myApp
@前端进阶之旅: 代码已经复制到剪贴板

# 1.2.1 微信小程序

选择微信小程序模式,需要自行下载并打开微信开发者工具,然后选择项目根目录进行预览

微信小程序编译预览及打包

# npm script
$ npm run dev:weapp
$ npm run build:weapp
@前端进阶之旅: 代码已经复制到剪贴板

# 1.2.2 百度小程序

选择百度小程序模式,需要自行下载并打开 百度开发者工具,然后在项目编译完后选择项目根目录下 dist 目录进行预览

百度小程序编译预览及打包

# npm script
$ npm run dev:swan
$ npm run build:swan
@前端进阶之旅: 代码已经复制到剪贴板

# 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.2.5 React Native

React Native 端运行需执行如下命令,React Native 端相关的运行说明请参见 React Native 教程

# npm script
$ npm run dev:rn
@前端进阶之旅: 代码已经复制到剪贴板

# 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 来嵌套子组件

# 2.2.7 不支持无状态组件(Stateless Component)

由于微信的 template 能力有限,不支持动态传值和函数,Taro 暂时只支持一个文件自定义一个组件。为了避免开发者疑惑,暂时不支持定义 Stateless Component

无效情况

function Test () {
  return <View />
}

function Test (ary) {
  return ary.map(() => <View />)
}

const Test = () => {
  return <View />
}

const Test = function () {
  return <View />
}...
@前端进阶之旅: 代码已经复制到剪贴板

解决方案

使用 class 定义组件。

class App extends Component {
  render() {
    return <View />
  }
}
@前端进阶之旅: 代码已经复制到剪贴板

# 2.3 命名规范

Taro 函数命名使用驼峰命名法,如onClick,由于微信小程序的 WXML 不支持传递函数,函数名编译后会以字符串的形式绑定在 WXML 上,囿于 WXML 的限制,函数名有三项限制

  • 方法名不能含有数字
  • 方法名不能以下划线开头或结尾
  • 方法名的长度不能大于 20

请遵守以上规则,否则编译后的代码在微信小程序中会报以下错误

# 2.4 推荐安装 ESLint 编辑器插件

Taro 有些写法跟 React 有些差异,可以通过安装 ESLint 相关的编辑器插件来获得人性化的提示。由于不同编辑器安装的插件有所不同,具体安装方法请自行搜索,这里不再赘述。 如下图,就是安装插件后获得的提示

fe
  • 一、Taro 的安装与使用
    • 1.1 安装
    • 1.2 使用
      • 1.2.1 微信小程序
      • 1.2.2 百度小程序
      • 1.2.3 支付宝小程序
      • 1.2.4 H5
      • 1.2.5 React Native
    • 1.3 更新 Taro
  • 二、Taro 开发说明与注意事项
    • 2.1 微信小程序开发工具的配置
    • 2.2 Taro 与 React 的差异
      • 2.2.1 暂不支持在 render() 之外的方法定义 JSX
      • 2.2.2 不能在包含 JSX 元素的 map 循环中使用 if 表达式
      • 2.2.3 不能使用 Array.map 之外的方法操作 JSX 数组
      • 2.2.4 不能在 JSX 参数中使用匿名函数
      • 2.2.5 不能在 JSX 参数中使用对象展开符
      • 2.2.6 不允许在 JSX 参数(props)中传入 JSX 元素
      • 2.2.7 不支持无状态组件(Stateless Component)
    • 2.3 命名规范
    • 2.4 推荐安装 ESLint 编辑器插件
    • 2.5 最佳编码方式
  • 三、Taro 设计思想及架构
    • 3.1 抹平多端差异
  • 四、CLI 原理及不同端的运行机制
    • 4.1 taro-cli 包
      • 4.1.1 Taro 命令
      • 4.1.2 包管理与发布
      • 4.1.3 taro-cli 包的目录结构如下
    • 4.2 用到的核心库
    • 4.3 Taro Init
      • 4.3.1 命令关联与参数解析
      • 4.3.2 参数解析及与用户交互
      • 4.3.3 模版文件操作
    • 4.4 Taro Build
      • 4.4.1 编译工作流与抽象语法树(AST)
      • 4.4.2 Babel 模块
      • 4.4.3 解析页面 Config 配置
  • 五、Taro 组件库及 API 的设计与适配
    • 5.1 多端差异
      • 5.1.1 组件差异
      • 5.1.2 API 差异
    • 5.2 多端适配
      • 5.2.1 样式处理
      • 5.2.2 组件封装
  • 六、JSX 转换微信小程序模板的实现
    • 6.1 代码的本质
    • 6.2 Babel
    • 6.3 实践例子
      • 6.3.1 设计思路
      • 6.3.2 WXML 和 JSX
  • 七、小程序运行时
    • 7.1 注册程序、页面以及自定义组件
    • 7.2 组件 state 转换
    • 7.3 将组件的生命周期对应到小程序组件的生命周期
    • 7.4 事件处理函数对应
    • 7.5 对 API 进行 Promise 化的处理
  • 八、H5 运行时
    • 8.1 H5 运行时解析
      • 8.1.1 组件实现
    • 8.2 API 适配
    • 8.3 路由
    • 8.4 Redux 处理
  • 九、更多参考

← Nginx中常用的模块整理与选型清单docker结合pm2部署node项目 →