前言

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/

用 React 编写的基于Taro + Dva构建的适配不同端(微信小程序、H5、React-Native 等)的时装衣橱的更多相关文章

  1. 教程视频、项目源码、全部干货【微信小程序、React Native、Java、iOS、数据结构】

    把我收藏多年的教学视频.项目源码分享给大家,大神就可以忽略了,很多东西都是基础性的,都是期初学习阶段收集的东西. 微信小程序(入门级,有web前端基础的人群): 链接: https://pan.bai ...

  2. 基于Taro与Typescript开发的网易云音乐小程序

    基于Taro与网易云音乐api开发,技术栈主要是:typescript+taro+taro-ui+redux,目前主要是着重小程序端的展示,主要也是借此项目强化下上述几个技术栈的使用,通过这个项目也可 ...

  3. 基于Taro与typescript开发的网易云音乐小程序(持续更新)

    基于Taro与网易云音乐api开发,技术栈主要是:typescript+taro+taro-ui+redux,目前主要是着重小程序端的展示,主要也是借此项目强化下上述几个技术栈的使用,通过这个项目也可 ...

  4. Taro开发微信小程序的初体验

    了解Taro 听说Taro是从几个星期前开始的,在一次饭桌上,一个小伙伴说:"Hey, 你听说了Taro么,听说只需要写一套程序就可以生成H5,小程序以及RN的代码模板,并且类似于React ...

  5. Native VS React Native VS 微信小程序

    随着React Native和 微信小程序的出现,Native一家独大的局面出现裂痕,很多小公司使用已经正在着手微信小程序和React Native了,我公司就已经走上React Native之路.那 ...

  6. Taro 微信小程序 上传文件到minio

    小程序前端上传文件不建议直接引用minio的js npm包,一来是这个包本身较大,会影响小程序的体积,二来是ak sk需要放到前端存储,不够安全,因此建议通过请求后端拿到签名数据后上传. 由于小程序的 ...

  7. 从0到1构建适配不同端(微信小程序、H5、React-Native 等)的taro + dva应用

    从0到1构建适配不同端(微信小程序.H5.React-Native 等)的taro + dva应用 写在前面 Taro 是一套遵循 React 语法规范的 多端开发 解决方案.现如今市面上端的形态多种 ...

  8. 迅速上手:使用taro构建微信小程序基础教程

    前言 由于微信小程序在开发上不能安装npm依赖,和开发流程上也饱受诟病:Taro 是由京东·凹凸实验室(aotu.io)倾力打造的 多端开发解决方案,它的api基于react,在本篇文章中主要介绍了使 ...

  9. 微信小程序项目开发实战:用WePY、mpvue、Taro打造高效的小程序》(笔记4)支持React.js语法的Taro框架

    Taro本身实现的情况类似于mpvue,mpvue的未来展望中也包含了支付宝小程序,现在的版本中,也可以使用不同的构建命令来构建出百度小程序的支持,如第10章所示,但是现在Taro先于mpvue实现了 ...

随机推荐

  1. [BZOJ1799][Ahoi2009]self 同类分布(数位dp)

    题目描述 给出两个数 a,ba,b ,求出 [a,b][a,b] 中各位数字之和能整除原数的数的个数. 输入输出格式 输入格式: 一行,两个整数 aa 和 bb 输出格式: 一个整数,表示答案 输入输 ...

  2. Linux下的hosts文件和network文件区别

    Linux下的hosts文件和network文件区别   Linux下有两种与计算机名相关的配置文件     1.hosts文件,路径:/etc/hosts,此文间是在网络上使用的, 用于解析计算机名 ...

  3. jq 使用手册

    翻译整理:Young.J官方网站:http://jquery.com jQuery是一款同prototype一样优秀js开发库类,特别是对css和XPath的支持,使我们写js变得更加方便!如果你不是 ...

  4. Linq中DeferredLoadingEnabled,DataLoadOption的用法

    1.  基本的数据关系图 Student和Class之间是多对一关系,Student和Course之间是多对多关系. DataContext的DeferredLoadingEnabled属性指定是否需 ...

  5. react 中文文档案例五 (循环列表)

    function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) = ...

  6. codeforces 620D Professor GukiZ and Two Arrays

    #include <bits/stdc++.h> using namespace std; + ; const long long inf = 1e18; int n, m; long l ...

  7. CROSS APPLY和 OUTER APPLY 区别详解

    SQL Server 2005 新增 cross apply 和 outer apply 联接语句,增加这两个东东有啥作用呢? 我们知道有个 SQL Server 2000 中有个 cross joi ...

  8. c语言中有关0和1的运算问题

    /*有关0和1 的总结 最近做题总是混淆0 和 1 对于/ 和 %运算时候的结果怎么算 所以就上机试验了一番 结论: c语言中,0/任何数都为0 0%任何数都为0 1/任何数都为0 1%任何数都余1 ...

  9. js 实现继承的几种方式

    //js中实现继承的几种方式 //实现继承首先要有一个父类,先创造一个动物的父类 function Animal(name){ this.name = name; this.shoot = funct ...

  10. java——修改txt文件中某一行的内容

    今天无意间看到java.io中有一个类:RandomAccessFile,可以在文件的任意位置进行读写操作,想到我之前写的一个小项目,想在txt中修改某一行的内容,都是从头遍历txt文件,修改这一行的 ...