摘要:但是如果多實例組件的含義明顯不具有通用性,特別是用于顯示數組元素的情況下,使用這種模式會引發多余的渲染過程。假設我們還有數組,數組元素的格式與一樣我們要用相同的元素組件來同時顯示和操作這兩個數組時,這種數組渲染模式就不適用了。
這是 Pastate.js 響應式 react state 管理框架系列教程的第三章,歡迎關注,持續更新。
這一章我們來看看在 pastate 中如何渲染和處理 state 中的數組。
渲染數組首先我們更新一下 state 的結構:
const initState = { basicInfo: ..., address: ..., pets: [{ id:"id01", name: "Kitty", age: 2 }] }
我們定義了一個有對象元素構成的數組 initState.pets, 且該數組有一個初始元素。
接著,我們定義相關組件來顯示 pets 的值:
class PetsView extends PureComponent { render() { /** @type {initState["pets"]} */ let state = this.props.state; return () } }My pets:{state.map(pet =>)}
class PetView extends PureComponent { render() { /** @type {initState["pets"][0]} */ let state = this.props.state; return () } }{state.name}: {state.age} years old.
這里定義了兩個組件,第一個是 PetsView,用來顯示 pets 數組; 第二個是 PetView,用來顯示 pet 元素。
接下來把 PetsView 組件放入 AppView 組件中顯示:
... class AppView extends PureComponent { render() { /** @type {initState} */ let state = this.props.state; return () } } ...
完成!我們成功渲染了一個數組對象,這與用原生 react 渲染數組的模式一樣,頁面結果如下:
修改數組首先,我們想添加或減少數組元素,這用 pasate 實現起來非常簡單。受 vue.js 啟發,pastate 對 store.state 的數組節點的以下7個 數組變異方法 都進行了加強,你可以直接調用這些數組函數,pastate 會自動觸發視圖的更新。這 7 個數組變異方法如下
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
我們來嘗試使用 push 和 pop 來更新數組:
class PetsView extends PureComponent { pushPet(){ state.pets.push({ id: Date.now() + "", name: "Puppy", age: 1 }) } popPet(){ state.pets.pop() } render() { /** @type {initState["pets"]} */ let state = this.props.state; return () } }My pets:{state.map(pet =>)}
非常容易!我們還添加了兩個按鈕并指定了點擊處理函數,運行體驗一下:
打開 react dev tools 的 Highlight Updates 選項,并點擊 push 或 pop 按鈕,可以觀察到視圖更新情況如我們所愿:
空初始數組與編輯器 intelliSence通常情況下,數組節點的初始值是空的。為了實現編輯器 intelliSence, 我們可以在外面定義一個元素類型,并注釋這個數組節點的元素為該類型:
const initState = { ... /** @type {[pet]} */ pets: [] } const pet = { id: "id01", name: "Kitty", age: 2 }
你也可以使用泛型的格式來定義數組類型: /** @type {Array
上一章我們提到了單實例組件,是指組件只被使用一次;而我們可以到 PetView 被用于顯示數組元素,會被多次使用。我們把這類在多處被使用的組件稱為多實例組件。多實例組件內部動作的處理邏輯由組件實例的具體位置而定,與單實例組件的處理模式有差別,我們來看看。
我們試著制作一個每個寵物視圖中添加兩個按鈕來調整寵物的年齡,我們用兩種傳統方案和pastate方案分別實現:
react 傳統方案 傳統方案1:父組件處理父組件向子組件傳遞綁定index的處理函數:這種模式是把子組件的動作處理邏輯實現在父組件中,然后父組件把動作綁定對應的 index 后傳遞給子組件
class PetsView extends PureComponent { ... addAge(index){ state.pets[index].age += 1 } reduceAge(index){ state.pets[index].age -= 1 } render() { /** @type {initState["pets"]} */ let state = this.props.state; return (... { state.map((pet, index) =>) } }this.addAge(index)} // 綁定 index 值,傳遞給子組件 reduceAge={() => this.reduceAge(index)} // 綁定 index 值,傳遞給子組件 />) } ...
class PetView extends PureComponent { render() { /** @type {initState["pets"][0]} */ let state = this.props.state; return () } }{state.name}: {/* 使用已綁定 index 值得動作處理函數 */} {state.age} {/* 使用已綁定 index 值得動作處理函數 */} years old.
這種模式可以把動作的處理統一在一個組件層級,如果多實例組件的視圖含義不明確、具有通用性,如自己封裝的 Button 組件等,使用這種動作處理模式是最好的。但是如果多實例組件的含義明顯、不具有通用性,特別是用于顯示數組元素的情況下,使用這種模式會引發多余的渲染過程。
打開 react dev tools 的 Highlight Updates 選項,點擊幾次 push pet 增加一些元素后,再點擊 + 或 - 按鈕看看組件重新渲染的情況:
可以發現當我們只修改某一個數組元素內部的值(pet[x].age)時,其他數組元素也會被重新渲染。這是因為 Pet.props.addAge 和 Pet.props.reduceAge 是每次父組件 PetsView 渲染時都會重新生成的匿名對象,PureComponent 以此認為組件依賴的數據更新了,所以觸發重新渲染。雖然使用 React.Component 配合 自定義的 shouldComponentUpdate 生命周期函數可以手動解決這個問題,但是每次渲染父組件 PetsView 時都重新生成一次匿名子組件屬性值,也在消耗運算資源。
傳統方案2:子組件結合 index 實現父組件向子組件傳遞 index 值:這種模式是父組件向子組件傳遞 index 值,并在子組件內部實現自身的事件處理邏輯,如下:
class PetsView extends PureComponent { ... render() { ... return (... { state.map((pet, index) =>) } }) } ...
class PetView extends PureComponent { // 在子組件實現動作邏輯 // 調用時傳遞 index addAge(index){ state.pets[index].age += 1 } // 或函數自行從 props 獲取 index reduceAge = () => { // 函數內部使用到 this 對象,使用 xxx = () => {...} 來定義組件屬性更方便 state.pets[this.props.index].age -= 1 } render() { /** @type {initState["pets"][0]} */ let state = this.props.state; let index = this.props.index; return () } }{state.name}: {/* 使用閉包傳遞 index 值 */} {state.age} {/* 或讓函數實現自己去獲取index值 */} years old.
這種模式可以使子組件獲取 index 并處理自身的動作邏輯,而且子組件也可以把自身所在的序號顯示出來,具有較強的靈活性。我們再來看看其當元素內部 state 改變時,組件的重新渲染情況:
我們發現,數組元素組件可以很好地按需渲染,在渲染數組元素的情況下這種方法具有較高的運行效率。
但是,由于元素組件內部操作函數綁定了唯一位置的 state 操作邏輯,如addAge(index){ state.pets[index].age += 1}。假設我們還有 state.children 數組,數組元素的格式與 state.pets 一樣, 我們要用相同的元素組件來同時顯示和操作這兩個數組時,這種數組渲染模式就不適用了。我們可以用第1種方案實現這種情況的需求,但第1種方案在渲染效率上不是很完美。
pastate 數組元素操作方案Pastate 的 imState 的每個節點本身帶有節點位置的信息和 store 歸宿信息,我們可以利用這一點來操作數組元素!
pastate 方案1:獲取對于的響應式節點我們使用 getResponsiveState 函數獲取 imState 對于的響應式 state,如下:
class PetsView extends PureComponent { ... render() { ... return (... { state.map((pet, index) =>) } }) } ...
import {..., getResponsiveState } from "pastate" class PetView extends PureComponent { addAge = () => { /** @type {initState["pets"][0]} */ let pet = getResponsiveState(this.props.state); // 使用 getResponsiveState 獲取響應式 state 節點 pet.age += 1 } reduceAge = () => { /** @type {initState["pets"][0]} */ let pet = getResponsiveState(this.props.state); // 使用 getResponsiveState 獲取響應式 state 節點 pet.age -= 1 } render() { /** @type {initState["pets"][0]} */ let state = this.props.state; return () } }{state.name}: {state.age} years old.
我們可以看到,子組件通過 getResponsiveState 獲取到當前的 props.state 對應的響應式 state,從而可以直接對 state 進行復制修改,你無需知道 props.state 究竟在 store.state 的什么節點上! 這種模式使得復用組件可以在多個不同掛載位置的數組中使用,而且可以保證很好的渲染性能:
pastate 方案2:使用 imState 操作函數Pastate 提供個三個直接操作 imState 的函數,分別為 set, merge, update。我們來演示用這些操作函數來代替 getResponsiveState 實現上面操作寵物年齡的功能:
import {..., set, merge, update } from "pastate" class PetView extends PureComponent { addAge = () => { set(this.props.state.age, this.props.state.age + 1); } reduceAge = () => { merge(this.props.state, { age: this.props.state.age - 1 }); } reduceAge_1 = () => { update(this.props.state.age, a => a - 1); } ... }
可見,這種 imState 操作函數的模式也非常簡單!
使用 pastate 數組元素操作方案的注意事項:當操作的 state 節點的值為 null 或 undefined 時, 只能使用 merge 函數把新值 merge 到父節點中,不可以使用 getResponsiveState ,set 或 update。我們在設計 state 結構時,應盡量避免使用絕對空值,我們完全可以用 "", [] 等代替絕對空值。
下一章,我們來看看如何在 pastate 中渲染和處理表單元素。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93803.html
摘要:這一章,我們在上一章的結構中添加多一些信息,并用多個組件來組織應用。是的響應式影子可以對任何節點進行直接賦值修改,會把修改結果作用到,并異步觸發視圖更新。因此在中的是對象而在中的是對象。 這是 pastate 系列教程的第二章,歡迎關注,持續更新。 這一章,我們在上一章的 state 結構中添加多一些信息,并用多個組件來組織 pastate 應用。 更新 state 結構 我們把上一章...
摘要:簡介是什么是一個響應式管理框架,實現了對的異步響應式管理。可靠性已經通過個測試用例的全面測試,穩定可靠。安裝是一個狀態管理框架,需要配合使用。 Pastate 簡介 Pastate 是什么 Pastate 是一個響應式 react state 管理框架,實現了對 state 的異步響應式管理。Pastate 是一個精益框架,它對很多高級概念進行了友好封裝,這意味著你不必學習一些難以理解...
摘要:宅印前端基于的模式開發,我們指定了一套分工明確的并行開發流程。下面通過一個蘋果籃子實例,來看看整個應用開發流程。容器負責接收中的和并發送大多數時候需要和直接連接,容器一般不需要多次使用,比如我們這個應用的蘋果籃子。 前言:在當下的前端界,react 和 redux 發展得如火如荼,react 在 github 的 star 數達 42000 +,超過了 jquery 的 39000+,...
摘要:本文總結了前端老司機經常問題的一些問題并結合個人總結給出了比較詳盡的答案。網易阿里騰訊校招社招必備知識點。此外還有網絡線程,定時器任務線程,文件系統處理線程等等。線程核心是引擎。主線程和工作線程之間的通知機制叫做事件循環。 showImg(https://segmentfault.com/img/bVbu4aB?w=300&h=208); 本文總結了前端老司機經常問題的一些問題并結合個...
閱讀 2845·2021-10-21 09:38
閱讀 2751·2021-10-11 10:59
閱讀 3022·2021-09-27 13:36
閱讀 1649·2021-08-23 09:43
閱讀 791·2019-08-29 14:14
閱讀 3034·2019-08-29 12:13
閱讀 3203·2019-08-29 12:13
閱讀 310·2019-08-26 12:24