96

又一篇React实践【v16.0 +】

 6 years ago
source link: https://zhuanlan.zhihu.com/p/30972165?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

又一篇React实践【v16.0 +】

隐居山野的农夫
路漫漫其修远兮,吾将上下而求索。

背景

完全是出于实践的目的,在一个小业务中,将最新的react工程撸了一遍。【虽说是小业务,两个人也开发了近一周,七个工作日。】

贡献

于是有了这篇文章和【开箱即用】的脚手架工程,其中Options的选项,可以自行移除。不过好消息是这个脚手架工程,我将跟进维护,力保第一时间和react以及其生态周边的库在版本上保持一致。关于react v16.x react-router v4.x的资源,在网路上都有很多,这里就不重复贴了,想说明的是,官网肯定是第一去处。

【开箱即用】icepy/fighting

  • react v16.0 +
  • react-router 4.x
  • webpack 3.x
  • redux

Options

  • ant design
  • iconfont
  • mock server
  • axios
  • 钉钉H5 SDK

fighting 使用MIT协议,欢迎过来添砖加瓦。

正题

在开始准备用v16.x写业务之前,还是下了一番苦工,花了一天时间大概的扫了一遍和其他东西的契合度,这才敢下决心试试,不然还真会坑了自己。

由于在v15.x的版本中已经开始使用PureComponent,于是在v16.x中依然沿用着PureComponent,整体上来看v16.x更多的是在“内核”上的改进,书写过程中很好的和上一个版本的知识积累契合,只是多了一些不同的东西,比如错误捕获【生命周期中的一个方法】,直接返回数组等。在react上真正花了点时间的是在表单的处理上,一直到最后发布上线才解决掉那行警告。如果你可以阅读到fighting项目,基本上可以了解到我是怎么看待这个项目的。

标准的redux,定义action,reducers,使用 redux-thunk 来做异步处理。

// constants.js
export const DEFAULT_SYNC_DEFAULT = 'DEFAULT_SYNC_DEFAULT';
export const DEFAULT_ASYNC_DEFAULT = 'DEFAULT_ASYNC_DEFAULT';

// actions
import { DEFAULT_SYNC_DEFAULT, DEFAULT_ASYNC_DEFAULT } from './constants';

export const getDefault = (params) => {
  return {
    type: DEFAULT_SYNC_DEFAULT,
    payload: {
      data: 'wower'
    }
  }
}

export const getAsyncDefault = (params) => (dispatch) => {
  setTimeout(() => {
    dispatch((() => {
      return {
        type: DEFAULT_ASYNC_DEFAULT,
        payload: {
          data: 'icepy'
        }
      }
    })())
  },2000)
}

// reducers
import { DEFAULT_SYNC_DEFAULT, DEFAULT_ASYNC_DEFAULT } from './constants';

const initState = {
  name: '',
  asyncName: '...'
};

export default function defaultReducers(state = initState, action){
  const { type, payload } = action;
  switch (type){
    case DEFAULT_SYNC_DEFAULT:
      return { ...state, name: payload.data }
    case DEFAULT_ASYNC_DEFAULT:
      return { ...state, asyncName: payload.data}
    default:
      return { ...state}
  }
}

构建基于webpack 3.x来编写,并且对样式进行了autoprefixer处理。

Bash

提炼了三个命令来完成项目的开发:

$ npm start // 项目启动
$ npm run mock-server  // 启动mock服务器
$ npm run build  // 打包可以发布的资源

目录结构

顶级目录结构如下:

  • src 项目源文件
  • build 构建脚本
  • config 构建脚本依赖的配置信息
  • dist 构建完成可发布的资源目录

src 目录结构如下:

  • components 公共组件
  • globals 公共reducers
  • routers 路由
  • containers 页面级别的组件
  • styles 公共样式
  • shared 抽象出来的request util等
  • store redux store
  • app.js 入口.js

containers 目录结构如下:

根据自己的业务,创建页面级别的组件

  • index.js 入口.js
  • .jsx 页面级别的组件
  • .less 页面级别的样式
  • components 这个页面独用的组件
  • flow 这个页面需要的action reducers

发布

使用 npm run build 构建待发布的资源,请忽略根目录中的index.html

建议发布规则:

  • 打包出来的dist发布到CDN中
  • 自己在服务端创建一个index.html,使用服务端输出的方式来引用一个version版本变量
  • 这个变量对应CDN的版本号

遗留问题

由于时间的原因,对于一些遗留的问题并没有处理好。

  • store 数据的清除机制
  • 基于 webpack 的异步处理方案
  • 使用 classname 搞的 css module
  • 路由钩子处理
  • eslint 规则配置,目前只加了一个 pre-commit

期待对于此感兴趣的朋友来提PR


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK