跳到主要内容

开发优秀写法

方法内声明变量

注意数据不可变性

const items = useMemo(() => {
const _items = [deps, ...add];
return _items;
}, [deps, add]);

用箭头函数分隔代码

jsx 中的函数会自动执行

<div>
{() => {
return <span>1</span>;
}}
</div>

Form.field 的 Children 一般可以直接非受控

因为该组件对 children 有拦截,如果是函数会传入参数

<Form.field>
{(value, onChange) => {
return <span>{value}</span>;
}}
</Form.field>

正则表达式在外部创建

const reg = /111/;
const fc = () => {};

多个条件判断可以改为数组

const EMPTY = [null, undefined, ""];

if (EMPTY.includes(a)) {
}

react 不推荐使用&&条件渲染

condition && <Component />;

大部分情况下&&都会生效,但是当第一个值不是 Boolean 类型时,就会出现问题

  • 如果 condition 为 0 ,则在 UI 中显示为 0

  • 如果 condition 未定义,将会抛出错误:未捕获的错误:错误:没有从渲染返回

    不渲染应返回 null

condition ? <Component /> : null;

或者转化为 boolean 类型,但是可读性较差

常用

!!condition && <Component />;

再举个例子

console.log(0 ? 1 : 2); // 2
console.log(0 && 2); // 0

利用对象字面量(map)

对象字面量可以使代码更具有可读性,假如想根据角色显示三种类型用户,不能使用三元, 因为选项数量超过两个

而用 switch 写起来比较麻烦

const { role } = user;

// 对象字面量
const compoents = {
ADMIN: Administer,
EMPLOYEE: EmployeeUser,
USER: NormalUser,
};

const Component = components[role];

return <Component />;

使用 Fragments 语法

始终使用 Fragments 而不是 div

保持代码整洁且有利于性能

<></>

不要在渲染 render 中定义函数

定义变量可能会有闭包风险 但是函数完全可以定义在渲染外,防止重复渲染的性能消耗

组件命名

始终对组件使用 PascalCase (首字母大写)

对实例使用 CamelCase

import ReservationCard from "./ReservationCard";

const resevrvationItem = <ReservationCard />;

引号

对 JSX 属性使用双引号,对所有其他 JS 使用单引号

<Foo bar="bar" />

<Foo style=={{left: '20px'}}>

如果 prop 值是 react 组件,则始终使用 PascalCase 作为 prop 名称

<MyComponent
userName="hello"
Component={<SomeComponent/>}
><MyComponent/>

方法(尤其暴露方法)重要参数前置

可缺省参数后置并设置缺省值

fun(obj[,config])
fun(obj,config={})

函数参数过多(多于 3)创建 object 数据体

但是缺点是无法在数据体内突出核心

fun(a, b, c);
fun({ a: 1, b: 1, c: 1 });

所有 setter 类操作返回 this

一般都是返回 void,但是 js 可以返回 this 直接实现链式调用,优化可读性

事件机制只能选择其一

object.onDoSomething = func;

object.on("doSomething", func);

subType 扩展

// render logic
switch(feed.type) {
case 'item':
...
break
case 'other':
break
default:
break
}

如果增加一种 type: smallItem, 会默认进入 default 分支

考虑 smallItem 应该归为 Item 分支

完全可以增加 subType,而 type 保持为 item

API 名称不应该太具体,保持高抽象度

renderrenderAtFirst

便于背后逻辑变更,而不需要用户替换 API 或了解细节

收敛 API

function renderPage() {
renderHeader();
renderSidebar();
renderFooter();
}

function renderPage() {
rederSections(["header", "Sidebar", "Footer"]);
}

利用 instanceof 聚合函数

function render(vehicle){
if(vehicle instanceof car){
...
}
}

延时操作

一般可以用setTimeout

涉及动画可以用requestAnimationFrame(callback)请求下一个动画帧

利用浏览器底层可以用requestIdleCallback

该 API 比较新,可以先面向接口编程,做一个 polyfill

解构实现增加和删除对象的键

const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // original 也被修改
delete copy.a; // 通过 delete 运算符去除指定属性

const original = { a: 1, b: 2 };
const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
const { a, ...noA } = copy; // noA => { b: 2, c: 3 }

不用展开语法映射(mapping)可迭代对象

[...arr].map() 直接使用Array.from

const baz = Array.from(foo, bar);

尽量不使用 props 透传

除非在高阶组件的使用场景中,否则避免使用展开语法直接传递 this.props 给内部组件,应尽可能筛选出不必要的属性后再传入。


render() {
return <WrappedComponent {...this.props} />
}
render() {
const { irrelevantProp, ...relevantProps } = this.props;
return <WrappedComponent {...relevantProps} />
}

在自闭合标签尾部保留一个空格

定义 displayName

// 对于使用高阶组件生成的组件类,应当定义 displayName,该名称由高阶组件的名称和传入的组件名称组合而成
export default function withFoo(WrappedComponent) {
function WithFoo(props) {
return <WrappedComponent {...props} foo />;
}
const wrappedComponentName =
WrappedComponent.displayName || WrappedComponent.name || "Component";
WithFoo.displayName = `withFoo(${wrappedComponentName})`;
return WithFoo;
}

请求特殊条件下才发送要做返回处理

多个请求,每个请求各自在其特殊条件下才需要发出

预设每个请求为new Promise({code:成功代码})进行占位

这样就算不需要在当前条件下触发,也不会触发失败提示

接着将多个请求放在数组里管理

如果当前条件下需要触发,将数组中该项更新为真实请求

最后数组用 Promise.all 拿结果