【Taro Development】April Fangfei, Taro Watching Guide

background

Recently received multi-end development, because the React used by the old project, considering the migration cost, chose Taro, the migration cost is relatively low, and the start is faster.

Taro sum uni-app

I did some research and found that there are many excellent and mature open source frameworks on the market. Among them, Taro and uni-app, as the two major "giant" frameworks, each have their own merits and provide me with more options.

For a comparison of them, please refer to the following good Nuggets article:

Taro

Comprehensive consideration, especially the migration cost mentioned earlier, I finally chose Taro. The following mainly introduces the use of Taro and a summary of the functions in the migration.

Taro's official documents are very comprehensive, and the basic operations can be completed by following the official documents. The official document address .

My project currently has only two business scenarios, namely WeChat applet and H5, so the technical exploration is also mainly aimed at these two ends, and the article is mainly a summary of the use of these two ends.

New Project

CLI tools installation

# 使用 npm 安装 CLI
$ npm install -g @tarojs/cli

# OR 使用 yarn 安装 CLI
$ yarn global add @tarojs/cli

# OR 安装了 cnpm,使用 cnpm 安装 CLI
$ cnpm install -g @tarojs/cli
复制代码

Project initialization

Create template project using command

$ taro init myApp
复制代码

npm 5.2+ can also use npx to create template projects without installing globally

$ npx @tarojs/cli init myApp
复制代码

Install dependencies

# 进入项目根目录
$ cd myApp

# 使用 yarn 安装依赖
$ yarn

# OR 使用 cnpm 安装依赖
$ cnpm install

# OR 使用 npm 安装依赖
$ npm install
复制代码

After the installation is complete, the file structure has been generated as shown below:

compile command

// 微信小程序
# yarn
$ yarn dev:weapp
$ yarn build:weapp

# npm script
$ npm run dev:weapp
$ npm run build:weapp

// H5
# yarn
$ yarn dev:h5
$ yarn build:h5

# npm script
$ npm run dev:h5
$ npm run build:h5
复制代码

React framework version of project migration

choose frame

Because I usually use the React framework for development, I also directly chose the React framework when migrating. This selection is selected when the project is initialized, as shown below:

Project migration

Copy the file directly, and then make adjustments. The main adjustments are as follows:

UI framework tweaks

The original project used antd-mobile , which was changed to @antmjs/vantui after the migration . Some component names and usage of components are slightly different.

For example the following page

  • The List component in antd-mobile is not available in @antmjs/vantui, so this part of the code needs to be rewritten;
  • The Button component has both UIs, but there are differences in the properties inside, and you can modify this part of the difference;
// import { List, Button } from 'antd-mobile';
import { Button } from '@antmjs/vantui';

// antd-mobile的List组件使用
  const listContent = content => {
    return (
      <div className='content-list'>
        <List>
          {content.list.map(item => {
            return (
              <List.Item className={classnames({ 'list-item-baseline': item.btnName })} prefix={materiaIcon[item.type]} key={item.type} description={item.btnName ? btnConten(item) : null}>
                <div className={classnames({ required: item.required })}>{item.name}</div>
              </List.Item>
            );
          })}
        </List>
      </div>
    );
  };

// @antmjs/vantui对List组件的改造
const listContent = content => {
    return (
      <View className='content-list'>
        {content.list.map(item => {
          return (
            <View key={item.type} className='content-item'>
              <View className='flex'>
                <Icon color='#007af5' name={materiaIcon[item.type]} size='20px' />
                <View className={classnames('ml5', { required: item.required })}>{item.name}</View>
              </View>
              {item.btnName ? btnContent(item) : null}
            </View>
          );
        })}
      </View>
    );
  };

// antd-mobile的Button组件使用
<Button color='primary' block shape='rectangular'>
  咨询客服
</Button>

// antd-mobile的Button组件使用
<Button type="primary" block={true}>
  咨询客服
</Button>
复制代码

page jump method

原生H5的跳转使用的是History对象提供的push或者replace方法,在Taro里使用Taro提供的路由API,因为小程序中tabBar中的页面和其他页面的跳转方法不一样,这个区别Taro也做了区分,为此我写了一个公共方法做跳转的统一处理。

/**
   * 跳转处理
   * @param {string} path app.config.js中的完整地址 例如/pages/home/index
   */
  commonNavigateTo(path) {
    /** @name 底导航路由列表 */
    const switchList = ['/pages/home/index'];
    if (switchList.includes(path)) {
      Taro.switchTab({
        url: path,
      });
    } else {
      Taro.navigateTo({
        url: path,
      });
    }
  }
复制代码

HTML标签

Taro v3.3以前是不支持使用HTML标签的,使用的是Taro提供的View、Text等标签,这些在Taro的组件库中有详细介绍。

import React, { Component } from 'react'
import { View, Text } from '@tarojs/components'

export default class C extends Component {
  render () {
    return (
      <View className='c'>
        <Text>c component</Text>
      </View>
    )
  }
}
复制代码

Taro v3.3+ 开始支持使用HTML标签,需要进行插件配置。

配置插件

1.首先下载安装插件 @tarojs/plugin-html

yarn add @tarojs/plugin-html
复制代码

2.然后在项目配置中添加使用插件

// config/index.js
config = {
  // ...
  plugins: ['@tarojs/plugin-html']
}
复制代码

注:

  • 如果遇到不支持的标签可以使用Taro提供的组件,详见Taro组件库

项目迁移之原生小程序

后面有规划把原生小程序项目也使用Taro开发成多端,但是目前还没有实际应用,待我实际应用之后,再进行更新,我预测会遇到一些有趣的问题。

开发“指南针”

开发过程中难免会遇到各种问题,不过它也侧面成为了我的“试金石”,我把遇到的问题、解决方案,详细的列出来,供jym参考,有些解决方案可能不是最优,欢迎大佬提供更优的方案。

路由跳转路径问题

Taro提供的路由跳转方法基本和小程序一致,可以参看文档

这里着重强调一下跳转的url的完整性,即url要以右斜线开始,否则或被当做相对路由处理。

错误示例

Taro.navigateTo({
  url: 'pages/order/index',
});
复制代码

报错如下

errMsg: "navigateTo:fail page "pages/order/orderStatement/pages/order/index" is not found"

正确示例

Taro.navigateTo({
  url: '/pages/order/index',
});
复制代码

小程序文件过大的处理方法

1.根据提示开启压缩

Tips: 预览模式生成的文件较大,设置 NODE_ENV 为 production 可以开启压缩。
Example:
$ NODE_ENV=production taro build --type weapp --watch
复制代码

2.分包

分包限制如下,官方文档

  • 整个小程序所有分包大小不超过 20M
  • 单个分包/主包大小不能超过 2M

因为我们的项目不是很大,所以并没有实际应用这种方案,但是我再掘金上找了几个不错的参考文章:

小程序分包(Taro分包案例)

京东购物小程序 | Taro3 项目分包实践

3.vendors.js过大的原因

vendors.js文件中包含了node_modules 除 Taro 外的公共依赖,可能会因为某些原因导致它体积过大。

下面主要列一下我的项目中导致vendors.js文件过大的原因

3.1 引入了crypto-js

这个第三方加密库,会导致一些意外的内容被打包进去(具体是什么官方也没有说的特别明白,可能是node的一些依赖之类的),解决方案就是降低crypto-js的版本或者直接把crypto-js-min放进本地(本地83KB)。

Taro.request在H5端不能自定义header的解决方案

因为我的项目某些特殊业务逻辑,所以必须添加自定义header,但是H5端Taro.request不支持自定义header(小程序端支持),所以根据不同端区分request的引入。

/**
 * @description 异步请求分发 H5和小程序使用的不一样
 */
import $ from './request-weapp';
import $2 from './request-h5';
export function requestFunc() {
  if (process.env.TARO_ENV === 'weapp') {
    return $;
  } else {
    return $2;
  }
}
复制代码

老项目迁移时H5端自定义路由

因为老项目有一些已经对外的入口,比如外推链接、第三方入口等,所以迁移的时候要进行兼容处理。

1.处理前的页面路由

处理前的页面路由如下,Taro框架自动生成的,显然和老项目的不一致

https://{{domain}}/pages/index/index(browser 模式)

2.自定义页面路由方案1

方案1 是使用Taro提供的方式,配置h5.router.customRoutes

config/index.js

module.exports = {
  // ...
  h5: {
    // ...
    router: {
      customRoutes: {
        // "页面路径": "自定义路由"
        '/pages/index/index': '/index',
        '/pages/detail/index': ['/detail'] // 可以通过数组为页面配置多个自定义路由
      }
    }
  }
}
复制代码

优点:不用做过多的逻辑。

缺点:1)当需要配置的页面多的时候容易漏;2)新增页面如果忘记补充,可能会导致跳转找不到页面。

3.自定义页面路由方案2

自己编写自定义页面路由的代码逻辑

app.js

import resetRouter from '@utils/resetRouter';

// 挂载生命周期时,h5端引入路由重定向的处理方法
componentDidMount() {
    // =>true:只有H5才处理路由
    if (process.env.TARO_ENV === 'h5') {
      resetRouter.resetRouter();
    }
  }
复制代码

utils/resetRouter.js

/**
 * @description 路由拦截处理 页面404重定向、页面非Taro最终的H5路由重定向等
 */
import Taro, { Current } from '@tarojs/taro';
/**
 * 获取小程序tabBar的pagePath数组对象
 * @param {Object} taroAppConfigInit 项目配置项
 * @return {Array} 最终得到的pagePath数组
 */
const getTabBarPageList = taroAppConfigInit => {
  const tabBarInit = taroAppConfigInit.tabBar ? taroAppConfigInit.tabBar : {};
  const tabBarList = tabBarInit.list ? tabBarInit.list : [];
  const tabBarPageList = [];
  if (tabBarList.length !== 0) {
    tabBarList.forEach(item => {
      tabBarPageList.push('/' + item.pagePath);
    });
  }
  return tabBarPageList;
};
/**
 * 获取全部路由的数组对象
 * @param {Object} taroAppConfigInit 项目配置项
 * @return {Array} 最终得到的数组数组
 */
const getAllPagesList = taroAppConfigInit => {
  const allPagesListInit = taroAppConfigInit.pages ? taroAppConfigInit.pages : [];
  let allPagesList = [];
  allPagesListInit.forEach(item => {
    allPagesList.push('/' + item);
  });
  return allPagesList;
};
/**
 * 获取页面是否是404的布尔值
 * @param {Array} allPagesList 全部路由数组
 * @param {string} pathname 当前页面路由
 * @return {boolean} 最终得到的布尔值
 */
const getNoFoundFlag = (allPagesList, pathname) => {
  let flag = true;
  if (allPagesList.includes(pathname)) {
    flag = false;
  }
  return flag;
};
/**
 * 页面路由处理 如果不包含pages的重组成/pages/pathname/index的格式
 * @param {string} pathname 当前页面路由
 * @return {boolean} 重组后的路由
 */
const resetPathname = pathname => {
  let pathnameInit = '';
  if (pathname.indexOf('pages') === -1) {
    pathnameInit = '/pages' + pathname + '/index';
  } else {
    pathnameInit = pathname;
  }
  return pathnameInit;
};
/**
 * 跳转处理 跳转到tabBar页面使用switchTab,其他使用navigateTo
 * @param {string} pathname 当前页面路由
 * @param {string} search 当前页面路由参数
 */
const switchTabOrnavigateTo = (pathname, search) => {
  // 隐藏配置window.__taroAppConfig(包含app.config.js中所有内容)
  const taroAppConfigInit = Current.app.config ? Current.app.config : {};
  const allPagesList = getAllPagesList(taroAppConfigInit);
  const tabBarPageList = getTabBarPageList(taroAppConfigInit);
  const pathnameInit = resetPathname(pathname);
  console.log(pathnameInit, 'pathnameInit');
  //=>true: 如果路由类型是tabBar
  if (tabBarPageList.includes(pathnameInit)) {
    return Taro.switchTab({
      url: pathnameInit,
    });
  } else {
    const noFoundFlag = getNoFoundFlag(allPagesList, pathnameInit);
    const url = noFoundFlag ? '/pages/dispatch/nofound/index' : pathnameInit + search;
    return Taro.navigateTo({
      url: url,
    });
  }
};
/**
 * 路由跳转拦截处理
 */
const resetRouter = () => {
  // H5先从location获取路由getCurrentInstance().page值为nullTaro还没有修复
  let { pathname, search } = window.location;
  switchTabOrnavigateTo(pathname, search);
};
export default { resetRouter };
复制代码

Disadvantages: You need to write your own logic, which adds extra workload.

Advantages: All page routes are processed at one time, no need to add again, and 404 redirects are added.

UI stile

We cooperated with Taro's UI framework and finally chose the awesome @antmjs/vantui. The components provided by this UI framework are very rich, and the common functions are covered, but its api documentation is slightly simple, and I may write a summary of its use later.

Summarize

Everything is difficult at the beginning, but there is nothing difficult in the world, only those who have a heart.

Open source frameworks are valuable resources to promote technological development, and there are maintenance costs. Therefore, when encountering pitfalls, you can change your thinking and do compatible processing yourself. For example, some problems can be handled by distinguishing the environment. Although it is a bit cumbersome, it helps to solve the problem. question.

Guess you like

Origin juejin.im/post/7084126264679727140