<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          拆解高頻面試題:你是如何理解單向數(shù)據(jù)流的?

          共 5546字,需瀏覽 12分鐘

           ·

          2021-09-11 10:51

          這是一道高頻面試題,也是我們 React 入門系列中需要重點(diǎn)理解的內(nèi)容。


          回憶一下 React 入門前五步:

          React 入門第一步:環(huán)境搭建

          React 入門第二步:搞懂 JSX 語法

          React 入門第三步:了解組件的概念及應(yīng)用

          React 入門第四步:組件間的值傳遞 Props

          React 入門第五步:組件布局小案例


          今天的主要內(nèi)容是組件狀態(tài)。


          狀態(tài)可以簡單的理解為數(shù)據(jù),與 props 類似,但是 state 是私有的,并且完全受控于當(dāng)前組件,因此組件狀態(tài)指的就是一個(gè)組件自己維護(hù)的數(shù)據(jù)。


          上篇我們也提到了一個(gè)非常重要的點(diǎn):數(shù)據(jù)驅(qū)動(dòng)UI。意思也很簡單,就是頁面所展示的內(nèi)容,完全是受狀態(tài)控制的,這也就是所謂 MVVM 的理念。UI 的改變,全部交給框架本身來做,我們只需要管理好 “數(shù)據(jù)(狀態(tài))” 就可以了。


          那么在 React 中,如何對(duì)狀態(tài)進(jìn)行管理呢?這就是本章節(jié)的重點(diǎn),也是整個(gè) React 學(xué)習(xí)的重點(diǎn):組件的狀態(tài)管理。


          基本使用

          state 的使用是非常簡單的,我們?cè)陬愔新暶饕粋€(gè)名為 state 的對(duì)象,對(duì)象中的元素就是當(dāng)前組件所維護(hù)的狀態(tài)數(shù)據(jù),獲取展示數(shù)據(jù)時(shí),只需要在 jsx 中,使用 this.state.xx 的方式獲取就可以了。

          import React, { Component }from'react'
          exportclass States extends Component { // 聲明 state 對(duì)象 state = { name:'xiling', age:18 }
          render() { return ( <> <h2>state 狀態(tài)</h2> {/* 使用 this.state.xx 獲取數(shù)據(jù) */} <p>{this.state.name}</p> <p>{this.state.age}</p> </> ) }}
          exportdefault States


          前面我們說,state 數(shù)據(jù)是可以控制界面的,那么我們?nèi)绾涡薷?state 從而讓界面發(fā)生改變呢?


          修改狀態(tài)

          想要修改 state 的值,最直觀的方式就是直接使用 this.state={} 的方式直接修改。我們?cè)O(shè)置一個(gè)按鈕,當(dāng)點(diǎn)擊按鈕時(shí),通過 this.state={} 發(fā)現(xiàn)是不起作用的,那應(yīng)該怎么做呢? 


          React 給我們提供了專門的 this.setState({}) 方法,我們需要調(diào)用 this.setState({}) 方法將需要修改的數(shù)據(jù)傳入才能正確的修改 state 的值。


          至于為什么,需要我們理解 React 數(shù)據(jù)流才能搞懂,這里就不再詳細(xì)介紹,你只需要記住這個(gè)規(guī)則就可以了。

          import React, { Component }from'react'
          exportclass States extends Component { // 聲明 state 對(duì)象 state = { name:'xiling', age:18 }
          // 箭頭函數(shù) changes = ()=>{ // console.log(22) // this.state.name = 'xiling' // 錯(cuò)誤的使用方式 this.setState({name:'西嶺'}) }
          render() { return ( <> <h2>state 狀態(tài)</h2> {/* 使用 this.state.xx 獲取數(shù)據(jù) */} <p>{this.state.name}</p> <p>{this.state.age}</p> <buttononClick={this.changes}>改變state</button> </> ) }}
          exportdefault States


          一旦 state 的值發(fā)生了改變,那么 JSX 中使用 state 的地方就會(huì)自動(dòng)發(fā)生改變。


          這里也需要注意一點(diǎn),因?yàn)?setState 方法是類中的屬性(方法),我們需要使用 this 進(jìn)行獲取,因此,事件綁定的處理函數(shù)就需要使用箭頭函數(shù)來固定 this 的指向,一定不要使用普通的函數(shù) (類方法) 聲明,否則會(huì)因?yàn)檎也坏椒椒ǘ苯訄?bào)錯(cuò)

           

          自頂向下的單向數(shù)據(jù)流

          關(guān)于數(shù)據(jù)流的問題,是面試中高頻次出現(xiàn)的典型題目,一般情況下面試官會(huì)直接問:“你是如何理解單向數(shù)據(jù)流的 ? ”。


          注意,這不是一個(gè)單獨(dú)的個(gè)體問題,而是數(shù)據(jù)流問題的綜合體。解答這個(gè)問題,你需要解釋:


          什么是數(shù)據(jù)流?

          為什么是自頂向下的?

          單向數(shù)據(jù)流是什么意思?

          為什么是單向的?不能是雙向的數(shù)據(jù)流嘛?

          單向數(shù)據(jù)流有什么作用呢?


          面試題一旦拆開,你會(huì)發(fā)現(xiàn)面試官問出來的幾乎每一個(gè)詞都需要解釋。寶兒,這個(gè)問題,真不簡單啊!


          那么,我應(yīng)該怎么解答呢?


          說實(shí)話,并沒有標(biāo)準(zhǔn)答案,因?yàn)閿?shù)據(jù)流這個(gè)問題,涉及到了框架本身的設(shè)計(jì)理念,需要你對(duì)框架的設(shè)計(jì)有深入理解,你要站在框架作者的角度看待問題;但是,對(duì)于初學(xué)者來說,這個(gè)問題顯然超綱了。


          完?duì)僮?,那么重要,我又學(xué)不了是嘛?不是,你需要學(xué)很多遍,這只是第一遍。


          開始之前,我們先來看一段普通的 JS 代碼:

          var datas = {  name:'lisi',  age:18}
          var l1 = datasvar l2 = l1var l3 = l2
          l1.age=20console.log(l1.age,l2.age,l3.age) // 20 20 20
          l3.age=26console.log(l1.age,l2.age,l3.age) // 26 26 26


          你會(huì)發(fā)現(xiàn),無論我們是修改那個(gè)變量的 age 屬性,其他數(shù)據(jù)都會(huì)跟著改變,原因也很簡單,大家都是共享一個(gè)內(nèi)存數(shù)據(jù)的。


          但是,賦值的前后邏輯上,我們可以將 L3 節(jié)點(diǎn)看作孫子,L2 節(jié)點(diǎn)看做父親,L1 節(jié)點(diǎn)看做爺爺。



          任意一個(gè)節(jié)點(diǎn)的數(shù)據(jù)改變之后,所有節(jié)點(diǎn)的數(shù)據(jù)都會(huì)跟著改變,我們就可以把這種現(xiàn)象看做是數(shù)據(jù)在“變量節(jié)點(diǎn)”上的流動(dòng)。


          但是,這樣的數(shù)據(jù)流動(dòng),是雙向的,拿 L2這個(gè)節(jié)點(diǎn)來說,只要數(shù)據(jù)改變,上層的 L1 節(jié)點(diǎn)和下層的 L3 節(jié)點(diǎn)都會(huì)跟著改變。


          雖然這個(gè)例子并不恰當(dāng),但是回到 React 組件中,道理是一樣的,所謂數(shù)據(jù)的流動(dòng)就是數(shù)據(jù)在組件間的傳遞。前面我們用了很大的篇幅講解的組件間的值傳遞,其實(shí)就是在講數(shù)據(jù)流這個(gè)概念的具體用法。


          那么,我們?cè)跀?shù)據(jù)流前面加上一個(gè)“單向”的定語,叫 “單向數(shù)據(jù)流” 是什么意思呢?其實(shí)現(xiàn)在你理解起來很簡單,就是數(shù)據(jù)在某個(gè)節(jié)點(diǎn)被改變后,只會(huì)影響一個(gè)方向上的其他節(jié)點(diǎn)。


          那所謂的自頂向下又怎么解釋呢?


          更簡單了,就是
          數(shù)據(jù)只會(huì)影響到下一個(gè)層級(jí)的節(jié)點(diǎn),不會(huì)影響上一個(gè)層級(jí)的節(jié)點(diǎn)。用上面的例子解釋,就是如果 L2 數(shù)據(jù)改變,只會(huì)影響到 L3,不會(huì)影響到 L1 或者其他節(jié)點(diǎn)。


          這就是 “自頂向下的單向數(shù)據(jù)流”。那么我們?cè)?React 框架中,就可以明確定義單向數(shù)據(jù)流:規(guī)范數(shù)據(jù)的流向,數(shù)據(jù)由外層組件向內(nèi)層組件進(jìn)行傳遞和更新。


          那么,在具體的代碼實(shí)現(xiàn)中,是怎么體現(xiàn)出來的呢?翠花,上代碼:



          圖有點(diǎn)看不清,接下來,我們看具體代碼的演示:

          // ========== App============import React, { Component } from'react'import C1 from'./C1'exportclass App extends Component {  state = {    name:"xiling"  }  render() {    return (      <div>        <h1>App</h1>        <p> APP 中的值:          <bstyle={{ color:"red" }}>            {this.state.name}          </b>        </p>        <C1toC1={this.state.name}></C1>      </div>    )  }}
          exportdefault App

          // ========== C1 ============import React, { Component } from'react'import C2 from'./C2'exportclass C1 extends Component {

          render() { return ( <div> <h2>C1</h2> <p>傳入C1 的值(App傳入): <bstyle={{ color:"red" }}> {this.props.toC1} </b> </p> <C2toC2={this.props.toC1}></C2> </div> ) }}
          exportdefault C1

          // ========== C2 ============import React, { Component } from'react'import C3 from'./C3'exportclass C2 extends Component {
          state = { name:this.props.toC2 }
          changes = () => { this.setState({ name:Math.random() }) }
          render() { return ( <div> <h2>C2</h2> <buttononClick={() => { this.changes() }}> 修改 </button> <p>傳入C2 的值(C1傳入): <bstyle={{ color:"red" }}> {this.state.name} </b> </p> <C3toC3={this.state.name}></C3> </div> )
          }}
          exportdefault C2

          // ========== C3 ============import React, { Component } from'react'
          exportclass C3 extends Component { render() { return ( <div> <h2>C3</h2> 傳入C3 的值(C2傳入): <bstyle={{ color:"red" }}> {this.props.toC3} </b> </div> ) }}
          exportdefault C3


          最后,我們?cè)賮斫忉?,為什么?有什么用?/span>


          其實(shí)這才是這個(gè)問題的核心,不同的技術(shù)理解,就會(huì)有不同的角度解釋,我這里僅一家之言,你且聽聽罷。


          我們?cè)O(shè)想這樣的情景:

          父組件的數(shù)據(jù)通過props傳遞給子組件,而子組件里更新了 props,導(dǎo)致父組件和其他關(guān)聯(lián)組件的數(shù)據(jù)更新,UI 渲染也會(huì)隨數(shù)據(jù)而更新。


          毫無疑問,這是會(huì)導(dǎo)致嚴(yán)重的數(shù)據(jù)紊亂和不可控。


          因此絕大多數(shù)框架在這方面做了處理。而 React 在這方面的處理,就是直接規(guī)定了 Props 為只讀的,而不是可更改的。這也就是我們前面看到的數(shù)據(jù)更新不能直接通過 this.state 操作,想要更新,就需要通過 React 提供的專門的 this.setState() 方法來做。


          單向數(shù)據(jù)流其實(shí)就是一種框架本身對(duì)數(shù)據(jù)流向的限制。


          暫時(shí)先說這些吧,等我們學(xué)的越多,經(jīng)驗(yàn)越豐富,對(duì)它的理解也就會(huì)越深刻,看待它的角度也就越全面。


          掰~


          推薦閱讀:

          Vite 的插件機(jī)制:插件應(yīng)用和基本使用

          騰訊小程序開發(fā):如何培養(yǎng)組件化思維?

          前端工程化到底是什么?


          恭喜你又在前端道路上進(jìn)步了一點(diǎn)點(diǎn)。

          點(diǎn)個(gè)“在看”和“”吧!

          瀏覽 69
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲a视频在线 | 超碰人人人人操 | 黑丝空姐在线观看视频 | 四虎国产成人永久精品免费 | a人片日本亚洲 |