参考答案:
Immutable,不可改变的,在计算机中,即指一旦创建,就不能再被更改的数据
对 Immutable
对象的任何修改或添加删除操作都会返回一个新的 Immutable
对象
Immutable
实现的原理是 Persistent Data Structure
(持久化数据结构):
也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变,同时为了避免 deepCopy
把所有节点都复制一遍带来的性能损耗,Immutable
使用了 Structural Sharing
(结构共享)
如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享
使用Immutable
对象最主要的库是immutable.js
immutable.js 是一个完全独立的库,无论基于什么框架都可以用它
其出现场景在于弥补 Javascript 没有不可变数据结构的问题,通过 structural sharing来解决的性能问题
内部提供了一套完整的 Persistent Data Structure,还有很多易用的数据类型,如Collection
、List
、Map
、Set
、Record
、Seq
,其中:
List: 有序索引集,类似 JavaScript 中的 Array
Map: 无序索引集,类似 JavaScript 中的 Object
Set: 没有重复值的集合
主要的方法如下:
1const obj = Immutable.fromJS({a:'123',b:'234'})
1import { Map, is } from 'immutable' 2const map1 = Map({ a: 1, b: 1, c: 1 }) 3const map2 = Map({ a: 1, b: 1, c: 1 }) 4map1 === map2 //false 5Object.is(map1, map2) // false 6is(map1, map2) // true
get(key):对数据或对象取值
getIn([]) :对嵌套对象或数组取值,传参为数组,表示位置
1let abs = Immutable.fromJS({a: {b:2}}); 2abs.getIn(['a', 'b']) // 2 3abs.getIn(['a', 'c']) // 子级没有值 4 5let arr = Immutable.fromJS([1 ,2, 3, {a: 5}]); 6arr.getIn([3, 'a']); // 5 7arr.getIn([3, 'c']); // 子级没有值
如下例子:使用方法如下:
1import Immutable from 'immutable'; 2foo = Immutable.fromJS({a: {b: 1}}); 3bar = foo.setIn(['a', 'b'], 2); // 使用 setIn 赋值 4console.log(foo.getIn(['a', 'b'])); // 使用 getIn 取值,打印 1 5console.log(foo === bar); // 打印 false
如果换到原生的js
,则对应如下:
1let foo = {a: {b: 1}}; 2let bar = foo; 3bar.a.b = 2; 4console.log(foo.a.b); // 打印 2 5console.log(foo === bar); // 打印 true
使用 Immutable
可以给 React
应用带来性能的优化,主要体现在减少渲染的次数
在做react
性能优化的时候,为了避免重复渲染,我们会在shouldComponentUpdate()
中做对比,当返回true
执行render
方法
Immutable
通过is
方法则可以完成对比,而无需像一样通过深度比较的方式比较
在使用redux
过程中也可以结合Immutable
,不使用Immutable
前修改一个数据需要做一个深拷贝
1import '_' from 'lodash'; 2 3const Component = React.createClass({ 4 getInitialState() { 5 return { 6 data: { times: 0 } 7 } 8 }, 9 handleAdd() { 10 let data = _.cloneDeep(this.state.data); 11 data.times = data.times + 1; 12 this.setState({ data: data }); 13 } 14}
使用 Immutable 后:
1getInitialState() { 2 return { 3 data: Map({ times: 0 }) 4 } 5}, 6 handleAdd() { 7 this.setState({ data: this.state.data.update('times', v => v + 1) }); 8 // 这时的 times 并不会改变 9 console.log(this.state.data.get('times')); 10 }
同理,在redux
中也可以将数据进行fromJS
处理
1import * as constants from './constants' 2import {fromJS} from 'immutable' 3const defaultState = fromJS({ //将数据转化成immutable数据 4 home:true, 5 focused:false, 6 mouseIn:false, 7 list:[], 8 page:1, 9 totalPage:1 10}) 11export default(state=defaultState,action)=>{ 12 switch(action.type){ 13 case constants.SEARCH_FOCUS: 14 return state.set('focused',true) //更改immutable数据 15 case constants.CHANGE_HOME_ACTIVE: 16 return state.set('home',action.value) 17 case constants.SEARCH_BLUR: 18 return state.set('focused',false) 19 case constants.CHANGE_LIST: 20 // return state.set('list',action.data).set('totalPage',action.totalPage) 21 //merge效率更高,执行一次改变多个数据 22 return state.merge({ 23 list:action.data, 24 totalPage:action.totalPage 25 }) 26 case constants.MOUSE_ENTER: 27 return state.set('mouseIn',true) 28 case constants.MOUSE_LEAVE: 29 return state.set('mouseIn',false) 30 case constants.CHANGE_PAGE: 31 return state.set('page',action.page) 32 default: 33 return state 34 } 35}
最近更新时间:2024-08-10