使用React改版網(wǎng)站后的一些感想

網(wǎng)站是畢業(yè)設(shè)計(jì)的作品,開(kāi)發(fā)這個(gè)網(wǎng)站的目的主要用于記錄一些筆記,以及聚合一些資訊信息,也算自己在網(wǎng)絡(luò)世界中的一塊靜地吧,可以在這里一些技術(shù)上想法的實(shí)踐。

網(wǎng)站最初前端使用vue開(kāi)發(fā),在前段時(shí)間由于項(xiàng)目的開(kāi)發(fā)進(jìn)度已經(jīng)不是那么緊急,有了一些空閑時(shí)間。而對(duì)沒(méi)有使用過(guò)React又一直耿耿于懷,索性就使用React進(jìn)行了一次前端的重構(gòu)。

學(xué)習(xí)一門新的技術(shù)最基本的當(dāng)然就是閱讀相關(guān)文檔了,作為一個(gè)單頁(yè)面應(yīng)用前端路由當(dāng)然是不可能少了,而使用React如果不使用Reduce那又感覺(jué)發(fā)揮不其作用(雖然他們其實(shí)也沒(méi)什么必須的關(guān)系)。所以在這里使用了react,react-router,react-redux,以下為在使用React開(kāi)發(fā)中的一些見(jiàn)聞,有幸被你看到該文,如有不對(duì)之處,還望指出,如果你不小心被帶入坑,本人概不負(fù)責(zé)。

首先就是閱讀React的文檔了,文檔使用大量舉例的形式介紹如何使用React進(jìn)行開(kāi)發(fā),如如何設(shè)計(jì)state,props,如何組件間通信,如何設(shè)計(jì)組件等。文檔雖然進(jìn)行了詳細(xì)的介紹,但是往往還是需要真正的實(shí)踐才能發(fā)現(xiàn)其中的妙處。如state,props的設(shè)計(jì),在一個(gè)X組件中擁有Y,Z兩個(gè)組件,假設(shè)Y組件擁有一個(gè)輸入框,而Z組件可能需要用到Y組件輸入的值做出一定的變化,當(dāng)然如果把他們寫到一起也不是不可以的,但是考慮到組件復(fù)用,功能單一等因素還是拆開(kāi)比較合理,那么這個(gè)值到底應(yīng)該哪個(gè)組件來(lái)儲(chǔ)存呢?如下兩個(gè)組件分別為Y,X,這樣設(shè)計(jì)明顯是不符合state設(shè)計(jì)的,擁有太多冗余部分。

class InputComponent extends Component {
  constructor () {
    super()
    this.state = {
      value: ''
    }
  }
  valInput (e) {
    let value =  e.target.value
    this.setState({value})
    this.props.inputChange(value)
  }
  render () {
    return <input onChange={this.valInput.bind(this)}/>
  }
}
class ParentComponent extends Component {
  constructor () {
    super()
    this.state = {
      val: ''
    }
  }
  inputChange (val) {
    this.setState({val})
  }
  render () {
    return (
      <section>
        {this.state.val}
        <InputComponent inputChange={this.inputChange.bind(this)}/>
      </section>
    )
  }
}

如果使用如下的寫法或許看起來(lái)更好

class InputComponent extends Component {
  render () {
    let {val, inputChange} = this.props
    // 這里的val并不是必須的,但是當(dāng)一個(gè)值來(lái)自非輸入控件的時(shí)候,如可編輯的div,ace在每次執(zhí)行render函數(shù)的時(shí)候都會(huì)導(dǎo)致原來(lái)輸入的值被清空。
    return <input value={val} onChange={inputChange}/>
  }
}
class ParentComponent extends Component {
  constructor () {
    super()
    this.state = {
      val: ''
    }
  }
  inputChange (e) {
    this.setState({val: e.target.value})
  }
  render () {
    let val = this.state.val
    return (
      <section>
        {val}
        <InputComponent val={val} inputChange={this.inputChange.bind(this)}/>
      </section>
    )
  }
}

?react-router提供了前端路由基本的需求,根據(jù)需要使用到的功能在項(xiàng)目文檔介紹中即可找到具體使用方法?;镜呐渲煤推渌蚣芤彩谴笸‘?,但是很多API的使用確有些大相徑庭(和vue相比),還是需要仔細(xì)通讀文檔的,以免在開(kāi)發(fā)中出現(xiàn)問(wèn)題再去解決浪費(fèi)時(shí)間,如IndexRoutevue中可以在子路由通過(guò)''這樣的空字符來(lái)作為默認(rèn)UI。

function root () {
  this.path = '/'
  this.component = require('pages/index').default
}
function demo () {
  this.path = 'demo'
  this.getComponent = (nextstate, cb) => {
    require.ensure([], (require) => {
      cb(null, require('pages/demo').default)
    })
  }
}
const createRoute = (R) => {
  let route = new R()
  route.childRoutes = route.childRoutes && route.childRoutes.map(r => createRoute(r))
  return route
}

export default [root, demo].map((route) => createRoute(route))

react-redux從表象理解Redux中進(jìn)行了簡(jiǎn)單介紹。Redux的使用減少了開(kāi)發(fā)中思考的時(shí)間,同時(shí)也避免了一些可能的問(wèn)題。在使用過(guò)程中也發(fā)現(xiàn)一些問(wèn)題,使用Redux必然導(dǎo)致大量的dispatch出現(xiàn)在組件中,如何防止業(yè)務(wù)變得復(fù)雜和龐大后導(dǎo)致項(xiàng)目變得難以維護(hù),也是值得思考的。在被改版的網(wǎng)站中使用頁(yè)面+組件的方式開(kāi)發(fā),一個(gè)頁(yè)面表示除了跟組件外的最高級(jí)組件,可擁有多個(gè)組件,只有頁(yè)面才能向reducer發(fā)起action,所有多個(gè)組件共用的數(shù)據(jù)則通過(guò)在頁(yè)面中傳遞到子組件的props,子組件如果需要更新數(shù)據(jù),則通過(guò)props屬性調(diào)用父組件傳入的方法向上傳遞命令,在頁(yè)面中使用dispath來(lái)指定action來(lái)調(diào)用reducer進(jìn)行數(shù)據(jù)更新,當(dāng)然有時(shí)候也需要在action中進(jìn)行處理后在dispath actionreducer(比如網(wǎng)絡(luò)請(qǐng)求)。值得注意的是每次dispath一個(gè)action,Redux都會(huì)遍歷所有已經(jīng)注冊(cè)的reducer(reducer往往由多個(gè)子reducer組成),也就是說(shuō)所有reducer都會(huì)被調(diào)用(從項(xiàng)目中的表現(xiàn)和文檔來(lái)看是這樣的),一下是被改版網(wǎng)站使用的reducer部分代碼。

export default class ArticleReducer {
  [AAS.ARTICLE_REQUEST_STATE] (state, action) {
    return Object.assign({}, state, {loading: action.loading})
  }
  [AAS.ARTICLE_SEARCH_STATE] (state, action) {
    return Object.assign({}, state, {searching: action.searching})
  }
}
const reducers = {}
const AR = new ArticleReducer()
const NR = new NewsReducer()
reducers.articles = (state = initState.article, action) => {
  return AR[action.type] ? AR[action.type](state, action) : state
}
reducers.editor = (state = initState.editor, action) => {
  return ER[action.type] ? ER[action.type](state, action) : state
}

就使用React后的感覺(jué),由于第一次真正使用Redux這樣的狀態(tài)管理工具來(lái)進(jìn)行進(jìn)行開(kāi)發(fā)(雖然也有使用vuex,但是都不是基于整個(gè)項(xiàng)目的),開(kāi)發(fā)流程變得更加可控,數(shù)據(jù)流向變得清晰,而在開(kāi)發(fā)中各個(gè)工具耦合性也變得更低,總的來(lái)說(shuō)這是一次不錯(cuò)的嘗試。不過(guò)個(gè)人覺(jué)得不管使用什么技術(shù),復(fù)雜程度隨著業(yè)務(wù)的增加必定變得更高,而要維持一個(gè)項(xiàng)目的穩(wěn)定,健壯,易于維護(hù)將變得更加困難。

最后不得不感嘆,良好編程習(xí)慣的重要性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容