從0到1構(gòu)建適配不同端(微信小程序杏慰、H5、React-Native 等)的taro + dva應(yīng)用

從0到1構(gòu)建適配不同端(微信小程序炼鞠、H5缘滥、React-Native 等)的taro + dva應(yīng)用

寫在前面

Taro 是一套遵循 React 語法規(guī)范的 多端開發(fā) 解決方案。現(xiàn)如今市面上端的形態(tài)多種多樣谒主,Web朝扼、React-Native、微信小程序等各種端大行其道霎肯,當(dāng)業(yè)務(wù)要求同時在不同的端都要求有所表現(xiàn)的時候擎颖,針對不同的端去編寫多套代碼的成本顯然非常高,這時候只編寫一套代碼就能夠適配到多端的能力就顯得極為需要观游。

使用 Taro搂捧,我們可以只書寫一套代碼,再通過 Taro 的編譯工具懂缕,將源代碼分別編譯出可以在不同端(微信小程序允跑、H5、React-Native 等)運行的代碼。

技術(shù)棧

React + taro + dva

taro的安裝及使用

安裝 Taro 開發(fā)工具 @tarojs/cli

使用 npm 或者 yarn 全局安裝聋丝,或者直接使用npx

$ npm install -g @tarojs/cli
$ yarn global add @tarojs/cli

使用命令創(chuàng)建模板項目

$ taro init myApp

進入項目目錄開始開發(fā)索烹,可以選擇小程序預(yù)覽模式,或者 h5 預(yù)覽模式弱睦,若使用微信小程序預(yù)覽模式百姓,則需要自行下載并打開微信開發(fā)者工具,選擇預(yù)覽項目根目錄况木。

微信小程序編譯預(yù)覽模式

# npm script
$ npm run dev:weapp
# 僅限全局安裝
$ taro build --type weapp --watch
# npx 用戶也可以使用
$ npx taro build --type weapp --watch

H5 編譯預(yù)覽模式

# npm script
$ npm run dev:h5
# 僅限全局安裝
$ taro build --type h5 --watch
# npx 用戶也可以使用
$ npx taro build --type h5 --watch

RN 編譯預(yù)覽模式

# npm script
$ npm run dev:rn
# 僅限全局安裝
$ taro build --type rn --watch
# npx 用戶也可以使用
$ npx taro build --type rn --watch

當(dāng)然到這一步有個大概的骨架垒拢,作為生產(chǎn)開發(fā)是不夠的,這時候我們引入dva

$ npm i dva-core dva-loading --save

新建dva.js

import { create } from 'dva-core';
import { createLogger } from 'redux-logger';
import createLoading from 'dva-loading';

let app;
let store;
let dispatch;

function createApp(opt) {
  // redux日志
  // opt.onAction = [createLogger()];
  app = create(opt);
  app.use(createLoading({}));

  if (!global.registered) opt.models.forEach(model => app.model(model));
  global.registered = true;
  app.start();

  store = app._store;
  app.getStore = () => store;

  dispatch = store.dispatch;

  app.dispatch = dispatch;
  return app;
}

export default {
  createApp,
  getDispatch() {
    return app.dispatch;
  }
}

并在入口文件導(dǎo)入

import dva from './utils/dva'
const dvaApp = dva.createApp({
  initialState: {},
  models: models,
});
const store = dvaApp.getStore();

dva集成好了火惊,下面我們來封裝下request網(wǎng)絡(luò)請求吧

import Taro from '@tarojs/taro';
import { baseUrl, noConsole } from '../config';

export default (options = { method: 'GET', data: {} }) => {
  if (!noConsole) {
    console.log(`${new Date().toLocaleString()}【 M=${options.url} 】P=${JSON.stringify(options.data)}`);
  }
  return Taro.request({
    url: baseUrl + options.url,
    data: options.data,
    headers: {
      'Content-Type': 'application/json',
    },
    method: options.method.toUpperCase(),
  }).then((res) => {
    const { statusCode, data } = res;
    if (statusCode >= 200 && statusCode < 300) {
      if (!noConsole) {
        console.log(`${new Date().toLocaleString()}【 M=${options.url} 】【接口響應(yīng):】`,res.data);
      }
      if (data.status !== 'ok') {
        Taro.showToast({
          title: `${res.data.error.message}~` || res.data.error.code,
          icon: 'none',
          mask: true,
        });
      }
      return data;
    } else {
      throw new Error(`網(wǎng)絡(luò)請求錯誤求类,狀態(tài)碼${statusCode}`);
    }
  })
}

好了,是應(yīng)該準備pages頁面的開發(fā)了矗晃,本人比較喜歡umi的目錄結(jié)構(gòu)

  pages                  // 頁面文件目錄
    └── home
        ├── index.js           // 頁面邏輯
        ├── index.scss         // 頁面樣式
        ├── model.js           // 頁面models
        └── service.css        // 頁面api

一個page要生成4個文件仑嗅?能否用腳本幫我們自動生成呢宴倍?那來寫一個吧

 /**
 * pages模版快速生成腳本,執(zhí)行命令 npm run tep `文件名`
 */

const fs = require('fs');

const dirName = process.argv[2];

if (!dirName) {
  console.log('文件夾名稱不能為空张症!');
  console.log('示例:npm run tep test');
  process.exit(0);
}

// 頁面模版
const indexTep = `import Taro, { Component } from '@tarojs/taro';
import { View } from '@tarojs/components';
import { connect } from '@tarojs/redux';
import './index.scss';

@connect(({${dirName}}) => ({
  ...${dirName},
}))
export default class ${titleCase(dirName)} extends Component {
  config = {
    navigationBarTitleText: '${dirName}',
  };

  componentDidMount = () => {

  };

  render() {
    return (
      <View className="${dirName}-page">
        ${dirName}
      </View>
    )
  }
}
`;

// scss文件模版
const scssTep = `@import "../../styles/mixin";

.${dirName}-page {
  @include wh(100%, 100%);
}
`;

// model文件模版
const modelTep = `import * as ${dirName}Api from './service';

export default {
  namespace: '${dirName}',
  state: {

  },

  effects: {
    * effectsDemo(_, { call, put }) {
      const { status, data } = yield call(${dirName}Api.demo, {});
      if (status === 'ok') {
        yield put({ type: 'save',
          payload: {
            topData: data,
          } });
      }
    },
  },

  reducers: {
    save(state, { payload }) {
      return { ...state, ...payload };
    },
  },

};
`;


// service頁面模版
const serviceTep = `import Request from '../../utils/request';

export const demo = (data) => {
  return Request({
    url: '路徑',
    method: 'POST',
    data,
  });
};
`;



fs.mkdirSync(`./src/pages/${dirName}`); // mkdir $1
process.chdir(`./src/pages/${dirName}`); // cd $1

fs.writeFileSync('index.js', indexTep);
fs.writeFileSync('index.scss', scssTep);
fs.writeFileSync('model.js', modelTep);
fs.writeFileSync('service.js', serviceTep);

console.log(`模版${dirName}已創(chuàng)建,請手動增加models`);

function titleCase(str) {
  const array = str.toLowerCase().split(' ');
  for (let i = 0; i < array.length; i++) {
    array[i] = array[i][0].toUpperCase() + array[i].substring(1, array[i].length);
  }
  const string = array.join(' ');
  return string;
}

process.exit(0);

現(xiàn)在是時候進行愉快的開發(fā)了。鸵贬。俗他。

目錄結(jié)構(gòu)

├── .temp                  // H5編譯結(jié)果目錄
├── .rn_temp               // RN編譯結(jié)果目錄
├── dist                   // 小程序編譯結(jié)果目錄
├── config                 // Taro配置目錄
│   ├── dev.js                 // 開發(fā)時配置
│   ├── index.js               // 默認配置
│   └── prod.js                // 打包時配置
├── screenshots            // 項目截圖,和項目開發(fā)無關(guān)
├── src                    // 源碼目錄
│   ├── components             // 組件
│   ├── config                 // 項目開發(fā)配置
│   ├── images                 // 圖片文件
│   ├── models                 // redux models
│   ├── pages                  // 頁面文件目錄
│   │   └── home
│   │       ├── index.js           // 頁面邏輯
│   │       ├── index.scss         // 頁面樣式
│   │       ├── model.js           // 頁面models
│   │       └── service.css        // 頁面api
│   ├── styles             // 樣式文件
│   ├── utils              // 常用工具類
│   ├── app.js             // 入口文件
│   └── index.html
├── package.json
└── template.js            // pages模版快速生成腳本,執(zhí)行命令 npm run tep `文件名`

寫在最后

項目完整代碼地址

git分支說明:

init:框架整體結(jié)構(gòu)阔逼,不涉及任何業(yè)務(wù)邏輯

master:項目的穩(wěn)定版本

feature:項目開發(fā)分支

后續(xù)我會加入一些業(yè)務(wù)代碼和小程序兆衅、H5的線上二維碼,方面大家學(xué)習(xí)和交流

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嗜浮,一起剝皮案震驚了整個濱河市羡亩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌危融,老刑警劉巖畏铆,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吉殃,居然都是意外死亡辞居,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門蛋勺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓦灶,“玉大人,你說我怎么就攤上這事抱完≡籼眨” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長每界。 經(jīng)常有香客問我捅僵,道長,這世上最難降的妖魔是什么眨层? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任庙楚,我火速辦了婚禮,結(jié)果婚禮上趴樱,老公的妹妹穿的比我還像新娘馒闷。我一直安慰自己,他們只是感情好叁征,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布纳账。 她就那樣靜靜地躺著,像睡著了一般捺疼。 火紅的嫁衣襯著肌膚如雪疏虫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天啤呼,我揣著相機與錄音卧秘,去河邊找鬼。 笑死官扣,一個胖子當(dāng)著我的面吹牛翅敌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惕蹄,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蚯涮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了卖陵?” 一聲冷哼從身側(cè)響起遭顶,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎泪蔫,沒想到半個月后棒旗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡鸥滨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年嗦哆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婿滓。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡老速,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凸主,到底是詐尸還是另有隱情橘券,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站旁舰,受9級特大地震影響锋华,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜箭窜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一毯焕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧磺樱,春花似錦纳猫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至块差,卻和暖如春侵续,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背憨闰。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工状蜗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人起趾。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓诗舰,卻偏偏與公主長得像警儒,于是被迫代替她去往敵國和親训裆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容