react textarea 空格为什么不换行_你需要的 React + TypeScript 50 条规范和经验
這篇文章沒有對錯之分,肯定也有不完善的地方,結(jié)合了自己日常開發(fā)和經(jīng)驗。可以讓你書寫代碼更具嚴謹性,希望看完之后有所幫助。本文字數(shù)4000+ ,看完本文大概需半小時。
1. 注釋
(1) 文件頂部的注釋,包括描述、作者、日期
/** * @description xxxxxx * @author chengfeng * @since 19/05/21 */復(fù)制代碼(2) 模塊的注釋
/** * 拷貝數(shù)據(jù) * @param {*} data 要拷貝的源數(shù)據(jù) * @param {boolean} [isDeep=false] 是否深拷貝,默認淺拷貝 * @return {*} 返回拷貝后的數(shù)據(jù) */復(fù)制代碼(3) 業(yè)務(wù)代碼注釋
/*業(yè)務(wù)代碼注釋*/復(fù)制代碼(4) 變量注釋
interface IState { // 名字 name: string; // 電話 phone: number; // 地址 address: string;}復(fù)制代碼2. 引用組件順序
- 先引用外部組件庫,,再引用當(dāng)前組件塊級組件, 然后是 common 里的公共函數(shù)庫最后是 css 樣式
3. 引號
- 使用單引號,或者 es6 的反引號
4. 縮進
- 使用兩個空格
5. 分號
- 除了代碼塊的以外的每個表達式后必須加分號。
6. 括號
下列關(guān)鍵字后必須有大括號(即使代碼塊的內(nèi)容只有一行):if, else, for, while, do, switch, try, catch, finally, with。
// not goodif (condition) doSomething();// goodif (condition) { doSomething();}復(fù)制代碼7. 空格
- 二元和三元運算符兩側(cè)必須有一個空格,一元運算符與操作對象之間不允許有空格。
- 用作代碼塊起始的左花括號 { 前必須有一個空格。
- if / else / for / while / function / switch / do / try / catch / finally 關(guān)鍵字后,必須有一個空格。
- 在對象創(chuàng)建時,屬性中的 : 之后必須有空格,: 之前不允許有空格。
8. 換行
- 每個獨立語句結(jié)束后必須換行。
- 在函數(shù)聲明、函數(shù)表達式、函數(shù)調(diào)用、對象創(chuàng)建、數(shù)組創(chuàng)建、for 語句等場景中,不允許在 , 或 ; 前換行
- 下列關(guān)鍵字后:else, catch, finally 不需要換行
9. 數(shù)組、對象
- 對象屬性名不需要加引號;
- 對象以縮進的形式書寫,不要寫在一行;
- 數(shù)組最后不要有逗號。
- 對象最后要有逗號。
10. 命名
- 類名: 大駝峰式風(fēng)格,字母和數(shù)字,例如:AbcTest。禁止?jié)h字、特殊符號,禁止非大駝峰式風(fēng)格。
- 函數(shù)名: 小駝峰式風(fēng)格,字母和數(shù)字,例如:abcTest。禁止?jié)h字、特殊符號,禁止非小駝峰式風(fēng)格,例如snake_case等。
- 變量名: 同函數(shù)名。
- 常量: 全大寫風(fēng)格,大寫字母、數(shù)字和下劃線,單詞之間以下劃線分隔,例如:ABC_TEST。禁止?jié)h字、特殊符號、小寫字母。
- 使用 onXxx 形式作為 props 中用于回調(diào)的屬性名稱。
- 組件內(nèi)的事件函數(shù)使用 handle 開頭尾,handleCheckBtn。
- 使用 withXxx 形式的詞作為高階組件的名稱。
- 接口命名前面帶上 I 表示 interface
11. 類型斷言
// badfunction getLength(something: string | number): number { return something.length;}// index.ts(2,22): error TS2339: Property 'length' does not exist on type 'string | number'.// Property 'length' does not exist on type 'number'.// bad function getLength(something: string | number): number { if ((something).length) { return (something).length; } else { return something.toString().length; }}// goodfunction getLength(something: string | number): number { if (typeof something === 'string') { return something.length; } else { return something.toString().length; }}復(fù)制代碼12. interface聲明順序
日常用到比較多的是四種,只讀參數(shù)放第一位,必選參數(shù)第二位,可選參數(shù)次之,不確定參數(shù)放最后
interface iProps { readonly x: number; readonly y: number; name: string; age: number; height?: number; [propName: string]: any;}復(fù)制代碼13. ts好用的相關(guān)工具泛型
- Record 用這個來聲明對象結(jié)構(gòu)的類型
- Partial 作用是將傳入的屬性變?yōu)榭蛇x項.
- Readonly 作用是將傳入的屬性變?yōu)樽兂芍蛔x
- Required 的作用是將傳入的屬性變?yōu)楸剡x項
查看更多
14. ts一些好用的小tips
- keyof
- in
15. 規(guī)范其他
- 不要使用 var 聲明變量
- 不會被修改的變量使用 const 聲明
- 去除聲明但未被引用的代碼
- 禁止在代碼里使用 debug
- 不允許有空的代碼塊
16. 僅當(dāng)初始 state 需要從 props 計算得到的時候,才將 state 的聲明放在構(gòu)造函數(shù)中,其它情況下使用靜態(tài)屬性聲明 state,并且一般情況下不要將 prop 傳給 state,
// badconstructor (){ this.setState({ people: this.props.people })}// goodstate: IState = { people: {},};復(fù)制代碼17. 渲染默認值
- 添加非空判斷可以提高代碼的穩(wěn)健性,例如后端返回的一些值,可能會出現(xiàn)不存在的情況,應(yīng)該要給默認值.
- 還有一種情況,就是本來后端應(yīng)該返回一個數(shù)組給你,但是數(shù)據(jù)庫取不到數(shù)據(jù),可能后端給你返回了null,然后前端null.length。這樣就gg了
18. 不確定的屬性,最后卻瘋狂的用...訪問不存在的屬性
例如一些地方,不確定這個變量里面到底有什么,但自己覺得有,就瘋狂的...,最明顯的就是后端返回了一個對象給你,前端拿到之后判斷都不判斷直接data.dataList.forEach()
// badconst data = await getPeopleList(keyword, page, pageSize);data.dataList.forEach() // 直接掛了// goodconst data = await getPeopleList(keyword, page, pageSize);if (data && data.dataList && Array.isArray(data.dataList) { data.dataList.forEach() }復(fù)制代碼19. 數(shù)據(jù)格式轉(zhuǎn)換
20. 判斷條件真假
js 中以下為假,其他情況為真
- false
- null
- undefined
- 0
- '' (空字符串)
- NaN
21. 簡單組件可以使用函數(shù)代替
// badclass Listing extends React.Component { render() { return {this.props.hello}; }}// goodfunction Listing({ hello }) { return {hello};}復(fù)制代碼22. 對于常用的屬性進行緩存
// badthis.props.app.openid;this.state.time// goodconst { app } = this.props;const { time } = this.state;console.log(app.openid)復(fù)制代碼23. input 輸入框使用 trim()
// badlet searchContent = form.search.value;// goodlet searchContent = form.search.value.trim();復(fù)制代碼24. 使用 location 跳轉(zhuǎn)前需要先轉(zhuǎn)義
// badwindow.location.href = redirectUrl + '?a=10&b=20';// goodwindow.location.href = redirectUrl + encodeURIComponent('?a=10&b=20');復(fù)制代碼25. 使用 react-router
// badimport { withRouter, RouteComponentProps } from 'react-router-dom';export interface IProps extends RouteComponentProps {}class App extends React.Component {}export default withRouter(App);// goodimport { withRouter, RouteComponentProps } from 'react-router-dom';class App extends React.Component, AppStates> {}export default withRouter(App);復(fù)制代碼26. 同時開發(fā),數(shù)據(jù)請求 api 目錄 git 沖突目錄方案
- 在 api 目錄下新建一個目錄,目錄對應(yīng)一級 tab,這個目錄內(nèi)放置一個 index.js ,最后把二級 tab 組件所使用的 api 請求都在這個 index.js 內(nèi)引入。
27. 組件嵌套過深
- 組件一般不要超過三層,最多四層,層級過深可能會導(dǎo)致數(shù)據(jù)傳遞過深,在做一些顆粒度比較細的操作的時候,處理起來較為繁瑣,可以使用 redux 等狀態(tài)管理工具替代。
28. 代碼過濾掉你沒考慮到的情況
- 例如一個函數(shù),你只想操作字符串,那你必須在函數(shù)開頭就只允許參數(shù)是字符串
29. 業(yè)務(wù)代碼里面的異步請求需要 try catch
- ajax 請求,使用 try catch,錯誤提示后端返回,并且做一些失敗后的狀態(tài)操作例如進入列表頁,我們需要一個 loading 狀態(tài),然后去請求數(shù)據(jù),可是失敗之后,也需要把 loading 狀態(tài)去掉,把 loading 隱藏的代碼就寫在 finally 里面。
30. setState有三種用法
// 對象this.setState({})// 函數(shù),一般是用于在setState之前做一些操作this.setState( () => { // TODO console.log('') return { a:300 } })// 第二個參數(shù),一般是用于在setState之后做一些操作this.setState({ a:300}, () => { // TODO})復(fù)制代碼31. setState可能是同步的
- setState 在react里的合成事件和鉤子函數(shù)中是“異步”的。
- setState 在原生事件和 setTimeout 中是同步的。
32. 不要在 setState 前面加 await
- setState 前面也是可以帶 await 的,會變成同步設(shè)置狀態(tài),但這是一種巧合,不確定未來哪個版本就不支持了,為了遵循 react 框架的設(shè)計原則,我們使用回掉函數(shù)的形式。
33. 阻止事件默認行為
- 在 React 中你不能通過返回 false 來阻止默認行為。必須明確調(diào)用 preventDefault 。
34. 在 componentWillUnmount 里面去除副作用的函數(shù)
- 清除 EventListener
- 中止數(shù)據(jù)請求
- 清除定時器
35. key
- 對于組件中的 key 優(yōu)化,起到最大化重用 dom
36. for-in 中一定要有 hasOwnProperty 的判斷(即禁止直接讀取原型對象的屬性)
//badconst arr = [];const key = '';for (key in obj) { arr.push(obj[key]);}//goodconst arr = [];const key = '';for (key in obj) { if (obj.hasOwnProperty(key)) { arr.push(obj[key]); }}復(fù)制代碼37. 第三方庫函數(shù)的使用
- 用 try catch 包裹,防止第三方庫的出現(xiàn)錯誤,導(dǎo)致整個程序崩潰
38. 防止 xss 攻擊
- input,textarea 等標(biāo)簽,不要直接把 html 文本直接渲染在頁面上,使用 xssb 等過濾之后再輸出到標(biāo)簽上;
39. 在組件中獲取真實 dom
- 使用 16 版本后的 createRef()函數(shù)
40. 減少魔法數(shù)字
- 寫代碼的時候盡量減少一些未知含義的數(shù)字,盡量用英文單詞。例如type === 0的時候做了一些操作,讓人不知所以然。
41. 如果需要優(yōu)化 react 性能(一般用不到)
- 如果組件的 state 和 props 都是簡單類型,可以繼承 PureComponent 而不是 Component
- 重寫 shouldComponentUpdate 方法,在 shouldComponentUpdate 里面根據(jù) state,props 是否有改變來判斷是否需要重新渲染.如果組件繼承了 PureComponent 就沒必要再重寫 shouldComponentUpdate 方法
42. Event 事件對象類型
很多小伙伴用了很久的ts,都不知道常用 Event 事件對象類型:
ClipboardEvent 剪貼板事件對象
DragEvent 拖拽事件對象
ChangeEvent Change 事件對象
KeyboardEvent 鍵盤事件對象
MouseEvent 鼠標(biāo)事件對象
TouchEvent 觸摸事件對象
WheelEvent 滾輪事件對象
AnimationEvent 動畫事件對象
TransitionEvent 過渡事件對象
import { MouseEvent } from 'react';interface IProps { onClick(event: MouseEvent): void;}復(fù)制代碼43. 使用私有屬性取代state狀態(tài)
對于一些不需要控制ui的狀態(tài)屬性,我們可以直接綁到this上, 即私有屬性,沒有必要弄到this.state上,不然會觸發(fā)渲染機制,造成性能浪費 例如請求翻頁數(shù)據(jù)的時候,我們都會有個變量。
// badstate: IState = { pageNo:1, pageSize:10};// good queryParams:Record = { pageNo:1, pageSize:10}復(fù)制代碼44. 代碼細粒度的思考
總結(jié)四句話。我們在寫組件或者函數(shù)的的時候,工具函數(shù)和業(yè)務(wù)邏輯抽離,表單校驗和業(yè)務(wù)抽離、事件函數(shù)和業(yè)務(wù)抽離,ajax和業(yè)務(wù)抽離。 例如有些頁面是通過location.href跳轉(zhuǎn)的,我們有些業(yè)務(wù)邏輯等都是放到didmountMount,但是后期改需求,可能要用react-router進行跳轉(zhuǎn),可能要改的邏輯就會很多了,所以函數(shù)抽離出來,需求更新就少改一點代碼。 如果還不確定如何劃分函數(shù)的細粒度,我有個建議。使用過兩次以上的代碼,要抽離組件或者函數(shù),兩次的可以不用
45. if else 等判斷太多了,后期難以維護。
個人覺得if else 嵌套深看起來也不會太難受,難受的是,項目迭代久之后,自己都忘記曾經(jīng)寫過這些代碼,而且類型多或者不確定有什么類型,是否后期還會加的情況下,改起來就非常復(fù)雜了,而且很容易踩坑和背鍋。 用配置取代if嵌套,大概就是抽離一個config.ts出來,里面放一些配置。
例如你的業(yè)務(wù)代碼里面,會根據(jù)不同url參數(shù),代碼會執(zhí)行不同的邏輯./info?type=wechat&uid=123456&const qsObj = qs(window.location.url)const urlType = qsObj.type// bad if (urlType === 'wechat') { doSomeThing()} else if () { doSomeThing()} else if () { doSomeThing()} else if () { doSomeThing()}// good config.tconst urlTypeConfig: Record = { 'wechat': { // key 就是對應(yīng)的type name: 'wechat', show: ['header', 'footer', 'wechat'] // 展示什么,可能是異步的 pession: ['admin'], // 權(quán)限是什么,可能是異步的 }, 'zhifubao': { // key 就是對應(yīng)的type name: 'zhifubao', show: ['header', 'footer', 'zhifubao'] // 展示什么,可能是異步的 pession: ['admin'], // 權(quán)限是什么,可能是異步的 },}// 業(yè)務(wù)邏輯const qsObj = qs(window.location.url)const urlType = qsObj.typeurlTypeConfig.forEach(item => { if(urlType === item.type) { doSomeThing(item.show) }})復(fù)制代碼46. 不要使用renderXXX,要使用函數(shù)式組件
發(fā)現(xiàn)團隊一些小伙伴為了減少render函數(shù)里面的代碼量,會把一些元素拆分到函數(shù)里面。
// bad renderHeader = () => { return ( renderHeader() renderBody() renderFooter() ) }復(fù)制代碼更好的辦法,是用函數(shù)式組件取代在當(dāng)前組件里面寫方法
// good function RenderHeader(props) = { return ({ render () { return(47. a標(biāo)簽安全問題
使用a標(biāo)簽打開一個新窗口過程中的安全問題。新頁面中可以使用window.opener來控制原始頁面。如果新老頁面同域,那么在新頁面中可以任意操作原始頁面。如果是不同域,新頁面中依然可以通過window.opener.location,訪問到原始頁面的location對象
在帶有target="_blank"的a標(biāo)簽中,加上rel="noopener"屬性。如果使用window.open的方式打開頁面,將opener對象置為空。
var newWindow = window.open();newWindow.opener = null;復(fù)制代碼48. void 0 替代undefined
clearSessioin = () => { req.session.userName = undefined; req.session.userName = void 0}復(fù)制代碼49. 前端不要操作cookie
在做一些前后端鑒權(quán)的時候,后端應(yīng)該開啟domain,secure,httponly嚴格模式,禁止前端操作cookie,防止csrf攻擊。
50. 代碼檢查插件
我們可以使用構(gòu)建工具繼承 husky eslint tslint lint-stage prettier來規(guī)范代碼。
- eslint-config-prettier
- eslint-plugin-prettier
- eslint-plugin-react
- tslint-react
- tslint-plugin-prettier
- tslint-config-prettier
- 團隊開發(fā)工作流
參考
- airbnb
- imweb代碼規(guī)范
- 如何無痛降低 if else 面條代碼復(fù)雜度
- 你真的理解setState嗎?
來源鏈接:https://juejin.im/post/5ce24f8ae51d45106477bd45
總結(jié)
以上是生活随笔為你收集整理的react textarea 空格为什么不换行_你需要的 React + TypeScript 50 条规范和经验的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue-cli3使用cdn引入
- 下一篇: 用了十年的昵称badboy_怎样用5秒钟