Taro踩坑實踐

快狗叫車前端團隊發表於2020-02-20

背景

快狗合夥人技術部,在去年使用 Taro開發了兩個微信小程式,現在均已上線。開發過程中也遇到了一些大大小小的問題,下面列出幾個比較典型的,供在使用或者已經使用但是還沒有遇到的同學做個參考。

使用 Mobx 的列表渲染

使用 Mobx 包裝過的陣列型別,要slice()一下,否則會導致列表渲染不成功。

// store.js
import { observable, action } from 'mobx'

class ListStore {
    @observable listData = []
    
    ...
}

export default new ListStore()

// List.jsx

import Taro, { Component } from '@tarojs/taro'
import { observer, inject } from '@tarojs/mobx'

@inject('ListStore')
@observer
export default class List extends Component {
    ...
    
   
    render() {
        let list = this.props.ListStore.listData
    
        list.slice()
        
        const renderList = list && list.map((item) => (<View>{item.name}</View>))

        return (
            <View>{renderList}</View>
        )
    }
}

複製程式碼

微信小程式手機號碼授權

在微信小程式手機號碼授權登入使用onGetPhoneNumber獲取否則獲取實現不了。

export default class login extends Component {

    getPhoneNumber(event) {
 
    }
 
    render() {
        return (
            <Button  openType='getPhoneNumber' onGetPhoneNumber="this.onGetPhoneNumberHandler.bind(this)">獲取手機號</Button>
        )
    }
}
複製程式碼

條件編譯

Taro 最方便的一點就是支援條件編譯,使用Taro特定的檔案命名方式就能實現,但是隻是在Js方面支援,並不支援在 config 的 pages 選項去用。

// src/set_title

// set_title.h5.js

/**
 * H5 設定頁面title
 * @param {String} title
 */
export default function setTitle (title) {
  document.title = title
}


// set_title.weapp.js

import Taro from '@tarojs/taro'

export default function setTitle (title) {
  Taro.setNavigationBarTitle({ title })
}

複製程式碼

使用

import setTitle from src/set_title

export default class MobileLogin extends Component {
  
    ...
    
    componentWillMount () {
        setTitle('標題')
    }
  
    render() {
        return (<View />)
    }
}
複製程式碼

條件編譯雖然好使,但是在app.js裡面對頁面使用是不可以的,例如你想定製支付寶小程式跟微信小程式通過同一個路徑去訪問不同的頁面,只能通過在頁面內部,通過程式碼進行邏輯判斷實現。

// app.js

config = {
    pages: [
        // 只能是具體的檔案
        'pages/Home/index',
        'pages/List/index'
    ]
}

複製程式碼

版本問題

之前有個此,初始化專案的時候,沒有使用 @taro/Mobx 的模板初始化,而是後來單獨裝的,導致在ios低版本(ios9)上頁面顯示異常。原因是使用的 mobx 版本太新,應該使用 mobx@4.8.0。

// package.json

{
    "dependencies": {
        "@tarojs/mobx": "1.3.19",
        "@tarojs/mobx-h5": "1.3.19",
        "@tarojs/mobx-rn": "1.3.19",
        "mobx": "4.8.0",
        ...
    }
}

複製程式碼

注意: 需要特別注意的是本地全域性安裝的taro-cli專案中依賴的@tarojs相關版本號必須一致,之前有小夥伴出現本地Taro版本很新,拉下程式碼之後,執行專案不成功,這個很坑。

環境變數

通常專案會執行在多個環境,每個環境有一份對應的配置,如介面服務,如果能在編譯的時候自動生成那是最好不過的了,那麼如何能在 Taro 中使用。

安裝 cross-env 設定環境變數,然後修改package.json

// package.json
...
"scripts": {
    "test:weapp": "cross-env APP_NS=test npm run build:weapp",
    "sandbox:weapp": "cross-env APP_NS=sandbox npm run build:weapp",
    "online:weapp": "cross-env APP_NS=online npm run build:weapp"
    ...
}

複製程式碼

修改 Taro 生產環境的配置,只有執行 npm run build:xx 的時候,才會執行此檔案的程式碼,也就是說,在 npm run dev:xx 的時候其實是不受影響的,所以本地開發環境,APP_NS 沒有做設定。

// config/prod.js

const APP_NS = JSON.stringify(process.env.APP_NS);

module.exports = {
  env: {
    NODE_ENV: '"production"',
    APP_NS: `${APP_NS}`
  },
  ...
}

複製程式碼

這樣每次在打包的時候,就能區分出環境了,通過環境設定的環境變數APP_NS的值,就能在編譯的時候取到對應字串,進行區分當前是什麼環境的資源包。

// src/api.js

const _env = process.env.APP_NS

const oUrl = {
    test: 'https://test.suyun.com',
    sandbox: 'https://sandbox.suyun.com',
    online: 'https://online.suyun.com'
}

export const baseUrl = oUrl[_env] || '/api'

複製程式碼

Mock 資料

本地開發,自己編寫伺服器,資料格式自己定義,使用Mockjs 實現,作為本地的一個單獨的伺服器使用。

// mock/server.js

/**
 * mock 伺服器
 */

const express = require('express')
const apiMocker = require('mocker-api')
const Mock = require('mockjs')

const mock = Mock.mock;

const PORT = 3000

const app = express();

const mocker = {
    'GET /list': mock({
        "code": 0,
        "message": 'success',
        "data|10": [
            {
                "sid": "@id",
                "name": "@cname",
                "photo": "@image",
            }
        ]
    })
}


apiMocker(app, mocker)

app.listen(PORT, () => {
  console.log(`Mock Server listening on http://localhost:${PORT}`)
});
複製程式碼

修改 package.js 指令碼命令

"scripts": {
    "mock": "node ./mock/mock-server.js",
    ...
}
複製程式碼

新增mock資料也可以單獨放在一個檔案中,方便維護。

// mocker.js

const Mock = require('mockjs');

const mock = Mock.mock;

const mocker = {
    'GET /list': mock({
        "code": 0,
        "message": 'success',
        "data|10": [
            {
                "sid": "@id",
                "name": "@cname",
                "photo": "@image",
            }
        ]
    })
}

module.exports = mocker

複製程式碼

關注我們

關注公眾號前端論道

相關文章