标准: 导入模块的程序
以有组织的形式引入 ES6 模块将节俭你查找任何找不到或不须要模块的工夫
之前
import {PageHeaderWrapper} from "@ant-design/pro-layout";
import {CustomFormHOC} from "@/components/FormWidget";
import {Form, Card, Button, Divider, message, Alert} from "antd";
import {connect} from "dva";
import PropTypes from "prop-types";
import React, {Component} from "react";
import TransportInfo from "./TransportInfo";
import RecordInfo from "./RecordInfo";
import router from "umi/router";
import styles from "./index.less";
之后
// node_modules
import React, {Component} from "react";
import {Form, Card, Button, Divider, message, Alert} from "antd";
import {connect} from "dva";
import router from "umi/router";
import PropTypes from "prop-types";
import {PageHeaderWrapper} from "@ant-design/pro-layout";
// 我的项目公共模块
import {CustomFormHOC} from "@/components/FormWidget";
// 以后业务耦合模块
import TransportInfo from "./TransportInfo";
import RecordInfo from "./RecordInfo";
// 款式文件
import styles from "./index.less";
在 之前 的引入是无序的,一个文件可能会很乱,然而当你关上大量文件时候,尝试找到一个特定的包真的很难。
应用 之后 的形式对导入的包进行分组,通过空格行宰割每个模块。又因为文件将保持一致,就能够删除正文了。
标准: 尽可能应用解构
另外一个重要的事件就是避免不必要的嵌套和反复(将对象的属性值保留为局部变量)
- 对象成员嵌套越深,读取速度也就越慢。所以好的教训法令是:如果在函数中须要屡次读取一个对象属性,最佳做法是将该属性值保留在局部变量中,防止屡次查找带来的性能开销 ( 对象变量防止嵌套过深)
- 函数参数越少越好,如果参数超过两个,要应用 ES6 的解构语法,这样就不必思考参数的程序了
- 应用参数默认值 代替应用条件语句进行赋值
在大多数状况下,将大大晋升可读性。
之前
const Page=(deliveryCompany,carrierName,driverInfo,driverInfo)=>{
return(<Descriptions.Item label="供应商">{deliveryCompany || '未知'}</Descriptions.Item>
<Descriptions.Item label="承运商">{carrierName || '未知'}</Descriptions.Item>
<Descriptions.Item label="司机">{driverInfo.driver || '未知'}</Descriptions.Item>
<Descriptions.Item label="联系方式">{driverInfo.contact || '未知'}</Descriptions.Item>
);
}
之后
const Page=dataDetail=>{
const {
deliveryCompany = '未知',
carrierName = '未知',
driverInfo = {driver: '未知', contact: '未知'},
} = props;
const {driver, contact} = driverInfo;
return(<Descriptions.Item label="供应商">{deliveryCompany}</Descriptions.Item>
<Descriptions.Item label="承运商">{carrierName}</Descriptions.Item>
<Descriptions.Item label="司机">{driver}</Descriptions.Item>
<Descriptions.Item label="联系方式">{contact}</Descriptions.Item>
);
}
标准: 变量和办法的命名约定
对于代码,有一点很重要,就是要晓得一个办法将返回什么,或者通过变量名轻松了解变量的含意(变量语义化),比方
- JS 采纳 Camel Case 小驼峰式命名
- 防止名称冗余,保障语义明确
- 每个常量都须要有意义的变量名(不然看代码的人不晓得这个常量示意什么意思)
动词 | 含意 |
---|---|
can | 判断是否可执行某个动作 |
has | 判断是否含有某个值 |
is | 判断是否为某个值 |
get | 获取某个值 |
set | 设置某个值 |
之前
User.cat = true;
User.admin = true;
function NewUser(age) {
User.age = 150 - age;
return User;
}
function add_photo(photo) {User.photo = photo;}
之后
let user = {};
user.hasCat = true;
User.isAdmin = true;
const maxAge = 150;
function getUser(age) {
User.age = maxAge - age;
return User;
}
function setUserPhoto(photo) {User.photo = photo;}
在 之后 展现了如何在命名变量和办法放弃一致性,在以下方面保持一致:
- 对于布尔类型应用:is, has,should 做前缀
- 对于办法应用 get/set 做前缀
- 变量和办法都应用驼峰命名
- 应用 ES6 的 const 定义常量
在 之后,组件为注入一些公共变量做筹备,比方 style, className, key 等等,应用开展操作,将一组公共属性传入容器。
标准: 删除弃用代码
很多时候有些代码曾经没有用了,然而没有及时去删除,这样导致代码外面包含很多正文的代码块,好的习惯是提交代码前记得删除曾经确认弃用的代码,例如:一些调试的 console
语句、无用的弃用代码。版本控制系统的存在是有起因的。如果想找旧代码就到 Git history 去找吧。
之前
doStuff();
// doOtherStuff();
// doSomeMoreStuff();
// doSoMuchStuff();
之后
doStuff();
标准: 放弃必要的正文
代码正文不是越多越好,放弃必要的业务逻辑正文,至于函数的用处、代码逻辑等,要通过语义化的命令、简单明了的代码逻辑,来让浏览代码的人疾速看懂。
标准: 应用 Async/Await 代替 Promise 和回调函数
Promise 是较回调而言更好的一种抉择,但 ES7 中的 async 和 await 更胜过 Promise
在能应用 ES7 个性的状况下能够尽量应用他们代替 Promise
之前
require("request-promise")
.get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin")
.then(function (response) {return require("fs-promise").writeFile("article.html", response);
})
.then(function () {console.log("File written");
})
.catch(function (err) {console.error(err);
});
之后
async function getCleanCodeArticle() {
try {const request = await require("request-promise");
const response = await request.get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin");
const fileHandle = await require("fs-promise");
await fileHandle.writeFile("article.html", response);
console.log("File written");
} catch (err) {console.log(err);
}
}
标准: 如何捕捉谬误
谬误抛出是个好货色!这使得你可能胜利定位运行状态中的程序产生谬误的地位。
应用 try catch
对捕捉的谬误不做任何解决是没有意义的。
代码中 try/catch
的意味着你认为这里可能呈现一些谬误,你应该对这些可能的谬误存在相应的解决计划(前端监控计划之一)。
之前
try {functionThatMightThrow();
} catch (error) {console.log(error);
}
之后
try {functionThatMightThrow();
} catch (error) {// One option (more noisy than console.log):
console.error(error);
// Another option:
notifyUserOfError(error);
// Another option:
reportErrorToService(error);
// OR do all three!
}
应用 Promise 的 catch
之前
getdata()
.then((data) => {functionThatMightThrow(data);
})
.catch((error) => {console.log(error);
});
之后
getdata()
.then((data) => {functionThatMightThrow(data);
})
.catch((error) => {// One option (more noisy than console.log):
console.error(error);
// Another option:
notifyUserOfError(error);
// Another option:
reportErrorToService(error);
// OR do all three!
});
标准: React 相干
一些十分根底的标准这里就不说了,说一些比根底高级一点的 😆
- 举荐应用函数式 +Hooks 编写代码
恪守 Hooks 规定
不要在循环、条件和嵌套函数内调用 Hooks。当你想有条件地应用某些 Hooks 时,请在这些 Hooks 中写入条件。
错误代码
if (name !== "") {useEffect(function persistForm() {localStorage.setItem("formData", name);
});
}
应该这样做
useEffect(function persistForm() {if (name !== "") {localStorage.setItem("formData", name);
}
});
这条规定能确保每次渲染组件时都以雷同的顺序调用 Hooks。这样一来,React 就能在多个 useState 和 useEffect 调用之间正确保留 Hooks 的状态。
应用 ESLint 的 React Hooks 插件
React 团队还创立了一个名为 eslint-plugin-react-hooks 的 ESLint 插件,以帮忙开发人员在本人的我的项目中以正确的形式编写 React Hooks。这个插件可能帮忙你在尝试运行应用程序之前捕捉并修复 Hooks 谬误。
它有两条简略的规定:
- react-hooks/rules-of-hooks
- react-hooks/exhaustive-deps
第一条规定只是强制你的代码合乎我在第一个技巧中阐明的 Hooks 规定。第二个规定,exhaustive-deps 用于施行 useEffect 的规定:effect 函数中援用的每个值也应呈现在依赖项数组中。
例如,上面这个 userInfo 组件会触发 exhaustive-deps 正告,因为 userId 变量在 useEffect 外部被援用,但未在依赖项数组中传递:
function UserInfo({userId}) {const [user, setUser] = useState(null);
useEffect(() => {getUser(userId).then((user) => setUser(user));
}, []); // no userId here
return <div>User detail:</div>;
}
以正确的程序创立函数组件
倡议先应用 useState Hook 申明状态变量,而后应用 useEffect Hook 编写订阅,接着编写与组件作业相干的其余函数。
最初,你得返回要由浏览器渲染的元素:
function App() {const [user, setUser] = useState(null);
const [name, setName] = useState("");
useEffect(() => {console.log("component is mounted");
}, []);
return <h1>React component order</h1>;
}
useState 的用法能够和类组件的状态完全一致,不只用于单个值
许多 useState 示例会向你展现如何通过申明多个变量来申明多个状态:
const [name, setName] = useState("John Doe");
const [email, setEmail] = useState("johndoe@email.com");
const [age, setAge] = useState(28);
然而 useState 实际上既能够解决数组也能够解决对象。你仍旧能够将相干数据分组为一个状态变量,如以下示例所示:
const [user, setUser] = useState({
name: "John Doe",
email: "john@email.com",
age: 28,
});
这里有一个正告。应用 useState 的更新函数更新状态时,以前的状态会替换为新状态。这与类组件的 this.setState 不同,后者的新类中,新状态会与旧状态合并:
const [user, setUser] = useState({
name: "John",
email: "john@email.com",
age: 28,
});
setUser({name: "Nathan"});
// result {name: 'Nathan'}
为了保留以前的状态,你须要创立将以后状态值传递到本身中的回调函数来手动合并它。因为下面的示例已将 user 变量调配为状态值,因而能够将其传递给 setUser 函数,如下所示:
setUser((user) = > ({...user, name: 'Nathan'}));
// result is {name:'Nathan', email: 'john@email.com', age: 28}
依据数据在应用程序生命周期中的变动状况,倡议在各个值彼此独立时将状态拆分为多个变量。
然而对于某些状况,例如构建一个简略的表单,最好将状态分组在一起,以便更轻松地解决更改和提交数据。
简而言之,你须要在多个 useState 调用和单个 useState 调用之间保持平衡。
应用自定义 Hooks 共享利用程序逻辑
在构建应用程序时,你会留神到一些利用程序逻辑会在许多组件中一次又一次地应用。
随着 React Hooks 的公布,你能够将组件的逻辑提取到可重用的函数中作为自定义 Hooks, 比方 ” 非驰名 ” 阿里开源库 ahooks
应用 useContext 防止 prop drilling
prop-drilling 是 React 应用程序中的常见问题,指的是将数据从一个父组件向下传递,通过各层组,直到达到指定的子组件,而其余嵌套组件实际上并不需要它们。
React Context 是一项性能,它提供了一种通过组件树向下传递数据的办法,这种办法无需在组件之间手动传 props。父组件中定义的 React Context 的值可由其子级通过 useContext Hook 拜访。
1. 组件申明
组件名称和定义该组件的文件名称倡议要保持一致
之前
import FooterComponent from "./FooterComponent/index";
之后
import Footer from "./Footer/index";
2. React 中的命名
- 组件名称:举荐应用大驼峰命名;
- 属性名称:React DOM 应用小驼峰命令来定义属性的名称,而不应用 HTML 属性名称的命名约定;
- style 款式属性:采纳小驼峰命名属性的 JavaScript 对象;
// 组件名称
MyComponent;
// 属性名称
onClick;
// 款式属性
backgroundColor;
3. 对齐
// 举荐
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
/>
// 如果组件的属性能够放在一行(一个属性时)就放弃在以后一行中
<Foo bar="bar" />
// 多行属性采纳缩进
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
>
<Quux />
</Foo>
// 不举荐
<Foo superLongParam="bar"
anotherSuperLongParam="baz" />
4. 引号
JSX 的属性都采纳双引号,其余的 JS 都应用单引号,因为 JSX 属性 不能蕴含本义的引号, 所以当输出 “don’t” 这类的缩写的时候用双引号会更不便
之前
<Foo bar='bar' />
<Foo style={{left: "20px"}} />
之后
<Foo bar="bar" />
<Foo style={{left: '20px'}} />
4. 为你的组件接管公共变量做好筹备
之前
const UserInfo = (props) => {const { name, sex, age} = props;
return (
<div>
<div> 姓名:{name}</div>
<div> 性别:{sex}</div>
<div> 年龄:{age}</div>
</div>
);
};
之后
const UserInfo = (props) => {const { name, sex, age, ...rest} = props;
return (<div {...rest}>
<div> 姓名:{name}</div>
<div> 性别:{sex}</div>
<div> 年龄:{age}</div>
</div>
);
};
7. 组件遵循繁多职责准则
组件遵循繁多职责准则(Single Responsibility Principle)能够让你轻松创立和奉献代码,并放弃代码库的整洁。
即容器组件与傻瓜组件。
- 容器组件负责数据的申请与获取,props/state 的更新。
- 傻瓜组件只负责接管 props,抛出事件
之前
import React, {useState, useEffect} from "react";
import fetch from "isomorphic-fetch";
const UserInfo = (props) => {const [user, setUser] = useState(null);
useEffect(() => {async function getUser() {const user = await fetch("/userAppi");
if (user) {setUser(user);
}
}
getUser();}, []);
const {name, age} = user;
return (
<div>
<div>{name}</div>
<div>{age}</div>
</div>
);
};
之后
import React, {useState, useEffect} from "react";
import {fetchUser} from "./api";
const UserInfo = (props) => {const { user} = props;
const {name, age} = user;
return (
<div>
<div>{name}</div>
<div>{age}</div>
</div>
);
};
const UserInfoPage = (props) => {const [user, setUser] = useState(null);
useEffect(() => {async function getUser() {const user = await fetchUser("/userAppi");
if (user) {setUser(user);
}
}
getUser();}, []);
return <UserInfo user={user} />;
};
附加:如果你正在应用类型查看器,请让它发挥作用。
如果你的团队抉择应用类型查看器,那么应用严格模式很重要,以确保它能发挥作用,来达到应用它的目标。
interface UserInfoInterface {
name: string;
age: number;
}
const UserInfo = (props: UserInfoInterface) => {const { user} = props;
const {name, age} = user;
return (
<div>
<div>{name}</div>
<div>{age}</div>
</div>
);
};
参考文档
- [[译]晋升你 react 和 js 编码的 5 个技巧](https://mp.weixin.qq.com/s/98…
- 团队 React 代码标准制订
- 前端团队代码评审 CheckList 清单
- 京东凹凸实验室代码标准
最初
在日常工作中你还应用哪些 JavaScript 标准 呢?欢送在评论区留下的你的见解!
感觉有播种的敌人欢送 点赞 , 关注 一波!
往期文章
react 构建系列
- 企业级前端开发标准如何搭建 🛠
- 「React Build」之集成 Webpack5/React17
- 「React Build」之集成 CSS/Less/Sass/Antd
- 「React Build」之集成图片 / 字体
- 「React Build」之集成 Redux/Typescript
- 「React Build」之应用 Redux-thunk 实现 Redux 异步操作
- 「React Build」之集成 React-Router/Antd Menu 实现路由权限