<img src="http://static-r.msparis.com/uploads/banners/2/a/2aa5a9ecba9d1f4ebad143902c8c1ceb.jpg!w750" width="100%"/>css
Taro 是一套遵循 React 语法规范的 多端开发 解决方案。现现在市面上端的形态多种多样,Web、React-Native、微信小程序等各类端大行其道,当业务要求同时在不一样的端都要求有所表现的时候,针对不一样的端去编写多套代码的成本显然很是高,这时候只编写一套代码就可以适配到多端的能力就显得极为须要。html
使用 Taro,咱们能够只书写一套代码,再经过 Taro 的编译工具,将源代码分别编译出能够在不一样端(微信小程序、H五、React-Native 等)运行的代码。react
该项目基于Taro,构建了一个时装衣橱的项目演示,涉及了一个电商平台完整的业务逻辑和功能点,若是这个项目能驾驭的了,相信大部分公司的其余React项目也就不在话下。git
查看demo请戳这里(请用chrome手机模式预览)github
<img src="https://gitee.com/easytuan/taro-msparis/raw/master/screenshots/qr-code.png" width="250"/> <img src="https://gitee.com/easytuan/taro-msparis/raw/master/screenshots/weapp-code.jpg" width="250"/>chrome
React + Taro + Dvanpm
git clone git@github.com:EasyTuan/taro-msparis.git # 国内镜像加速节点:git@gitee.com:easytuan/taro-msparis.git cd taro-msparis npm install # 开发时时监听编译小程序 npm run dev:weapp # 开发时时监听编译H5 npm run dev:h5 # pages模版快速生成 npm run tep `文件名`
git分支说明:json
init:框架总体结构,不涉及任何业务逻辑redux
master:项目的稳定版本小程序
feature:项目开发分支
目录结构
├── .temp // H5编译结果目录 ├── .rn_temp // RN编译结果目录 ├── dist // 小程序编译结果目录 ├── config // Taro配置目录 │ ├── dev.js // 开发时配置 │ ├── index.js // 默认配置 │ └── prod.js // 打包时配置 ├── screenshots // 项目截图,和项目开发无关 ├── site // H5静态文件(打包文件) ├── src // 源码目录 │ ├── components // 组件 │ ├── config // 项目开发配置 │ ├── images // 图片文件 │ ├── models // redux models │ ├── pages // 页面文件目录 │ │ └── home │ │ ├── index.js // 页面逻辑 │ │ ├── index.scss // 页面样式 │ │ ├── model.js // 页面models │ │ └── service.js // 页面api │ ├── styles // 样式文件 │ ├── utils // 经常使用工具类 │ ├── app.js // 入口文件 │ └── index.html ├── package.json └── template.js // pages模版快速生成脚本,执行命令 npm run tep `文件名`
<img src="https://gitee.com/easytuan/taro-msparis/raw/master/screenshots/1.png" width="375px" height="667px" /> <img src="https://gitee.com/easytuan/taro-msparis/raw/master/screenshots/2.png" width="375px" height="667px" />
<img src="https://gitee.com/easytuan/taro-msparis/raw/master/screenshots/3.png" width="375px" height="667px" /> <img src="https://gitee.com/easytuan/taro-msparis/raw/master/screenshots/4.png" width="375px" height="667px" />
<img src="https://gitee.com/easytuan/taro-msparis/raw/master/screenshots/5.png" width="375px" height="667px" /> <img src="https://gitee.com/easytuan/taro-msparis/raw/master/screenshots/6.png" width="375px" height="667px" />
安装 Taro 开发工具 @tarojs/cli
使用 npm 或者 yarn 全局安装,或者直接使用npx
$ npm install -g @tarojs/cli $ yarn global add @tarojs/cli
使用命令建立模板项目
$ taro init myApp
进入项目目录开始开发,能够选择小程序预览模式,或者 h5 预览模式,若使用微信小程序预览模式,则须要自行下载并打开微信开发者工具,选择预览项目根目录。
微信小程序编译预览模式
# npm script $ npm run dev:weapp # 仅限全局安装 $ taro build --type weapp --watch # npx 用户也可使用 $ npx taro build --type weapp --watch
H5 编译预览模式
# npm script $ npm run dev:h5 # 仅限全局安装 $ taro build --type h5 --watch # npx 用户也可使用 $ npx taro build --type h5 --watch
RN 编译预览模式
# npm script $ npm run dev:rn # 仅限全局安装 $ taro build --type rn --watch # npx 用户也可使用 $ npx taro build --type rn --watch
固然到这一步有个大概的骨架,做为生产开发是不够的,这时候咱们引入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; } }
并在入口文件导入
import dva from './utils/dva' const dvaApp = dva.createApp({ initialState: {}, models: models, }); const store = dvaApp.getStore();
dva集成好了,下面咱们来封装下request网络请求吧
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} 】【接口响应:】`,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(`网络请求错误,状态码${statusCode}`); } }) }
好了,是应该准备pages页面的开发了,本人比较喜欢umi的目录结构
pages // 页面文件目录 └── home ├── index.js // 页面逻辑 ├── index.scss // 页面样式 ├── model.js // 页面models └── service.css // 页面api
一个page要生成4个文件?可否用脚本帮咱们自动生成呢?那来写一个吧
/** * pages模版快速生成脚本,执行命令 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}已建立,请手动增长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);
如今是时候进行愉快的开发了。。。
目录结构
├── .temp // H5编译结果目录 ├── .rn_temp // RN编译结果目录 ├── dist // 小程序编译结果目录 ├── config // Taro配置目录 │ ├── dev.js // 开发时配置 │ ├── index.js // 默认配置 │ └── prod.js // 打包时配置 ├── screenshots // 项目截图,和项目开发无关 ├── src // 源码目录 │ ├── components // 组件 │ ├── config // 项目开发配置 │ ├── images // 图片文件 │ ├── models // redux models │ ├── pages // 页面文件目录 │ │ └── home │ │ ├── index.js // 页面逻辑 │ │ ├── index.scss // 页面样式 │ │ ├── model.js // 页面models │ │ └── service.js // 页面api │ ├── styles // 样式文件 │ ├── utils // 经常使用工具类 │ ├── app.js // 入口文件 │ └── index.html ├── package.json └── template.js // pages模版快速生成脚本,执行命令 npm run tep `文件名`