前言
最近在寫一個項目,在寫react的過程中遇到過很多坑,現在總結一下,為以后的項目作參考.另外借此項目來比較一下 vue.js 和 react.js 之間的一些異同.
先說說組件
剛剛開始寫組件的時候,感覺難度不大(跟vue差不多)。最有意思的應該是jsx語法,個人感覺,jsx的功能性確實比vue的template更強,而且可讀性更高.
舉個栗子
// vue
<p :id="text" :class="{'active':isActive}" v-text="'hello! ' + msg"></p>
// jsx
<p id={text} className={isActive && 'active'}>hello !{msg}</p>
- 在jsx里面沒有指令,而且jsx里面
{}
代表要執行的js語句,它的效果類似return
,它會有返回值.這樣的話,更好理解jsx的內容,jsx里面的dom不是真正的dom,只是一種表示dom的語法,{}
里面的內容可以完全理解為js,這種整個jsx就可以完成理解為原生js寫的html模版. - 屬性計算的部分,vue里面需要在屬性名前面加
:
,在jsx里面則不需要. - 另外,在vue里面的dom的
contentText
不使用{{}}
來渲染,使用因為在vue頁面生成之前,模版語法部分沒有渲染出來,就會在頁面上先出現{{content}}
,再一閃變成真正的文本內容.
再舉個數組遍歷渲染的栗子
// vue
<ul><li v-for="(item,index) in list" :key="index" v-if="showItem(item)"><span v-text="item.label"></span></li>
</ul>// vue的methods屬性
methods:{showItem(item){return item.label.indexOf('abc') !== -1}
}
// jsx
<ul>{list.map((item,index) => {return item.label.indexOf('abc') !== -1 && (<li key={index}><span>{item.label}</span></li>)})}
</ul>
你會發現,在一些比較簡單渲染需求時,使用vue的template會比較簡單直接,而且很易懂.但是如果涉及一些比較復雜的邏輯處理渲染,jsx更直觀,因為jsx的語法跟js的差異不大,相當于用js來描述需要如何渲染dom結構.當然jsx并不是說可以完成使用js的語法來寫dom,{}
里面只能是一個表達式,所以像if else
或者switch
這種語法在{}
是不能用的.
redux
在寫redux的時候,不是很習慣。后來慢慢的去適應。由于還用到了saga
,以至于書寫方法上與redux官方的推薦的有所不同。
'action type'定義的不同類型。
- action ===> reducer
- action ===> saga ===> reducer
第一種情況:觸發action
之后直接commit一個reducer
。
// action
{type:'do/update-some-data',payload}
第二種情況,觸發的action
會被saga
攔截,然后saga
完成一定的操作后(一般是從后臺獲取數據);put
一個action
,作用到reducer
。
// saga action
{type:'start/get-some-data',payload}// reducer action
{type:'success/get-some-data',payload}
{type:'failed/get-some-data',payload}
{type:'error/get-some-data',payload}
一些代碼書寫規范
因為以前在寫代碼的時候一直都沒有確定好一個規范,導致代碼風格一直有變化(已經被同事吐槽好幾次了)。后來在這個項目里面看了其他的同事的代碼再結合網上推薦的一些代碼規范,目前總結出一些小心得(也不算什么心得)。
1.還是從組件開始
- 組件注釋
- 模塊引入
- 內部方法
- 組件類定義
- redux select
- export
1.注釋的問題我個人一直都重視的,一份好的注釋可以讓別人在開始看代碼之前就能對內容有一個大概清晰的了解。
/*** @name:組件名稱* @author:誰維護的* @version:2017-12-28 日期或者版本號* @description:描述* 你會發現沒有’param‘,這個部分在組件定義的地方會提到。*/
這些只是基本的信息,還可以添加其他你想加的內容。
2.模塊引入的部分一般有這些分類
- 依賴。例如庫或者插件
- 子組件
- 資源文件。例如默認的圖標或者背景圖什么的。
3.內部方法
內部方法一般是針對該組件需要的功能而定義的,而且不想跟類一起export出去。比如,組件里拿到后臺的一個對象數組,需要根據這個數組的信息計算出一個值,然后在組件中使用。
如果這個方法在多個組件中使用到的話,還可以把它提到utils
文件夾中。
4.組件定義
一般情況下,組件都會使用類來定義。比如:
class MyComponent extends Component{static defaultProps = {a:0,b:1}constructor(props) {super(props)this.state = {c:2,d:3}}handleClick = () = >{// some stuff}render() {const {a,b} = this.propsconst {c,d} = this.stateconst e = falsereturn(<div><div a={a} b={b}></div><div {...{a,c}}></div><div {...this.props} {...this.state}></div>e && {<div>some code</div>}</div>)}
}
首先,為啥子要寫defaultProps
?我覺得,有兩點:
- 知道在使用這個組件的時候,應該傳入哪些參數,都有什么意義。這樣比在組件頭注釋寫更具體。
- 設置默認值,避免使用時沒有傳參,導致一些bug。
state
就略過了。
類的方法。這里使用了箭頭函數
來定義,主要是為了使用this
,因為大多數情況下,handle里面都會調用this.setState
,這樣寫就不需要去constructor
一個個bind(this)
了。其實如果方法里面沒有使用指向類的this
,用函數定義的方式也是可以的。
render部分。我一般習慣將使用到的props
和state
以及其他的數據全部在return
前定義出來。這樣會更清晰明白組件里面使用了哪些數據。
另外是給元素設置屬性的一些小技巧。平時最常用的方式是這樣的key={value}
,還可以使用對象解構的方式設置屬性。
redux seletct & export
說到redux
一定要扯上vuex
(看完下面的內容,如果有不同意見的戰友,請不要打我)。
這里先從組件部分來看一下redux
和vuex
的區別。在組件里面主要是看如何讓當前組件使用到store
中的數據和方法。
// react
import React, { Component } from 'react'
import { connect } from 'react-redux'
import * as actions from '../actions'
import { bindActionCreators } from 'redux'class MyComponent extends Component{}function mapStateToProps(state){return {...state,stateOne:state=>state.stateOne,stateTwo:state=>state.stateTwo}
}
functino mapDispatchToProps(dispatch){return {...bindActionCreators(actions,dispatch),handleOne:(arg)=>dispatch(actions.handleOne(arg)),handleTwo:(arg)=>dispatch(actions.handleTwo(arg))}
}export connect(mapStateToProps,mapDispatchToProps)(MyComponent)
react里面要使用connect
方法把state和dispatcher和當前組件連接起來.
// vueimport { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('theModule')export default {computed:{...mapState(['stateOne','stateTwo']),...mapState({stateThree:state=>state.theModule.stateThree,stateFour:state=>state.theModule.stateFour})},methods:{...mapActions(['handleOne','handleTwo']),...mapActions({handleThree:'actionThree',handleFour:'actionFour'})}
}
在vue里面也有相應的輔助函數,而且vuex的store
包含來數據和方法,在根組件注入之后,所有的子組件都可以通過this.$store
使用,輔助函數只是用來過濾而已.
待續...