【Taro開發】四月芳菲,Taro觀賞指南
背景
最近接到多端開發,因為老項目使用的React,考慮到遷移成本,選擇了Taro,遷移成本相對較低,且上手較快。
Taro和uni-app
我做了一下調研,目前市面上優秀且成熟的開源框架有很多。其中,Taro和uni-app作為兩大“豪門”框架,優秀之處各有千秋,為我提供了更多的選擇項。
關於它們的對比可以參看下面這篇掘金好文:
Taro
綜合考量,尤其是前面提到的,遷移成本,我最後選擇了Taro。下面主要介紹Taro的使用以及遷移中的功能總結。
Taro的官方文檔內容很全面,基本的操作跟着官方文檔即可完成,官方文檔地址。
我的項目目前只有兩個端的業務場景,分別是微信小程序和H5,所以技術探索也主要針對這兩個端,文章也主要是這兩個端使用總結。
新建項目
CLI 工具安裝
```js
使用 npm 安裝 CLI
$ npm install -g @tarojs/cli
OR 使用 yarn 安裝 CLI
$ yarn global add @tarojs/cli
OR 安裝了 cnpm,使用 cnpm 安裝 CLI
$ cnpm install -g @tarojs/cli ```
項目初始化
使用命令創建模板項目
$ taro init myApp
npm 5.2+ 也可在不全局安裝的情況下使用 npx 創建模板項目
$ npx @tarojs/cli init myApp
安裝依賴
```
進入項目根目錄
$ cd myApp
使用 yarn 安裝依賴
$ yarn
OR 使用 cnpm 安裝依賴
$ cnpm install
OR 使用 npm 安裝依賴
$ npm install ```
安裝完成之後,文件結構已經生成如下圖:
編譯命令
``` // 微信小程序
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框架版
選擇框架
因為我平時使用React框架進行開發,所以遷移的時候也直接選擇了React框架。這個選擇是在項目初始化的時候選擇的,如下圖:
項目遷移
直接把文件拷貝過來,然後進行調整,主要調整的內容有以下幾個部分
UI框架的調整
原來的項目使用的是antd-mobile,遷移之後改成了@antmjs/vantui,部分組件名以及組件的用法略有不同。
比如下面的頁
- antd-mobile中的List組件在@antmjs/vantui是沒有的,所以需要重寫這部分代碼;
- Button組件兩個UI都有,但是裏面的屬性存在差異,針對這部分差異進行修改即可;
``` // import { List, Button } from 'antd-mobile'; import { Button } from '@antmjs/vantui';
// antd-mobile的List組件使用 const listContent = content => { return (
-
{content.list.map(item => {
return (
// @antmjs/vantui對List組件的改造
const listContent = content => {
return (
// antd-mobile的Button組件使用
// antd-mobile的Button組件使用 ```
頁面跳轉方法
原生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 (
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
因為我們的項目不是很大,所以並沒有實際應用這種方案,但是我再掘金上找了幾個不錯的參考文章:
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 };
缺點:需要自己寫邏輯,增加了額外的工作量。
優點:一次性處理了所有的頁面路由,不需要再次添加,且增加了404的重定向。
UI框架
我們配合Taro的UI框架最終選擇了有讚的@antmjs/vantui。這個UI框架提供的組件很豐富,常見的功能都覆蓋到了,不過它的api文檔寫的略微簡單,我後面可能寫一篇它的使用總結。
總結
萬事開頭難,但是世上無難事只怕有心人。
開源框架是推動技術發展的寶貴資源,有維護成本在的,所以遇到坑,可以轉換思維,自己做兼容處理,比如某些問題可以通過環境區分做處理,雖然繁瑣了一點,但是幫助解決了問題。
- await-to-js 源碼分析,體驗一把捕獲異常的優雅
- CSS偽類的第三集,原來偽類也可組CP
- 從:is()説起,開啟CSS偽類第二集
- 一組純CSS開發的聊天背景圖,幫助避免發錯消息的尷尬
- 「CSS特效」我的發呆專屬,反覆解鎖手機屏幕
- 「技術分享」以Antd為例,快速打通UI組件開發的任督二脈
- 「功能實現」我封裝了一個表單組件,感覺離財富自由又近了一步
- 「經驗總結」高效開發,老代碼可以這樣動
- 前端開發提效小技巧之業務功能篇
- 人生有忙忙碌碌,也有詩和遠方 | 2022年中總結
- 【端午節】新奇體驗,我用react實現網頁遊戲的全過程(包括規則設計)
- 【暑假記憶】消暑神器,我用CSS復刻了一個遊戲機
- 突圍?我願稱之為向上的攀登者
- 【孟夏之遇】望孟夏之短夜兮,螢星相伴
- 【技術學習】SVG-邊學邊做
- 【TS實踐】自己動手豐衣足食的TS項目開發
- 【碼上掘金】通過FileReader讀取Excel文件內容
- 【Taro開發】四月芳菲,Taro觀賞指南
- 【Node.js】青梅煮酒,聊聊zlib壓縮
- 【知識點】關於iframe跨域通信