用React编写的基于Taro + Dva构建的适配不同端(微信小程序、H5、RN 等)的时装衣橱

前言

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 !== &#39;ok&#39;) {
        Taro.showToast({
          title: `${res.data.error.message}~` || res.data.error.code,
          icon: &#39;none&#39;,
          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(&#39;fs&#39;);

const dirName = process.argv[2];

if (!dirName) {
  console.log(&#39;文件夹名称不能为空!&#39;);
  console.log(&#39;示例:npm run tep test&#39;);
  process.exit(0);
}

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

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

  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 &#39;./service&#39;;

export default {
  namespace: &#39;${dirName}&#39;,
  state: {

  },

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

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

};
`;


// service页面模版
const serviceTep = `import Request from &#39;../../utils/request&#39;;

export const demo = (data) => {
  return Request({
    url: &#39;路径&#39;,
    method: &#39;POST&#39;,
    data,
  });
};
`;



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

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

console.log(`模版${dirName}已创建,请手动增加models`);

function titleCase(str) {
  const array = str.toLowerCase().split(&#39; &#39;);
  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(&#39; &#39;);
  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/

评论 抢沙发

表情
  1. #1

    来自河北沧州的用户 8天前
    小白我没有看懂hhh

  2. #2

    来自山东济南的用户 10天前
    写的真好,受用

  3. #3

    来自山西太原的用户 12天前
    太秀了老哥,顶一个

  4. #4

    来自上海徐汇的用户 17天前
    可以说是相当详细了

  5. #5

    来自海南海口的用户 19天前
    赞一个

  6. #6

    来自河北石家庄的用户 19天前
    学习了, 总结的很细很棒, 赞

  7. #7

    来自福建福州的用户 21天前
    点赞,前排摸大佬沾点技术

  8. #8

    来自河北石家庄的用户 21天前
    你们送过来的程序员已经见到了,挺厉害一小伙。另外我这边还缺个产品经理,什么时候给我送个过来?

  9. #9

    来自浙江杭州的用户 22天前
    大神 听说你又有才 人又帅,明明可以靠脸吃饭,可是你偏要靠才华,鼓励师都被你撩了我们怎么办

  10. #10

    来自重庆万州的用户 23天前
    涨知识了

  11. #11

    来自安徽合肥的用户 23天前
    满满的干货,受益匪浅!如果排版再弄好看点,可能点赞数更高

  12. #12

    来自湖南长沙的用户 24天前
    贼详细,收藏了

  13. #13

    来自海南海口的用户 29天前
    虽然很多还看不懂 但是很赞

  14. #14

    来自海南海口的用户 30天前
    大神

  15. #15

    来自天津南开的用户 30天前
    小有所得,不错