成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

理解了狀態管理,就理解了前端開發的核心?

開發 前端
狀態就是數據的變化。前端應用的核心問題就是管理狀態,管理狀態變化之前的通過視圖或者其他方式觸發的異步過程,管理狀態變化之后的聯動渲染和聯動的邏輯執行。

狀態管理是前端整天遇到的概念,但是大家是否思考過什么是狀態,管理的又是什么呢?

我們知道,程序是處理數據的,數據是信息的載體,比如顏色是紅色或藍色這就是數據。

那為什么不叫數據管理呢?狀態和數據是什么關系?

什么是狀態

狀態是數據的變化,比如顏色是紅色或藍色是數據,而顏色從紅色變為藍色這就是狀態了。

狀態的改變對應著視圖的渲染或者某段邏輯的執行。比如顏色從紅色變為藍色可能就要重新渲染視圖,并且執行發送請求到服務端的邏輯。

通過視圖交互或者其他方式觸發狀態的變化,狀態變化聯動視圖的渲染和邏輯的執行,這就是前端應用的核心。

為什么之前 jQuery 時代沒咋聽說狀態管理的概念,而 Vue、React 時代經常聽到呢?

jQuery 時代是手動把數據渲染到視圖和執行數據變化之后的邏輯的,它可能沒有明確的狀態這一層,而是直接把數據渲染成 dom,下次需要數據也是從 dom 來取的。

而 Vue、React 前端框架的時代不需要手動操作 dom 和執行數據變化之后的邏輯,只要管理好狀態,由前端框架負責狀態變化之后的處理。

狀態管理管理的是什么呢?

什么是狀態管理

狀態管理具體有兩層含義:

  • 狀態變化之前的邏輯,一般是異步的。
  • 狀態變化之后的聯動處理,比如渲染視圖或執行某段邏輯。

比如 React 的 setState 不會馬上修改狀態,而是異步的批量的執行,把狀態做一下合并。

比如 Redux 的 action 在修改全局 state 之前也是要經歷中間件的處理的。

這些都是狀態變化之前的異步過程的管理,是狀態管理的第一層含義。

再比如 React setState 修改了狀態之后要觸發視圖的渲染和生命周期函數的執行,hooks 在依賴數組的狀態變化之后也會重新執行。(vue 的 data 修改之后會重新渲染視圖、執行 computed 和 watch 邏輯)

Redux 修改了全局狀態之后要通知組件做渲染或者做其他邏輯的處理,Vuex、Mobx 等都是。

這些是狀態變化之后的聯動處理的管理,是狀態管理的第二層含義。

我們知道了什么是狀態,什么是狀態管理,那前端框架 Vue、React 和全局狀態管理的庫 Redux、Mobx、Vuex 都是怎么實現狀態管理的呢?

狀態管理的兩種實現思路

狀態不會是一個,多個狀態的集合會用對象的 key、value 來表示,比如 React 的 state 對象,Vue 的 data 對象(雖然叫 data 也是指的狀態)。

怎么監聽一個對象的變化呢?

我們是不是可以提供一個 api 來修改,在這個 api 內做 state 變化之前的處理,并且在 state 變化之后做聯動處理。

這樣的方案只能通過 api 觸發狀態修改,直接修改 state 是觸發不了狀態管理邏輯的。

React 的 setState 就是這種思路,通過 setState 修改狀態會做狀態變化之前的批量異步的狀態合并,會觸發狀態變化之后視圖渲染和 hooks、生命周期的重新執行。但是直接修改 state 是沒用的。

那怎么讓直接修改狀態也能監聽到變化呢?

可以對狀態對象做一層代理,代理它的 get、set,當執行狀態的 get 的時候把依賴該狀態的邏輯收集起來,當 set 修改狀態的時候通知所有依賴它的邏輯(視圖渲染、邏輯執行)做更新。

Vue 的 data 監聽變化就是用的這種思路,在狀態 get 的時候把依賴封裝成 Watcher,當 set 的時候通知所有 Watcher 做更新。

這種思路叫做響應式(reactive),也就是狀態變化之后自動響應變化做聯動處理的意思。

代理 get、set 可以用 Object.defineProperty 的 api,但是它不能監聽動態增刪的對象屬性,所以 Vue3 改為了用 Proxy 的 api 實現。

監聽對象的變化就這兩種方式:

  • 提供 api 來修改,內部做聯動處理。
  • 對對象做一層代理,set 的時候做聯動處理,通知 get 時收集的所有依賴。

前端框架狀態變化的性能優化

但是頻繁的修改 state 不是每次都要做聯動處理,有一些可以合并的,比如兩次都把顏色改為紅色,那后續邏輯就沒必要執行兩次,需要再做些性能方面的優化。

所以 React 的 setState 是異步的,會做批量的 state 合并(注意,React 的 setState 傳入的不是最終的 state,而是 state 的 diff,React 內部去把這些 diff state 更新到 state)。

而 Vue 因為是直接修改的同一個對象,所以沒必要做啥合并,它的 Watcher 執行是異步的,對多次放到隊列里的 Watcher 做下去重就行了。

組件間的狀態管理

組件內的狀態管理就是這樣的,利用前端框架自帶的 state 機制來管理。

那組件之間呢?一個組件的 state 變了如何聯動其他組件變化?

props

通過 props,把當前組件的 state 作為 props 傳入其他組件就行了,這樣就能聯動變化。

但是 props 只能一層層傳遞,如果組件和想聯動變化的組件相隔很多層,傳遞 props 就很麻煩。

這種情況下前端框架也都提供了解決方案,React 提供了 Context、Vue 提供了 Event Bus。

Context、Event Bus

React 組件可以在 context 中存放 state,當 context 中的 state 變化的時候會直接觸發關聯組件的渲染。

Vue 可以在一個組件內 emit 一個事件,然后另一個組件 on 這個事件,然后更新自己的 data 來觸發渲染。不過這兩個 api 在 Vue3 都廢棄了。

這種前端框架自帶的任意層組件的狀態聯動方案只能處理簡單的場景,復雜的場景還是得用全局狀態管理庫,比如 Redux、Vuex、Mobx 這些。

為什么這么說呢?

還記得狀態管理的兩層含義么?狀態變化前的異步過程的管理,狀態變化后的聯動處理。

Context 和 Event Bus 都只做到了狀態變化后的聯動處理,但是沒有對狀態變化前的異步過程管理做支持。

比如多個組件都要修改 context 中的值(或者通過 event bus 修改全局狀態),這個過程都要執行一段異步邏輯,要做 loading 的展示,那多個組件里怎么復用這段 loading 的邏輯呢?

還有,如果異步過程比較麻煩,需要用 rxjs 這樣的庫,用 context 和 event bus 的方案怎么和 rxjs 結合呢?

當然,是可以對 context 和 event bus 做一些邏輯復用的封裝和一些結合 rxjs 方案之類的封裝的,但是比較麻煩。

而且更重要的是如果你想做這些的時候,那也就沒必要用 context 和 event bus 了,直接用全局狀態管理庫就行。

Redux、Mobx、Vuex

redux 就提供了中間件的機制,組件里發送 action 到 store(存放全局 state 的地方),之前會經歷層層中間件的處理,在這里就可以做一些可復用的邏輯的封裝,比如 loading 的處理,也可以結合 rxjs 這種異步過程處理方案。

redux 里最常用的中間件就是 redux-saga 和 redux-observable 了,這倆都是做異步過程的管理的。

redux-saga 是基于 generator 實現的,不管是同步還是異步,都只要聲明式的描述要執行的邏輯就行,由 saga 內部的執行器會去做同步或異步的處理,描述異步邏輯就很簡潔,而且 redux-saga 提供了很多內置的邏輯封裝。

redux-observable 則是結合 rxjs 的方案了,把 action 變成數據源,經歷層層 opreator 的處理,最后傳遞到 store??梢杂?rxjs 生態大量的 oprator,做下組裝就行,根本不用自己寫異步邏輯的具體實現。

vuex 也同樣支持中間件機制。

mobx 沒有提供中間件機制,它的 action 是執行狀態 class 的某個方法,可以用 class 的那套來做封裝。

有的同學對這些狀態管理庫不太熟,簡單來介紹下。

我們理清了狀態管理的實現只有兩種方案,一種是提供 api 做修改,一種是對 state 對象做響應式代理。

前端框架的狀態管理是這樣,獨立的全局狀態管理庫也同樣是這樣。

redux 就是提供 api 來修改的方案,通過 reducer 函數來對傳入的 action 做處理,返回新的 state。

而且 redux 這種思路是函數式的思想,每個 reducer 都是輸入和輸出一一對應的純函數,返回的 state 都是全新的,為了方便創建新的 state,一般會搭配 immutable 庫,只要修改屬性就會返回新的 state 對象。

mobx 是響應式代理的方案,它對全局 state 做了一層代理(通過 Object.defineProperty),狀態的 get 收集依賴,set 的時候觸發依賴更新。

所以這種方案很自然的可以把全局 state 組織成一個個 class,是面向對象的思想,可以通過繼承等方式實現邏輯復用。

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {observer} from 'mobx-react';

@observer
class TodoListView extends Component {
render() {
return <div>
<ul>
{this.props.todoList.todos.map(todo =>
<TodoView todo={todo} key={todo.id} />
)}
</ul>
Tasks left: {this.props.todoList.unfinishedTodoCount}
</div>
}
}

const TodoView = observer(({todo}) =>
<li>
<input
type="checkbox"
checked={todo.finished}
onClick={() => todo.finished = !todo.finished}
/>{todo.title}
</li>
)

const store = new TodoList();
ReactDOM.render(<TodoListView todoList={store} />, document.getElementById('mount'));

vuex 則像是兩種思路的結合,內部是用響應式代理來實現的變化監聽,但是暴露出的 api 卻是 redux 的 action 那一套。

和 React 搭配使用的話,需要把組件添加到狀態的依賴中,這個不用自己調用 subscribe 之類的 api,直接用一些封裝好的高階組件(接受組件作為參數返回新的組件的組件)就行,比如 react-redux 的 connect,mobx-react 的 observer。

總結

講了這么多,回過頭來看一下就會發現:

不管是前端框架內置的組件內狀態變化管理的方案(react 的 setState、vue 的直接修改 data),還是前端框架提供的組件間的狀態管理方案(props、react 的 context、vue 的 event bus),或是第三方的全局狀態管理方案(redux、vuex、mobx 等),都沒有脫離那兩種實現狀態管理的方式:提供修改狀態的 api 或者對狀態對象做一層響應式代理。也沒有脫離狀態管理的兩層含義:對狀態變化前的異步過程做管理,狀態變化后做聯動處理。只不過它們用在了不同的地方(前端框架內、全局狀態管理庫),提供了不同的封裝形式(對象、函數),基于不同的思想(函數式、面向對象)結合了不同的異步管理方案(rxjs、generator + 自定義執行器)。

所以,狀態就是數據的變化。前端應用的核心問題就是管理狀態,管理狀態變化之前的通過視圖或者其他方式觸發的異步過程,管理狀態變化之后的聯動渲染和聯動的邏輯執行。

雖然我們會用不同的前端框架,不同的全局狀態管理庫,結合不同的異步過程處理方案,但是思想都是一樣的。

毫不夸張地說,理解了狀態管理,就理解了前端開發的核心。

責任編輯:武曉燕 來源: 神光的編程秘籍
相關推薦

2020-04-16 10:55:03

Java虛擬機字節碼

2022-03-27 09:06:25

vuexActionsMutations

2019-09-29 06:12:38

交換機配置vlan

2024-03-15 08:23:26

異步編程函數

2019-12-26 09:15:44

網絡IOLinux

2012-11-30 11:19:02

JavaScript

2024-11-25 07:39:48

2022-10-20 18:43:32

C語言golang安全

2018-03-21 16:19:40

MVCMVPMVVM

2022-07-27 22:59:53

Node.jsNest

2019-09-16 08:32:59

遞歸算法編程

2019-09-18 10:12:37

遞歸數據結構

2021-09-07 07:55:22

Linux CPULinux 系統

2022-11-26 00:22:14

引用類型數組

2022-08-05 13:03:09

Python依賴管理代碼

2019-05-28 09:40:39

TCP協議socket接口

2019-05-17 09:02:19

TCP協議服務端

2022-02-21 07:45:29

面向對象代碼依賴倒置

2021-03-19 07:59:33

紅黑樹面試數據

2020-11-09 14:30:28

Linux多線程數據
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲一区二区久久 | 天天干天天爱天天爽 | 欧美一级观看 | 亚洲综合在线网 | 91一区二区 | 国产一区欧美一区 | 国产成人精品网站 | 成人午夜免费视频 | 红桃视频一区二区三区免费 | 中文字幕一区在线观看视频 | 亚洲免费久久久 | 国产精品亚洲综合 | 99久久久99久久国产片鸭王 | 日产久久 | 国产精品久久久久久久久久久免费看 | 亚洲综合在线视频 | 亚洲精品日韩欧美 | 天天操网| 日韩精品免费播放 | 亚洲一区视频在线 | 亚洲国产精品99久久久久久久久 | 国产视频福利一区 | 91久久综合 | 亚洲成人一区 | 亚洲成人午夜在线 | 精品亚洲一区二区三区 | 午夜看看 | 99精品在线 | 亚洲视频一区 | 国产精品免费一区二区三区 | 一区二区三区福利视频 | 欧美高清性xxxxhd | 国产九九精品 | 国产视频二区在线观看 | 中文字幕av中文字幕 | 色999日韩 | 国产欧美一区二区精品久导航 | 中文字幕欧美一区 | 成在线人视频免费视频 | 色综合久 | 男女深夜网站 |