简介
Taro 是一个遵循 React 语法规范的开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5 等应用,内置了UI组件,还有物料市场,只编写一套代码就能够适配到多端。
Tara 遵循 React 语法,集成的是 Nerv 框架。
Nerv是一款基于virtual dom技术的类React UI框架,它基于React标准,拥有和React一致的API与生命周期。得益于与React保持一致API的特性,Nerv可以无缝兼容到React的相关生态,例如react-router,react-redux,以及使用React开发的组件,所以对于旧的React项目,可以无痛地将React替换成Nerv。
环境准备
Taro 仅提供一种开发方式:安装 Taro 命令行工具(Taro CLI)进行开发。
在终端输入命令 npm i -g @tarojs/cli 安装 Taro CLI。
Taro CLI 依赖于 Node.js 环境(>=8.0.0)。
框架
项目目录结构
编译配置
编译配置存放于项目根目录下 config 目录中,包含三个文件:
index.js: 通用配置
dev.js : 开发环境配置
prod.js : 生产环境配置
入口文件
每一个 Taro 应用都需要一个入口组件用来注册应用,入口文件默认是 src/app.js。
页面文件
页面组件是每一项路由将会渲染的页面,Taro 的页面默认放在 src/pages 中,每一个 Taro 项目至少有一个页面组件。页面创建好后如果需要渲染展示,需要在项目入口文件 app.config.js 的 pages 数组中进行指定。
文件配置
全局配置:可以通过 app.config.js 的文件进行全局配置, 配置页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。
一个简单的全局配置如下:
// app.config.js``export default {` `pages: [` `'pages/index/index',` `'pages/list/index'` `],` `window: {` `backgroundTextStyle: 'light',` `navigationBarBackgroundColor: '#fff',` `}``}`
未指定
entryPagePath
时,数组的第一项代表初始页面。
新增/减少页面,都需要对 pages 数组进行修改。
页面配置:每一个页面组件(例如 index.js)也会有一个页面配置(例如 index.config.js),可以在页面配置文件中设置页面的导航栏、背景颜色等参数。
一个最简单的页面配置如下:
// ./pages/index/index.jsx``export default {` `navigationBarTitleText: '首页'``}`
配置规范基于微信小程序的全局配置进行制定,所有平台进行统一。在配置文件中,Taro 并不关心框架的区别,Taro CLI 会直接在编译时在 Node.js 环境直接执行全局配置的代码,并把 export default 导出的对象序列化为一个 JSON 文件。
因此,我们必须保证配置文件是在 Node.js 环境中是可以执行的,不能使用一些在 H5 环境或小程序环境才能运行的包或者代码,否则编译将会失败。
项目配置
为了能够适配到各个小程序平台,满足不同小程序平台配置文件不同的情况, Taro 支持为各个小程序平台添加不同的项目配置文件。
通过 Taro 模板创建的项目都会默认拥有 project.config.json 文件,若要兼容到其他小程序平台,按如下对应规则来增加相应平台的配置文件,其配置与各自小程序平台要求的一致。
小程序平台 | 配置文件 | 说明 |
---|---|---|
微信小程序 | project.config.json | |
百度小程序 | project.swan.json | |
头条小程序 | project.tt.json | |
快应用 | project.quickapp.json | 配置文件中请勿配置 router 与 display ,这两个配置将由 Taro 生成 |
QQ小程序 | project.qq.json |
组件生命周期与事件处理函数
以Hooks为例:
css 工具
在 Taro 中,我们可以自由地使用 CSS 预处理器和后处理器,使用的方法也非常简单,只要在编译配置添加相关的插件即可:
// config/index.js``const config = {` `designWidth: 750,` `sourceRoot: 'src',` `outputRoot: 'dist',` `plugins: [` `'@tarojs/plugin-sass', // 使用 Sass` `// '@tarojs/plugin-less', // 使用 Less` `// '@tarojs/plugin-stylus', // 使用 Stylus` `],` `defineConstants: {},` `mini: {},` `h5: {}``}``module.exports = function (merge) {` `if (process.env.NODE_ENV === 'development') {` `return merge({}, config, require('./dev'))` `}` `return merge({}, config, require('./prod'))``}`
除了 CSS 预处理器之外,Taro 还支持 CSS Modules 和 CSS-in-JS。通过 自定义编译 ,还可以支持更多 CSS 工具。
路由功能
在 Taro 中,路由功能是默认自带的,不需要开发者进行额外的路由配置。
入口组件和页面组件是通过配置文件来交互的,我们只需要在入口文件的 config 配置中指定好 pages,然后就可以在代码中通过 Taro 提供的 API 来跳转到目的页面,例如:
// 跳转到目的页面,打开新页面``Taro.navigateTo({` `url: '/pages/page/path/name'``})``// 跳转到目的页面,在当前页面打开``Taro.redirectTo({` `url: '/pages/page/path/name'``})`
尺寸单位
在 Taro 中, 尺寸单位建议使用px, %,Taro 默认会对所有单位进行转换。当转成微信小程序的时候,尺寸单位将默认转换以 rpx为单位,当转成 H5 时将默认转换以 rem 为单位。
如果你希望部分 px 单位不被转换成 rpx 或者 rem ,最简单的做法就是在 px 单位中增加一个大写字母,例如 Px 或者 PX 这样,则会被转换插件忽略。
Taro 默认以 750px 作为换算尺寸标准,如果设计稿不是以 750px 为标准,则需要在项目配置 config/index.js 中进行设置,例如设计稿尺寸是 640px,则需要修改项目配置 config/index.js 中的 designWidth 配置为 640:
const config = {` `designWidth: 640,``}`
目前 Taro 支持 750、 640 、 828 三种尺寸设计稿,他们的换算规则如下:
const DEVICE_RATIO = {` `'640': 2.34 / 2,` `'750': 1,` `'828': 1.81 / 2``}`
多端开发
由于不同的平台之间还是存在一些无法消除的差异,所以为了更好的实现跨平台开发,Taro 中提供了两种解决方案:
1. 内置环境变量:process.env.TARO_ENV
process.env.TARO_ENV 用于判断当前编译类型,目前有 weapp / swan / alipay / h5 / rn / tt / qq / quickapp 八个取值。通过这个变量来写对应一些不同环境下的代码,在编译时会将不属于当前编译类型的代码去掉,只保留当前编译类型下的代码。
render () {` `return (` `<View>` `{process.env.TARO_ENV === 'weapp' && <ScrollViewWeapp />}` `{process.env.TARO_ENV === 'h5' && <ScrollViewH5 />}` `</View>` `)``}`
缺点:虽然可以解决大部分跨端的问题,但是会让代码中充斥着逻辑判断,影响代码的可维护性,而且也让代码变得愈发丑陋。
2. 统一接口的多端文件
针对一项功能,如果多个端之间都有差异,开发者可以通过将文件修改成 原文件名.端类型 的命名形式实现多端文件。Taro 在编译时,会根据编译平台类型,将加载的文件变更为带有对应端类型文件名的文件,从而达到不同的端加载对应文件的目的。
使用要点
不同端的对应文件一定要对外暴露统一接口,统一调用方式,接受一致的参数
最好有一个平台无关的默认文件,这样在使用 ts 的时候也不会出现报错
引用文件的时候,只需要写默认文件名,不用带文件后缀
多端文件简单的例子:
1、多端组件
// 1. 定义多端组件``-test``--test.js // Test组件默认的形式,编译到微信小程序和H5之外的端``--test.h5.js // Test 组件的 H5 版本``--test.weapp.js // Test 组件的 微信小程序 版本``// 2. 引用组件``import Test from '../../components/test';``<Test argA={1} argA={2} />`
2、多端方法
// 1.定义多端方法``-utils``--set_title.js``--set_title.h5.js``--set_title.weapp.js``// 2. 使用方法``import setTitle from '../utils/set_title'``setTitle('页面标题')`
跨平台组件库
相对于我们熟悉的 div、span 元素而言,在 Taro 中我们要全部使用跨平台组件进行开发。
Taro 以 微信小程序组件库 为标准,结合 jsx 语法规范,定制了一套自己的组件库规范。基于这个原则,在小程序端,可以使用所有的小程序原生组件,在其他端,Taro提供了对应的组件库实现:
H5 端: @tarojs/components,需要引入的默认标准组件库
RN 端: @tarojs/components-rn
开发规范
首字母大写与驼峰式命名
组件的事件传递都要以 on 开头
组件种类
使用
在使用时,我们需要先从 Taro 标准组件库 @tarojs/components 引用组件,再进行使用。
import Taro, { Component } from '@tarojs/taro';``// 使用 <View />、 <Text /> 组件``import { View, Text } from '@tarojs/components';``export default class C extends Component {` `render () {` `return (` `<View className='c'>` `<Text>c component</Text>` `</View>` `)` `}``}`
Taro UI
Taro UI 是一款基于 Taro 框架开发的多端 UI 组件库。
特性
基于 Taro 开发 UI 组件
一套组件可以在 微信小程序,支付宝小程序,百度小程序,H5 多端适配运行(ReactNative 端暂不支持)
提供友好的 API,可灵活的使用组件
组件种类
使用
1. 引入组件样式
引入组件样式有三种方式:
全局引入(JS中): 在入口文件app.js中引入 taro-ui 所有的样式
import 'taro-ui/dist/style/index.scss' // 引入组件样式
全局引入(CSS中): 在 app.scss 样式文件中 import 组件样式并按照文档说明使用
@import "~taro-ui/dist/style/index.scss"; // 引入组件样式
按需引入: 在页面样式或全局样式中 import 需要的组件样式
@import "~taro-ui/dist/style/components/button.scss"; // 引入所需的组件样式
2. 引入所需组件
// index.js``import { AtButton } from 'taro-ui';`
一个使用AtButton的完整例子:
// src/pages/index/index.tsx``import Taro, { Component, Config } from '@tarojs/taro'``import { View } from '@tarojs/components'``import { AtButton } from 'taro-ui'``import './index.scss';``export default class Index extends Component {` `config: Config = {` `navigationBarTitleText: '首页'` `}` `render () {` `return (` `<View className='index'>` `<AtButton type='primary'>按钮文案</AtButton>` `</View>` `)` `}``}`
/* app.scss*/``@import "~taro-ui/dist/style/index.scss";`
自定义主题
Taro UI 目前只有一套默认的主题配色,为满足业务和品牌上多样化的视觉需求,UI 库支持一定程度的样式定制。(请确保微信基础库版本在 v2.2.3 以上)
目前支持三种自定义主题的方式,可以进行不同程度的样式自定义:
SCSS 变量覆盖
globalClass 全局样式类
配置 customStyle 属性(仅有部分组件支持,请查看组件文档,不建议使用)
SCSS 主题变量覆盖
Taro UI 的组件样式是使用 SCSS 编写的,如果你的项目中也使用了 SCSS,那么可以直接在项目中改变 Taro UI 的样式变量。
1. 覆写的变量,需要在引入 taro ui 默认样式之前定义,默认主题变量命名。
2. Slider, Switch 组件暂时不支持 SCSS 变量覆盖的方式自定义主题。
1、在app.scss文件写入以下内容:
// app.scss``$color-brand: #6190E8; /* 改变主题变量 */``@import "~taro-ui/dist/style/index.scss"; /* 引入 Taro UI 默认样式 */`
2、在app.js中引入以上的样式文件即可
// app.js
import './app.scss';
改变主题变量前后对比图:
全局样式类
全局样式类是微信小程序定义的一套用于修改组件内部样式的方案。如果希望组件外样式类能够影响组件内部,可以在组件构造器中的 options.addGlobalClass 字段设置为 true(Taro UI 的组件均开启了此特性)。
addGlobalClass 只对 Page 上的 class 起作用。换言之,如果在自定义的组件中使用 taro-ui,是无法在自定义组件内部通过 全局样式类 的方式去更改组件样式的。
当开放了全局样式类,存在外部样式无意间污染组件样式的风险。由于 Taro UI 的组件样式采用 BEM 的命名方式,从一定程度上避免了样式污染的问题。
/* page/index/index.js */``import Taro from '@tarojs/taro'``import { AtButton } from 'taro-ui'``import "./index.scss"``export default IndexPage extends Taro.Component { `` render () {` `return <AtButton className='my-button' />` `}``}``/**` `* page/index/index.scss 必须在 Page 上` `* .at-button 为组件内部类名,只需要写一样的类名去覆盖即可` `**/``.my-button .at-button {` `color: red;``}`
设计思想与编译原理
在 Taro 中先按照 Nerv语法编写一份源代码,然后通过编译工具将源代码编译成对应的代码。
编译工具采用的是编译原理的思想,所谓编译原理,就是一个对输入的源代码进行语法分析,语法树构建,随后对语法树进行转换操作再解析生成目标代码的过程。
Taro标准:抹平多端差异
基于编译原理,可以将 Taro 源码编译成不同端上可以运行的代码了,但是这对于实现多端开发还是远远不够。不同的平台都有自己的特性,每一个平台都不尽相同,这些差异主要体现在不同的组件标准与不同的 API 标准以及不同的运行机制上。
以小程序和 Web 端为例:
可以看出小程序和 Web 端上组件标准与 API 标准有很大差异,这些差异仅仅通过代码编译手段是无法抹平的,例如不能直接在编译时将小程序的
仅仅依靠代码编译,无法做到一致,同理,众多 API 也面临一样的情况。针对这样的情况,Taro 采用了定制一套运行时标准来抹平不同平台之间的差异。
这一套标准主要以三个部分组成,包括标准运行时框架、标准基础组件库、标准端能力 API,其中运行时框架和 API 对应 @taro/taro,组件库对应 @tarojs/components,通过在不同端实现这些标准,从而达到去差异化的目的。
taro build命令
taro build 命令是整个 taro 项目的灵魂和核心,主要负责 多端代码编译(h5,小程序,React Native等)。不同的平台,编译传参不同,编译规则不同。
// package.json
"scripts": {
// 微信小程序 weapp
"build:weapp": "taro build --type weapp",
// h5
"build:h5": "taro build --type h5",
// 支付宝小程序 alipay
"build:alipay": "taro build --type alipay",
// ....
},
编译工作流与抽象语法树(AST)
一般来说,将一种结构化语言的代码编译成另一种类似的结构化语言的代码包括以下几个步骤:
首先是 parse,将代码 解析(Parse)成 抽象语法树(Abstract Syntex Tree),然后对抽象语法树 AST 进行 遍历(traverse)和 替换(replace)(可以类比 DOM 树的操作),最后是 生成(generate),根据新的 AST 生成编译后的代码。
Babel模块
Babel 是一个通用的多功能的 JavaScript编译器,更确切地说是源码到源码的编译器,通常也叫做转换编译器(transpiler)。Taro 项目的代码编译部分就是基于 Babel 的以下模块实现:
babylon Babylon 是 Babel 的解析器。最初是 从Acorn项目fork出来的。Acorn非常快,易于使用,并且针对非标准特性(以及那些未来的标准特性) 设计了一个基于插件的架构。
babel-traverse Babel Traverse(遍历)模块维护了整棵树的状态,并且负责替换、移除和添加节点。
babel-types Babel Types模块是一个用于 AST 节点的 Lodash 式工具库, 它包含了构造、验证以及变换 AST 节点的方法。该工具库包含考虑周到的工具方法,对编写处理AST逻辑非常有用。
babel-generator Babel Generator模块是 Babel 的代码生成器,它读取AST并将其转换为代码和源码映射(sourcemaps)。
babel-template babel-template 是另一个虽然很小但却非常有用的模块。它能让你编写字符串形式且带有占位符的代码来代替手动编码, 尤其是生成的大规模 AST的时候。在计算机科学中,这种能力被称为准引用(quasiquotes)。