React 开发规范 参考

141 阅读3分钟

React 开发规范

以下都本人开发过程中所践行的规范,总结一波。如果对各位有所帮助就perfect了。

命名

  1. 文件夹:使用中划线,如: any-modal
  2. 组件、类、接口、类型:使用帕斯卡+驼峰命名
    const AnyModal:React.FC<AnyFnProps>
    class AnyClass
    interface AnyInterface
    type AntType
  1. 高阶组件:驼峰命名。
  • 返回组件的命名为:高阶组件名+ { 传入组件displayName | 传入组件name | 'Component' }(displayName > name > 'component')
  1. 属性:驼峰命名。若值为true省略赋值。

组件规范

  1. 函数组件使用模板
type AnyFcProps = {
  val:string;
  isProps?:boolean;
  onChange:() => void;
};
const AnyFc:React.FC<AnyFcProps>=(props)=>{
    const {val, onChange} = props;
    // 状态
    // 副作用
    // 函数
    return (
        <div onClick={()=>onChange()}>
            {val}
        </div>
    )
 }
 AnyFc.defaultProps = {
     isProps:false // 非必要属性默认值
 }
 export AnyFcComponent = React.memo(AnyFc)
  1. 对齐方式
    // 方式1
    <AnyFcComponent props1="foo1" />
    // 方式2
    <AnyFcComponent props1="foo1" props2 />
    // 方式3
    <AnyFcComponent 
        props1="foo1"
        props2
    />
    

通讯

  1. 3层内,使用props
  2. 层级超3层,使用redux
  3. redux实现数据的传递不能实现某些场景时可以试着用pubsub-js(实现了兄弟组件间的数据传递)

redux使用规范

  1. store结构
  • 结构不要太深
  • 减少冗余,设计成类似于关系数据库的结构
  • 使用索引保存数据,使用选择器读取数据
  1. redux-saga
  • 使用spawn,防止一个saga的异常导致所有saga无法正常工作
  • 创建saga时需要监听error,防止某个sub_saga为捕获的错误,导致整个系统的崩溃
// 创建 saga 中间件
const sagaMiddleware = createSagaMiddleware({
  onError: (error: Error) => {
    // saga中未被捕获的错误
    console.log('error===', error);
  },
});
  • 使用try/catch捕获异常
function* sagaFn() {
 try {
   const res = yield call(getDataApi);
   return res;
 } catch(e) {
   logger.error('request error: ', e);// 错误日志上报
   message.error('xxxx');   // 错误提示
 }
}
  1. API使用
  • fork:非阻塞,返回task用于取消fork
  • call:阻塞generator
  • take+while(true):连续触发action,上次action结束才会触发下一次
  • takeEvery:只要注册,每次action都会响应,允许多个请求同时执行,不管之前是否有请求尚未结束是非阻塞的
  • takeLatest:只响应最近一次的异步action请求,如果之前还未结束就会被取消。
// take+while(true)
while(true) {
  yield take(pattern);
  yield call(fetchData);
}

// takeEvery
takeEvery(pattern, () => {
  yield call(fetchData);
});

//takeEvery原理
const takeEvery = (pattern, saga, ...args) => {
  while (true) {
    const action = yield take(pattern)
    yield fork(saga, ...args.concat(action))
  }
}


// ./sagas
function* checkout() {
  const cart = yield select(getCart)
}
while (true) {
  yield take('CHECKOUT_REQUEST')
  yield fork(checkout)
}

// saga checkout 仅与getCart选择相耦合,这样可以在多个saga共享getCart选择器,并且如果state结构变化,只需要更新getCart
  1. 文件结构

├── module

│   ├── index.ts

│   └── saga.ts

│   └── thunk.ts(若使用Thunk,使用次文件)

├── root_reducer.ts  // 使用combineReducers集合所有的reducer

├── root-saga.ts // 集合所有saga

└── root-store.ts // 创建store,管理所有的middleware

typescript规范

  1. 变量名
  • 变量:驼峰;常量:大写+下划线
  • 类、接口类型使用驼峰并首字母大写
  • 私有变量使用 _ 为开头
  1. 空格
  • 一元运算不用空格
  • 二运运算空格
  • 一般2格缩进,多行使用4格缩进
  1. 导入与导出
  • 不要使用 export default XXX 来进行导出
  • 避免单行代码过长

sass规范

  1. 使用 @use,不建议使用@import,@use解决了@import的一下问题
  • 使所有的变量、混合指令(mixin)、方法等变成全局,难以定位定义位置。
  • 由于所有的都是全局的,所以库内部的命名要加前缀防止命名冲突。
  • @extend规则也会变为全局的,所以很难预测哪个style的规则会被继承。
  • 每次@import都会被执行,增加编译时间,容易产生冗余css。
  • 无法定义私有变量。

未完待续