前言
Taro 是一套遵循 React 语法规范的 多端开发 解决方案。现如今市面上端的形态多种多样,Web、React-Native、微信小程序等各种端大行其道,当业务要求同时在不同的端都要求有所表现的时候,针对不同的端去编写多套代码的成本显然非常高,这时候只编写一套代码就能够适配到多端的能力就显得极为需要。
使用 Taro,我们可以只书写一套代码,再通过 Taro 的编译工具,将源代码分别编译出可以在不同端(微信小程序、H5、React-Native 等)运行的代码。
该项目基于Taro,构建了一个时装衣橱的项目演示,涉及了一个电商平台完整的业务逻辑和功能点,如果这个项目能驾驭的了,相信大部分公司的其他React项目也就不在话下。
效果演示
查看demo请戳这里(请用chrome手机模式预览)
H5版 && 微信小程序版
技术栈
React + Taro + Dva
项目运行
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分支说明:
init:框架整体结构,不涉及任何业务逻辑
master:项目的稳定版本
feature:项目开发分支
目标功能
- [x] 美衣列表 -- 完成
- [x] 美衣详情 -- 完成
- [x] 登录、注册 -- 完成
- [x] 个人中心 -- 完成
- [x] 优惠券 -- 完成
- [x] 衣袋(购物车) -- 完成
业务介绍
目录结构
├── .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 `文件名`
部分截图展示
首页 && 商品详情
衣袋 && 我的
登录 && 优惠券
taro的安装及使用
安装 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 `文件名`
写在最后
文档
Taro开发文档
https://nervjs.github.io/taro/docs/README.html
dva开发文档地址
https://dvajs.com/
小程序开发文档
https://mp.weixin.qq.com/debug/wxadoc/dev/
来自湖南长沙的用户 3天前
文章挺好,先赞再看,点赞这么少,真的没人喜欢这么用嘛
来自河南郑州的用户 4天前
好文章,值得分享
来自安徽合肥的用户 7天前
优秀,加油!
来自江苏玄武的用户 9天前
感谢。
来自北京朝阳的用户 14天前
点赞,前排摸大佬沾点技术
来自辽宁沈阳的用户 14天前
学习了
来自山西太原的用户 17天前
开始学习
来自北京昌平的用户 19天前
非常感谢,眼界开阔了
来自湖南长沙的用户 22天前
小白我没有看懂hhh
来自北京朝阳的用户 24天前
为何你如此秀
来自河南郑州的用户 24天前
楼下方便加下微信麽,交流下!
来自四川成都的用户 25天前
有发布到github吗?
来自山西太原的用户 26天前
太秀了老哥,顶一个
来自辽宁沈阳的用户 27天前
很棒,很棒
来自河南郑州的用户 30天前
涨知识了