由里到外的状态管理

 

既然我们是通过数据状态来管理视图的,那么在设计初期我们就可以从有限的状态转移来思考业务逻辑。通过思考每个状态对应的数据,状态转移函数,我们可以很清晰的罗列出数据更变逻辑。从数据去控制视图也是现代前端所接触到的MVVM模式。

一个大型应用,我们也会使用Vuex 或 Redux来进行一整个应用的管理。

在平时的业务中,我们会遇到一个痛点是:Vuex,Redux是一个全局状态管理,但我们现在需要在局部需要一个局部状态管理变更,只能使用 mutation 或 dispatch 去提交更改。

如果我们频繁的更新状态,那么我们需要为每一个局部模块编写大量dispatch函数来间接修改全局状态。随着应用的扩充,dispatch文件会越来越臃肿。

那么我们是不是可以使用不同的状态管理工具,来实现局部状态的管理。在局部状态更新完之后,再去用局部更新去更新全局呢?

注:但这也会有一个缺点,局部管理相对独立。有些高度复用的提交函数需要放在全局状态管理上

a. 框架原生组件状态管理

React Hooks + React.createContext

React Hooks提供了useReducer + useContext + Context 可以实现一个小型的状态管理


  1. // 以下代码就实现了一个能够穿透组件的状态管理
  2. import React, { useReducer, useContext } from 'react'
  3.  
  4. const reducer = (state = 0, { type, …payload }) => { 
  5.   switch (type) { 
  6.     case 'add'
  7.       return state + 1
  8.     case 'desc'
  9.       return state – 1
  10.     default
  11.       return state; 
  12.   } 
  13.  
  14. const Context = React.createContext(); 
  15. const Parent = () => { 
  16.   const [state, dispatch] = useReducer(reducer, 0); 
  17.   return ( 
  18.     <> 
  19.       <Context.Provider value={{ state, dispatch }}> 
  20.         <Son /> 
  21.       </Context.Provider> 
  22.     </> 
  23.   ) 
  24.  
  25. function Son() { 
  26.   return <Counter /> 
  27.  
  28. function Counter() { 
  29.   const { state, dispatch } = useContext(Context); 
  30.   return ( 
  31.     <div> 
  32.       <button onClick={() => dispatch({ type: 'desc' })}>-</button> 
  33.       {state} 
  34.       <button onClick={() => dispatch({ type: 'add' })}>+</button> 
  35.     </div> 
  36.   ) 
  37. export default Parent; 
  38. 复制代码 

Vue响应式数据 + vue.Provide/inject

使用vue响应式系统 + provide/inject API来实现一个具有穿透性的局部状态管理


  1. // Parent.vue
  2. <template> 
  3.   <Son /> 
  4. </template> 
  5.  
  6. <script setup> 
  7. import { provide, reactive, readonly } from "vue"
  8. import Son from "./Son.vue"
  9. const data = reactive({ 
  10.   count: 0
  11. }); 
  12. const onAdd = () => { 
  13.   data.count++; 
  14. }; 
  15. const onDesc = () => { 
  16.   data.count–; 
  17. }; 
  18. provide("store", { 
  19.   data: readonly(data), // 只读属性
  20.   onAdd, // 修改函数add
  21.   onDesc, // 修改函数desc
  22. }); 
  23. </script> 
  24.  
  25. 复制代码 

  1. // Son.vue
  2. <template> 
  3.   <Counter /> 
  4. </template> 
  5.  
  6. <script setup> 
  7. import Counter from "./Counter.vue"
  8. </script> 
  9. 复制代码 

  1. // Counter.vue
  2. <template> 
  3.   <div> 
  4.     <button @click="store.onDesc">-</button> 
  5.     {{ store.data.count }} 
  6.     <button @click="store.onAdd">+</button> 
  7.   </div> 
  8. </template> 
  9.  
  10. <script setup> 
  11. import { inject } from "vue"
  12. const store = inject("store", {}); // 穿透读取store
  13. </script> 
  14. 复制代码 
【声明】:芜湖站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

相关文章