diff --git a/docs/config-detail.md b/docs/config-detail.md index 374f770e8690..3676cecaad8d 100644 --- a/docs/config-detail.md +++ b/docs/config-detail.md @@ -35,7 +35,7 @@ title: 编译配置详情 配置方式可参考 [Webpack DefinePlugin](https://webpack.js.org/plugins/define-plugin/),例如: -```js +```js title="/config/index.js" module.exports = { // ... defineConstants: { @@ -110,7 +110,7 @@ import projectConfig from '@/project' **config/dev.js**: -```jsx +```jsx title="/config/dev.js" module.exports = { // ... env: { @@ -121,7 +121,7 @@ module.exports = { **config/prod.js**: -```jsx +```jsx title="config/prod.js" module.exports = { // ... env: { diff --git a/docs/config.md b/docs/config.md index 33b769ecd449..b29c7b033e60 100644 --- a/docs/config.md +++ b/docs/config.md @@ -10,7 +10,7 @@ title: 编译配置 ## index.js —— 通用配置 -```js +```js title="/config/index.js" const config = { // 项目名称 projectName: 'Awesome Next', diff --git a/docs/convert-to-react.md b/docs/convert-to-react.md new file mode 100644 index 000000000000..f09cf129acb2 --- /dev/null +++ b/docs/convert-to-react.md @@ -0,0 +1,72 @@ +--- +title: 转换成 React +--- + +## 二次开发 + +原生小程序代码: + +```jsx +Page({ + data: { + text: 'Hello World' + } +}) + + + {{ text }} + +``` + +转换后: + +```javascript +import { Block, View } from '@tarojs/components' +import React from 'react' +import Taro from '@tarojs/taro' +import withWeapp from '@tarojs/with-weapp' +import Title from '../../components/title/index' +import './index.scss' + +@withWeapp({ + data: { + text: 'Hello World' + } +}) +class _C extends React.Component { + render() { + const { text } = this.data + return {text} + } +} + +export default _C +``` + +它看起来就像普通的 Taro 组件,最重要的区别就在于 `@withWeapp()` 这个装饰器,你可以将它理解为转换代码的运行时,`@withWeapp()` 会增加一些原来 Taro 没有方法和属性,例如: + +### `this.setData` + +转换后的 `this.setData` 的 API 相当于小程序的 `this.setData` 的 polyfill,他和 `this.setState` 最大的区别就在于,`this.setData` 之后 `data` 的数据是同步更新,而渲染是异步更新,而 `setState` 两者都是异步的。 + +### `this.data` 和 `this.properties` + +`this.data` 和 `this.properties` 相当于 Taro 的 `this.state` 和 `this.props` 的 alias,当它们的数据更新时,对应的 `state` 和 `props` 也会同步更新。 + +### 生命周期 + +Taro 会将原生小程序的生命周期转换为 Taro 的生命周期,完整对应关系如下: + +|小程序生命周期|Taro 生命周期| +| :-- | :-- | +| onShow | componentDidShow | +| onHide | componentDidHide | +| App.onLaunch | onLaunch | +| Page.onLoad | onLoad | +| Page.onReady | onReady | +| Page.onUnload | componentWillUnmount | +| Component.created | componentWillMount | +| Component.attached | componentDidMount | +| Component.ready | Page.onReady | +| Component.detached | componentWillUnmount | + diff --git a/docs/css-in-js.md b/docs/css-in-js.md index 68755d112416..00a2edb8c26b 100644 --- a/docs/css-in-js.md +++ b/docs/css-in-js.md @@ -16,7 +16,7 @@ $ npm i linaria 其次配置项目根目录的 `babel.config.js`: -```js +```js title="babel.config.js" module.exports = { presets: [ ['taro', { @@ -30,7 +30,7 @@ module.exports = { 之后配置 `config/index.js` -```js +```js title="config/index.js" const config = { mini: { webpackChain(chain, webpack) { @@ -49,7 +49,7 @@ const config = { 最后在项目根目录新建 `linaria.config.js` -```js +```js title="linaria.config.js" // linaria 配置详见 https://github.com/callstack/linaria/blob/master/docs/CONFIGURATION.md#options module.exports = { rules: [ diff --git a/docs/css-modules.md b/docs/css-modules.md index 5768e96f0b51..bbee1769788a 100644 --- a/docs/css-modules.md +++ b/docs/css-modules.md @@ -8,7 +8,7 @@ Taro 中内置了 [CSS Modules](https://github.com/css-modules/css-modules) 的 小程序端开启 -```js +```js title="config/index.js" weapp: { module: { postcss: { @@ -27,7 +27,7 @@ weapp: { H5 端开启 -```js +```js title="config/index.js" h5: { module: { postcss: { diff --git a/docs/debug-config.md b/docs/debug-config.md index 603893a8a3d5..b37e194fd3e5 100644 --- a/docs/debug-config.md +++ b/docs/debug-config.md @@ -43,7 +43,7 @@ yarn global add rollup launch.json 有以下预设配置: -```json +```json title="launch.json" { // ... "configurations": [ @@ -83,7 +83,7 @@ launch.json 有以下预设配置: 可以这样配置 launch.json: -```json +```json title="launch.json" { // ... "configurations": [ @@ -108,7 +108,7 @@ launch.json 有以下预设配置: 可以这样配置 launch.json: -```json +```json title="launch.json" { // ... "configurations": [ diff --git a/docs/envs-debug.md b/docs/envs-debug.md index 6d613d3a7286..f882f09b1b7b 100644 --- a/docs/envs-debug.md +++ b/docs/envs-debug.md @@ -3,7 +3,8 @@ title: 多端同步调试 --- 从 1.3.5 版本开始,可以在 dist 目录下创建一个与编译的目标平台名同名的目录,并将结果放在这个目录下,例如编译到微信小程序,最终结果是在 dist/weapp 目录下,这样做的好处是,各个平台使用独立的目录互不影响,从而达到多端同步调试的目的,在 `config/index.js` 配置如下: -``` + +```js title="/config/index.js" outputRoot: `dist/${process.env.TARO_ENV}` ``` diff --git a/docs/envs.md b/docs/envs.md index 2cf44bb91071..6dd8e972507c 100644 --- a/docs/envs.md +++ b/docs/envs.md @@ -81,7 +81,7 @@ import Test from '../../components/test' 增加 `set_title.h5.js`,代码如下 -```js +```js title="set_title.h5.js" export default function setTitle (title) { document.title = title } @@ -89,7 +89,7 @@ export default function setTitle (title) { 增加 `set_title.weapp.js`,代码如下 -```js +```js title="set_title.weapp.js" import Taro from '@tarojs/taro' export default function setTitle (title) { Taro.setNavigationBarTitle({ @@ -145,7 +145,7 @@ Taro 3 里的多端文件由 [MultiPlatformPlugin](https://github.com/NervJS/tar 假如我们有一个 npm 包名叫 @taro-mobile,需要解析里面的多端文件,可以在 taro 的配置文件中这样修改 MultiPlatformPlugin 的配置: -```js +```js title="/config/index.js" // mini 也可改为 h5,分别对应小程序与 h5 端配置 mini: { webpackChain (chain) { diff --git a/docs/mini-third-party.md b/docs/mini-third-party.md index 2e7cda740928..bff39f906793 100644 --- a/docs/mini-third-party.md +++ b/docs/mini-third-party.md @@ -18,8 +18,7 @@ Taro 支持使用小程序的第三方组件和插件,使用方式也异常的 > 注意:Taro3 中没有自定义组件,组件是没有配置文件的。usingComponents 必须配置在“页面”的配置文件中。 -```js -// page.config.js +```js {2} title="page.config.js" export default { usingComponents: { // 定义需要引入的第三方组件 @@ -32,8 +31,7 @@ export default { 2. JSX 中引用 -```jsx -// page.js +```jsx {14} title="page.js" import React, { Component } from 'react' import { View } from '@tarojs/components' @@ -83,8 +81,7 @@ page.selectComponent('#mychart-dom-area') 使用插件前,使用者要在 `app.confg.js` 的配置中声明需要使用的插件,例如 -```jsx -// app.config.js +```jsx title="app.config.js" export default { plugins: { myPlugin: { diff --git a/docs/miniprogram-plugin.md b/docs/miniprogram-plugin.md index d6b42783f42d..485c1164bca5 100644 --- a/docs/miniprogram-plugin.md +++ b/docs/miniprogram-plugin.md @@ -50,7 +50,7 @@ taro build --plugin weapp --watch plugin.json 的 **pages** 字段加入页面插件路径: -```json +```json title="plugin.json" { "pages": { "list": "pages/list/list" @@ -60,7 +60,7 @@ plugin.json 的 **pages** 字段加入页面插件路径: 页面使用路径: **plugin://[app.js 中注册的插件名]/[plugin.json 中注册的页面名]** 进行跳转。 -```jsx +```jsx {1} Go to pages/list! @@ -70,7 +70,7 @@ plugin.json 的 **pages** 字段加入页面插件路径: plugin.json 的 **publicComponents** 字段加入组件插件路径: -```json +```json title="plugin.json" { "publicComponents": { "avatar": "components/avatar/avatar" @@ -80,7 +80,7 @@ plugin.json 的 **publicComponents** 字段加入组件插件路径: 在页面配置 config.usingComponents 中配置好插件名和插件路径(**plugin://[app.js 中注册的插件名]/[plugin.json 中注册的组件名]**): -```jsx +```jsx {4} export default class Index extends Component { config = { usingComponents: { @@ -114,7 +114,7 @@ const extraProps = { plugin.json 的 **main** 字段加入接口插件路径: -```json +```json title="plugin.json" { "main": "index.js" } diff --git a/docs/nerv.md b/docs/nerv.md index 0536b3c0040b..f73607c863bb 100644 --- a/docs/nerv.md +++ b/docs/nerv.md @@ -8,7 +8,7 @@ title: Nerv 在使用第三方 React 库时,需要在[配置文件](config-detail.md#miniwebpackchain) `webpack.resolve.alias`,把 `react` 和 `react-dom` 映射到 `nervjs`: -```js +```js title="/config/index.js" { webpackChain (chain, webpack) { chain.merge({ diff --git a/docs/platform-plugin-base.md b/docs/platform-plugin-base.md index 906b319fc034..a797b2e499ca 100644 --- a/docs/platform-plugin-base.md +++ b/docs/platform-plugin-base.md @@ -6,8 +6,7 @@ title: TaroPlatformBase 例如我们创建一个微信小程序平台: -```js -// program.ts +```js title="program.ts" import { TaroPlatformBase } from '@tarojs/service' export default class Weapp extends TaroPlatformBase { // ... @@ -184,8 +183,7 @@ runner(options) ### 1. 继承基类 -```js -// program.ts +```js title="program.ts" import { TaroPlatformBase } from '@tarojs/service' class Weapp extends TaroPlatformBase { @@ -234,8 +232,7 @@ class Weapp extends TaroPlatformBase { 规范: -```js -//components.ts +```js title="components.ts" import { singleQuote } from '@tarojs/shared' export const components = { @@ -319,8 +316,7 @@ internalComponent = { 除了借助 `template.mergeComponents` 进行合并,我们也可以直接修改 `template.internalComponents`。 -```js -// program.ts +```js title="program.ts" class Weapp extends TaroPlatformBase { modifyComponents () { // 删除 Slider 组件里的一些属性 @@ -376,8 +372,7 @@ class Weapp extends TaroPlatformBase { 我们创建的平台类需要编写一个对外的接口,在其中对编译流程进行设计,最终目标是调用 `@tarojs/mini-runner` 驱动 **Webpack** 开启编译。 -```js -// program.ts +```js title="program.ts" class Weapp extends TaroPlatformBase { // ... async start () { diff --git a/docs/platform-plugin-how.md b/docs/platform-plugin-how.md index 988a719cdc65..12f0ed19ac63 100644 --- a/docs/platform-plugin-how.md +++ b/docs/platform-plugin-how.md @@ -41,8 +41,7 @@ title: 编写端平台插件 首先我们需要编写一个 Taro 插件来注册我们的编译平台,如: -```js -// index.ts +```js title="index.ts" export default (ctx) => { ctx.registerPlatform({ name: 'weapp', @@ -99,8 +98,7 @@ Taro 小程序相关配置默认放在 `mini` 字段下,因此一般情况配 然后在插件入口函数中调用上述自定义平台类的编译接口: -```js -// index.ts +```js title="index.ts" import Weapp from './program' export default (ctx) => { @@ -221,8 +219,7 @@ export function initNativeApi (taro) { 当前扩展的小程序平台如果需要额外新增 API,建议使用一个 `apis-list.ts` 文件维护: -```js -// apis-list.ts +```js title="apis-list.ts" // 微信小程序部分扩展 API export const _onAndSyncApis = new Set([ 'getAccountInfoSync' @@ -279,8 +276,7 @@ function processApis (taro) { 注意,Taro 相关的包需要配置 `external`,以免重复打包: -```js -// rollup.config.js +```js title="rollup.config.js" { external: ['@tarojs/shared', '@tarojs/service'] } @@ -292,8 +288,7 @@ Taro 核心库维护的类型可能没有包括当前插件新增的组件和 AP 创建一个类型定义文件: -```ts -// types/shims-iot.d.ts +```ts title="types/shims-iot.d.ts" // 为支付宝 IOT 小程序拓展新增的 API 和组件定义 import { ComponentType } from 'react' import Taro from '@tarojs/taro' @@ -319,7 +314,6 @@ declare module '@tarojs/components' { 开发者在类型定义文件中引入此文件即可: -```ts -// global.d.ts +```ts title="global.d.ts" /// ``` diff --git a/docs/plugin.md b/docs/plugin.md index 04788fe373e2..ea8bd409a9e2 100644 --- a/docs/plugin.md +++ b/docs/plugin.md @@ -20,7 +20,7 @@ Taro 提供了一些官方插件 `plugins` 字段取值为一个数组,配置方式如下: -```js +```js title="/config/index.js" const config = { plugins: [ // 引入 npm 安装的插件 @@ -46,7 +46,7 @@ const config = { 配置[编译配置](./config-detail.md)中的 `presets` 字段,如下。 -```js +```js title="/config/index.js" const config = { presets: [ // 引入 npm 安装的插件集 diff --git a/docs/prerender.md b/docs/prerender.md index 4521678b86d2..ed62c1854835 100644 --- a/docs/prerender.md +++ b/docs/prerender.md @@ -18,8 +18,7 @@ Taro Next 在一个页面加载时需要经历以下步骤: 使用 Prerender 非常简单,你可以找到项目根目录下的 `config` 文件夹,根据你的项目情况更改 `index.js`/`dev.js`/`prod.js` 三者中的任意一个[项目配置](./config.md),在编译时 Taro CLI 会根据你的配置自动启动 prerender: -```js -// /project/config/prod.js +```js title="/config/index.js 或 /config/dev.js 或 /config/prod.js " const config = { ... mini: { diff --git a/docs/redux.md b/docs/redux.md index 5ded4e3d36a9..d1bf2f9f482e 100644 --- a/docs/redux.md +++ b/docs/redux.md @@ -14,8 +14,7 @@ $ npm install --save redux react-redux redux-thunk redux-logger 随后可以在项目 `src` 目录下新增一个 `store` 目录,在目录下增加 `index.js` 文件用来配置 `store`,按自己喜好设置 `redux` 的中间件,例如下面例子中使用 `redux-thunk` 和 `redux-logger` 这两个中间件 -```jsx -// src/store/index.js +```jsx title="src/store/index.js" import { createStore, applyMiddleware, compose } from 'redux' import thunkMiddleware from 'redux-thunk' import rootReducer from '../reducers' @@ -48,8 +47,7 @@ export default function configStore () { 接下来在项目入口文件 `app.js` 中使用 `redux` 中提供的 `Provider` 组件将前面写好的 `store` 接入应用中 -```jsx -// src/app.js +```jsx title="src/app.js" import React, { Component } from 'react' import { Provider } from 'react-redux' @@ -93,16 +91,14 @@ export default App 新增 `action type` -```jsx -// src/constants/counter.js +```jsx title="src/constants/counter.js" export const ADD = 'ADD' export const MINUS = 'MINUS' ``` 新增 `reducer` 处理 -```jsx -// src/reducers/counter.js +```jsx title="src/reducers/counter.js" import { ADD, MINUS } from '../constants/counter' const INITIAL_STATE = { @@ -127,8 +123,7 @@ export default function counter (state = INITIAL_STATE, action) { } ``` -```jsx -// src/reducers/index.js +```jsx title="src/reducers/index.js" import { combineReducers } from 'redux' import counter from './counter' @@ -140,8 +135,7 @@ export default combineReducers({ 新增 `action` 处理 -```jsx -// src/actions/counter.js +```jsx title="src/actions/counter.js" import { ADD, MINUS @@ -171,8 +165,7 @@ export function asyncAdd () { 最后,我们可以在页面(或者组件)中进行使用,我们将通过 `redux` 提供的 `connect` 方法将 `redux` 与我们的页面进行连接 -```jsx -// src/pages/index/index.js +```jsx title="src/pages/index/index.js" import React, { Component } from 'react' import { connect } from 'react-redux' import { View, Button, Text } from '@tarojs/components' diff --git a/docs/size.md b/docs/size.md index 79d97d12d89a..a95afcfe6b00 100644 --- a/docs/size.md +++ b/docs/size.md @@ -8,7 +8,7 @@ title: 设计稿及尺寸单位 结合过往的开发经验,Taro 默认以 `750px` 作为换算尺寸标准,如果设计稿不是以 `750px` 为标准,则需要在项目配置 `config/index.js` 中进行设置,例如设计稿尺寸是 `640px`,则需要修改项目配置 `config/index.js` 中的 `designWidth` 配置为 `640`: -```jsx +```jsx title="/config/index.js" const config = { projectName: 'myProject', date: '2018-4-18', @@ -108,7 +108,7 @@ REM 单位允许的小数位。 配置规则对应到 `config/index.js` ,例如: -```js +```js {9-14,20-25} title="/config/index.js" { h5: { publicPath: '/', diff --git a/docs/static-reference.md b/docs/static-reference.md index 0884d311cabc..aa9533ec9246 100644 --- a/docs/static-reference.md +++ b/docs/static-reference.md @@ -70,7 +70,7 @@ Taro 默认会对 `1kb` 大小以下的资源进行转换,如果需要修改 具体配置如下 -```javascript +```js title="/config/index.js" // 小程序端样式引用本地资源内联 url: { enable: true, diff --git a/docs/taroize-troubleshooting.md b/docs/taroize-troubleshooting.md new file mode 100644 index 000000000000..6aa3be0c6c3c --- /dev/null +++ b/docs/taroize-troubleshooting.md @@ -0,0 +1,291 @@ +--- +title: Troubleshooting +--- + +## 不支持的小程序特性 + +### 入口 App 对象 + +|属性|说明| +|:--|:--| +|onError|| +|onPageNotFound|| +|onUnhandledRejection|| +|onThemeChange|| + +### 页面 Page 对象 + +|属性|说明| +|:--|:--| +|selectComponent|建议使用 React ref 重构| +|selectAllComponents|建议使用 React ref 重构| +|selectOwnerComponent|建议使用 React ref 重构| +|groupSetData|| + +### 自定义组件 + +|属性|说明| +|:--|:--| +|moved|| +|externalClasses|Taro 3 不存在自定义组件,建议规范类名或使用 CSS Module 代替| +|relations|| +|options|| +|definitionFilter|| + +### wxml 语法 + +|属性|说明| +|:--|:--| +|循环|[部分语法有限制]| +|事件|[部分语法有限制](./taroize-troubleshooting#2-事件)| +|引用|[部分语法有限制](./taroize-troubleshooting#16-include-里不支持使用-template)| +|wxs|[部分语法有限制](./taroize-troubleshooting#15-不支持-wxs-里的-getregexp-方法)| + +## 关键问题 + +### 1. 没有处理基类 + +原生开发中,常常会把 App、Page、Component 构造对象的公共逻辑整合到基类中。 + +如 **Vant-weapp** 中: + +```js +// 组件 +VantComponent({ + data: {} +}) +// 基类 +function VantComponent(vantOptions = {}) { + // 整合组件独有配置 vantOptions 和公共配置到最终的配置对象 options 中 + // ... + + // 调用小程序的 Component 方法构造自定义组件 + Component(options); +} +``` + +Taro 在编译时只能识别出入口、页面、组件文件中存在的 `App()`、`Page()`、`Component()` 调用,使用基类对配置封装后就不存在这些调用。因此编译后的 `withWeapp` 获得的参数是 `{}`。 + +```js +VantComponent({ + data: {} +}) +// withWeapp 中应该传入小程序配置对象 +@withWeapp({}) +class _C extends React.Component {} +``` + +因此我们需要手动修改: + +```js +// 基类 +function VantComponent(vantOptions = {}) { + // 整合组件独有配置 vantOptions 和公共配置到最终的配置对象 options 中 + // ... + + // 调用小程序的 Component 方法构造自定义组件 + // Component(options); + + // 1. 基类直接返回整合后的 options + return options +} +``` + + +```js +// 2. 把基类创建的配置传入 withWeapp: +const options = VantComponent({ + data: {} +}) +@withWeapp(options) +class _C extends React.Component {} +``` + +### 2. 样式作用域 + +微信小程序中的自定义组件,转换后会生成一个 Taro 中的 React/Vue 组件。 + +但是 Taro 中使用 React/Vue 开发的组件,编译到小程序平台时,并不会生成对应的小程序自定义组件。 + +**因此微信小程序自定义组件的样式隔离特性,在转换为 Taro 后就会丢失。** + +#### 解决办法: + +1. 修改冲突的选择器。 +2. 使用 CSS Modules 进行改写。 + +## 常见问题 + +### 1. wxml 语法转换问题 + +把 `wxml` 转换为 `JSX` 是通过操作 `AST` 实现的,有一些写法可能没有考虑到,或难以适配,从而导致报错。 + +以下是一些已知问题,需要手动修复: + +#### 1.1 组件同时使用 `wx:for` 和 `wx:if` 语句时转换错误 + +当组件上同时使用了 `wx:for` 和 `wx:if` 语句,并且使用了当前**循环元素 item** 或**循环下标 index** 做判断条件时,转换后会报错。 + +例如: + +```jsx +// 转换前(注意判断条件使用了循环下标 index): + + objectArray item: {{item.id}} + +``` + +```jsx +// 转换后: +{index % 2 !== 0 && ( + + {objectArray.map((item, index) => { + return ( + + {'objectArray item: ' + item.id} + + ) + })} + +)} +``` + +上例可见,对于条件语句的转换,目前的处理会把条件提取到组件外部。但是如果条件使用了 `item` 或 `index` 时,这样的提取逻辑会导致**变量未定义**的报错。 + +暂时可以通过手动修复解决: + +方法一,修改**编译前**的代码,把循环和条件语句拆开到两个组件中: + +```jsx + + + objectArray item: {{item.id}} + + +``` + +方法二,修改**编译后**的代码,把条件判断放进循环体中: + +```jsx + + {objectArray.map((item, index) => { + return ( + + {index % 2 !== 0 && {'objectArray item: ' + item.id}} + + ) + })} + +``` + +#### 1.2 根元素不能含有 `hidden` 属性。 + +#### 1.3 编译时报错:SyntaxError: Unexpected token + +尖括号 “<” 右侧需要留一个空格,[#4243](https://github.com/NervJS/taro/issues/4243) + +##### 解决办法: + +检查是否存在以下写法: + +```jsx +{{a <4? "1": "2"}} +``` + +改为: + +```jsx +{{a < 4? "1": "2"}} +``` + +#### 1.4 运行时报错:ReferenceError: item is not defined + +查看编译后的 JSX,是否因为漏了从 `this.data` 中取出变量,如: + +``` +// 下面的代码没有引用 item +const { a, b, c } = this.data +``` + +##### 解决办法: + +`this.data` 中的变量名,不要和用于指定数组当前下标的变量名,默认值为 `item`,或由 `wx:for-index` 具体指定的变量名相同。 + + +#### 1.5 不支持 WXS 里的 GetRegExp 方法 + +使用 `RegExp` 构造正则表达式。 + +#### 1.6 `` 里不支持使用 `