欢迎来到DIVCSS5查找CSS资料与学习DIV CSS布局技术!
简介
 
React的Reconciliation解决了虚拟DOM更新的问题,但没有对在什么场景下优化更新给出解决方案,它不像Reactive那样能自动跟踪状态变化,而是把这个难题通过shouldComponentUpdate这个口子留给了开发者。于是开发者需要针对前后状态的变化进行对比,以决定要不要继续渲染更新DOM。如果状态对象的层次很深很复杂,那么这个对比必然会很痛苦。
 
但是话说回来,如果比较得很痛苦,那很有可能状态对象设计的有问题
 
于是Immutable诞生了,简单的可以把Immutable看做是一个黑盒,输入是对象A,输出是一个对象A‘。
 
用公式表示就是
 
假如输入对象A1和A2完全一样(但仍然不是同一个实例),那么输出的A1'和A2’能方便地比较出是否相等(提供了API直接调用来比较),同时也能从A1'或A2'里拿出A1或A2的原始数据(但A1'和A2‘仍然是两个不同的实例)。后续更新的操作也都是要通过A'的API来进行了,也就是说原始对象已经离你远去。
 
名气最大的Immutable解决方案就是当年的Immutable.js,本文介绍的Immer.js属于Immutable界的后浪。Immer这个词来自于德语的Always,它的作者同时也是Mobx的作者。
 
先上图,看样子仍然是个黑盒不变。
 
如果真没任何变化,那也称不上是后浪了。它基于copy-on-write机制——在当前的状态数据上复制出一份临时的草稿,然后对这份草稿涂涂改改,最后生成新的状态数据。借力于ES6的Proxy,只需要直接修改对象即可,不需要调用复杂的API(几乎只用到一个produce函数!!!),跟响应式的自动跟踪是一样的。
 
官网文档将其比喻成你的小秘(不是小蜜),这个小秘复制一份你的信给你涂改,然后根据涂改能帮你打印出一份新的修改后的信件。
 
 import produce from "immer"
 
 ​
 
 const baseState = [
 
     {
 
         todo: "Learn typescript",
 
         done: true
 
     },
 
     {
 
         todo: "Try immer",
 
         done: false
 
     }
 
 ]
 
 ​
 
 const nextState = produce(baseState, draftState => {
 
     draftState.push({todo: "Tweet about it"})
 
     draftState[1].done = true
 
 })
 
如果了解响应式的话,会发现
 
在React里,setState就变成了
 
 this.setState(
 
     produce(draft => {
 
         draft.user.age += 1
 
     })
 
 )
 
在Redux里,Reducer就变成了
 
 const byId = produce((draft, action) => {
 
     switch (action.type) {
 
         case RECEIVE_PRODUCTS:
 
             action.products.forEach(product => {
 
                 draft[product.id] = product
 
             })
 
     }
 
 })
 
default分支也可以省略,因为produce方法默认返回原始对象实例。
 
也有个例外,就是如果要返回undefined还不能直接干,得要返回nothing
 
 import produce, {nothing} from "immer"
 
 const state = {
 
     hello: "world"
 
 }
 
 ​
 
 produce(state, draft => {})
 
 produce(state, draft => undefined)
 
 // Both return the original state: { hello: "world"}
 
 ​
 
 produce(state, draft => nothing)
 
 // Produces a new state, 'undefined'

如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h64075.shtml