Redux书写习惯
react+redux项目已经是很常见了, redux的流程图
这里对每个点都做详细的规范介绍,最后展示完整的demo。 一、目录结构规范
项目使用的是碎片化目录结构,适合大型项目。 上述是以 二、redux数据源规范通常情况下,每个页面都有自己的数据源,各个页面的数据源是平级的。 import { injectReducer } from '../../store/reducers' export default (store) => ({ path: 'user',getComponent (nextState,cb) { require.ensure([],(require) => { // 拿到reducer和store 动态注入节点 const {infoReducer} = require('./redux/index').default; injectReducer(store,{ key: 'info',reducer: infoReducer }); const Info = require('./containers/info').default; cb(null,Info); }) } }) 上述代码的大致意思就是:当路由走到user页面的时候,到对应模块下的redux文件中 获取对应reducer, . ├── list │ ├── list │ └── detail └── user └── info 对应的redux的结构: { list: {},detail: {},info: {} } 各个页面在redux中的数据源是平铺的,这样各个数据源互不干涉,不影响。 之前还想过另一种方式,参考了一个vuex的多页应用设计。 { list: { list: {},},user: { info: {} } } 根路由结构一样,这样的话,以模块为单位,页面数据源是模块下的一个属性。
所以,还是应该使用节点平铺的方式。 三、redux相关文件名称规范项目目录按照模块划分的, 四、action type变量名称规范在redux中,所有的action type是唯一的,全局不可重复。 写了一段时间,发现一个急于要解决的问题,就是action type的命名。 前两个名字是为了避免变量重名,
例如: // 更新化列表数据 export const LIST_LIST_UPDATE_LIST = 'LIST_LIST_UPDATE_LIST'; // 初始化详情页数据 export const LIST_DETAIL_INIT = 'LIST_DETAIL_INIT'; // 还原详情页数据 export const LIST_DETAIL_RECOVER = 'LIST_DETAIL_RECOVER'; 五、action/action creator书写顺序,export顺序规范actions里面是整个模块的action和action creator。 const updateList = (data) => ({ type: actionType.LIST_LIST_UPDATE_LIST,payload: data }); 还有发请求,请求数据的: function fetchList() { return (dispatch,getState) => { // 这里使用axios发送请求 // 此处可以通过getState()获取到整个store的数据 // 发送请求前处理数据 // return axios.get('/ajax/xxxxxxx') // .then(response => response.data) // .catch(response => response.data) // 模拟接口 return new Promise(()=>{ const array = [ {id: 'a1',title: 'this is title',content: 'this is content'},{id: 'b2',title: 'this is b2 title',content: 'this is content,文章内容文章内容文章内容文章内容文章内容文章内容文章内容文章内容'},{id: 'c3',title: 'this is c3 title',content: 'this is 文章内容文章内容文章内容文章内容文章内容文章内容文章内容文章内容'},{id: 'd4',title: 'this is title d4',{id: 'e5',title: 'this is e5 title',content: 'this is content 文章内容文章内容文章内容文章内容文章内容文章内容文章内容文章内容'} ]; dispatch(updateList(array)); return array; }); } 所以需要区分
export default { fetchList,getDetailById,initDetail,updateDetailStatus,recoverDetail }; 六、reducer书写规范reducers文件包含该模块下的所有页面的reducer, detailState = {}; function detailReducer (state ={...detilState},action) { switch (action.type) { case actionTypes.LIST_DETAIL_INIT: { const { title,content } = action.payload; state.title = title; state.content = content; return { ...state }; } case actionTypes.LIST_DETAIL_RECOVER: { state = detailState; return { ...state }; } default: return state; } }; 七、模块无状态组件规范每个模块都会有些可重用的html代码段,这些代码段里通常还有变量, import React from 'react' import { Link } from 'react-router' export function getListListDOM({ list }) { const result = []; list.map((item) => { result.push( <li key={item.id}> <Link to={`/list/detail/${item.id}`}>{item.title}</Link> </li> ); }); return result; } 页面使用的时候: import React from 'react' import { connect } from 'react-redux' import { bindActionCreators } from 'redux' import actions from '../redux/actions' import { getListListDOM } from '../util/' import '../style/index.scss' import '../style/list.scss' class List extends React.Component { constructor (props) { super(props); this.state = {}; } componentDidMount () { this.props.dispatch(actions.fetchList()) .then((result) => { // 在业务层里进行报错提示等业务操作 if (result) { console.log('获取数据成功'); } }); } render () { const listDOM = getListListDOM(this.props.list); return ( <div> <ul> {listDOM} </ul> </div> ); } } const mapStateToProps = state => ({ list: state.list,}); export default connect(mapStateToProps,dispatch => ({ ...bindActionCreators(actions,dispatch),dispatch }))(List) 八、数据和业务分离规范引入redux就是帮我们管理数据的,所以在redux的相关文件里面不要做view层能做的事。 九、公共组件使用redux规范公共组件面临着在多个页面使用的场景,需要的参数虽然相同,但是可能来自不同的数据节点, 十、搭配 eslint-react 使用项目中,为了规范大家的代码,使用到了eslint,并且引入了针对react规范的包。 { "rules": { "comma-dangle": 0,"no-console": 0,"react/default-props-match-prop-types": 2,// 有默认值的属性必须在propTypes中指定 "react/no-array-index-key": 2,// 遍历出来的节点必须加key "react/no-children-prop": 2,// 禁止使用children作为prop "react/no-direct-mutation-state": 2,// 禁止直接this.state = 方式修改state 必须使用setState "react/no-multi-comp": 2,// 一个文件只能存在一个组件 "react/no-set-state": 2,// 不必要的组件改写成无状态组件 "react/no-string-refs": 2,// 禁止字符串的ref "react/no-unescaped-entities": 2,// 禁止'<','>'等单标签 "react/no-unknown-property": 2,// 禁止未知的DOM属性 "react/no-unused-prop-types": 2,// 禁止未使用的prop参数 "react/prefer-es6-class": 2,// 强制使用es6 extend方法创建组件 "react/require-default-props": 2,// 非require的propTypes必须制定默认值 "react/self-closing-comp": 2,// 没有children的组件和html必须使用自闭和标签 "react/sort-comp": 2,// 对组件的方法排序 "react/sort-prop-types": 2,// 对prop排序 "react/style-prop-object": 2,// 组件参数如果是style,value必须是object "react/jsx-boolean-value": 2,// 属性值为true的时候,省略值只写属性名 "react/jsx-closing-bracket-location": 2,// 强制闭合标签的位置 "react/jsx-closing-tag-location": 2,// 强制开始标签闭合标签位置 "react/jsx-equals-spacing": 2,// 属性赋值不允许有空格 "react/jsx-first-prop-new-line": 2,// 只有一个属性情况下单行 "react/jsx-key": 2,// 强制遍历出来的jsx加key "react/jsx-max-props-per-line": [2,{ "maximum": 2 }],// 每行最多几个属性 "react/jsx-no-comment-textnodes": 2,// 检查jsx注释 "react/jsx-no-duplicate-props": 2,// 检查属性名重名 "react/jsx-no-target-blank": 2,// 检查jsx是否被引入和使用 "react/jsx-no-undef": 2,// 检查jsx引用规范 "react/jsx-pascal-case": 2,// 检查jsx标签名规范 } } 总结其实redux引入相当于是前端引入了一个数据库,全局可以使用,但是不可持久化。 完整的项目:https://github.com/Aus0049/re... (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |