React学习32(深浅克隆之Immutable.js)

Immutable.js github地址:https://github.com/immutable-js/immutable-js

介绍

每次修改一个immutable对象时都会创建一个新的不可变的对象,在新对象上操作并不会影响到原

对象的数据,那Immutable这个库的实现是深拷贝还是浅拷贝?

深拷贝与浅拷贝的关系

(1)var arr = {}; arr2 = arr  浅拷贝

(2)Object.assign()只是一级属性复制,比浅拷贝多拷贝了一层而已

(3)const obj1 = JSON.parse(JSON.stringfy(obj));数组,对象都好用的方法,是深拷贝(缺点:

属性中不能有undefined,如果属性中有undedined,在进行拷贝的时候会忽略该属性)

Immutable优化性能的方式

Immutable实现的原理是Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新

数据时,要保证旧数据同时可用且不变,同时为了避免deepCopy把所有节点都复制一遍带来的性

能损耗,Immutable使用了Strctural Sharing(结构共享),即如果对象树中的一个节点发生变化,

只修改这个节点和受它影响的腹肌诶单,其他节点则进行共享。

扫描二维码关注公众号,回复: 16439900 查看本文章

Immutable中常用类型有Map, List

Immutable使用

下载:npm i immutable

引入:import {Map, List} from 'immutable'

Map使用

使用说明:

1.对定义的对象进行包裹,返回一个相同的新对象

2.如何修改属性-------通过.set('要修改的属性', ‘要修改的结果’)

3.如何得到属性--------通过.get('要得到的属性值的属性名')

4.如何将immutable对象转化为普通对象--------toJS()

示例:

import { Map } from 'immutable'
const obj = {
  name:'xiaojian', 
  age:18
}
// 对原对象进行immutable包装返回一个新的对象
const oldImmutable = Map(obj)
// 修改原对象中的属性并将修改后的原对象赋值给新的对象
const newImmutable = oldImmutable.set('name', 'xiaoliu')
console.log(oldImmutable, newImmutable);

// 1.get获取immutable
console.log(oldImmutable.get('name'), newImmutable.get('name'));

// 2.将immutable转化为普通的对象使用
console.log(oldImmutable.toJS(), newImmutable.toJS());

输出结果:

 组件使用一:

// // 定义state时使用Map包装后的对象
export default class App extends Component {

  state = {
    info:Map({
      name:'xiaojian', 
      age:18
    })
  }
  render() {
    return (
      <div>
        <button onClick={() => {
          this.setState({
            info:this.state.info.set('name', 'xiaoliu').set('age', 28)
          })
        }}>修改按钮</button>
        {this.state.info.get('name')} -- {this.state.info.get('age')}
      </div>
    )
  }
}

 组件使用二:

// 定义state的时候使用普通对象
export default class App extends Component {
  state = {
    info:{
      name:'xiaojian', 
      age:18
    }
  }
  render() {
    return (
      <div>
        <button onClick={() => {
          const old = Map(this.state.info)
          const newImmu = old.set('name', 'xiaoliu').set('age', 28)
          this.setState({
            info:newImmu.toJS()
          })
        }}>修改按钮</button>
        {this.state.info.name} -- {this.state.info.age}
      </div>
    )
  }
}

父子组件传值:

如何手动解决在父子组件之间传递参数时在修改父组件数据,而子组件数据不变的情况下,不重新

渲染子组件而带来的性能优化,可以通过shouldComponentUpdate函数来实现

import React, { Component } from 'react'
import { Map } from 'immutable';

export default class App extends Component {
state = {
  info:Map({
    name:'xiaojian',
    select:'aa',
    filter:Map({
      text:'',
      up:true,
      down:false
    })
  })
}

componentDidMount() {
  // console.log(this.state.info);
}
  render() {
    return (
      <div>
        <button onClick={() => {
          this.setState({
            info:this.state.info.set('name', 'xiaoming')
          })
        }}>更新</button>
        {this.state.info.get('name')}
        <Child filter={this.state.info.get('filter')}/>
      </div>
    )
  }
}

class Child extends Component{
  shouldComponentUpdate(nextProps, nextState) {
    if (this.props.filter === nextProps.filter) {
      return false
    }
    return true
    // console.log(nextProps, nextState);
  }
  render() {
    return <div>
      child
    </div>
  }

  componentDidUpdate() {
    console.log('componentDidUpdate');
  }
}

List使用:

说明:List主要是为数组服务,为了降低immutable中List的学习成本,其中封装的方法与array的方

法的作用是一样的

js示例代码:

import { List } from 'immutable'
const arr = List([1, 2, 3])

// 添加元素可以使用push,不会影响老的对象结构
const arr2 = arr.push(4)
console.log(arr, arr2);

输出结果:

 组件示例:

import React, { Component } from 'react'
import { List } from 'immutable'

export default class App extends Component {
  state = {
    favo:List(['aa', 'bb', 'cc'])
  }

  render() {
    return (
      <div>
        {
          this.state.favo.map(item => {
            return <li key={item}>{item}</li>
          })
        }
      </div>
    )
  }
}

}

同时使用Map, List

import { Map, List } from 'immutable'
import React, { Component } from 'react'

export default class App extends Component {

  state = {
    info:Map({
      name:'小剑',
      location:Map({
        province:'四川',
        city:'成都'
      }),
      favor:List(['读书','看报', '写代码'])

    })
  }
  render() {
    return (
      <div>
        <h1>个人信息修改页面</h1>
        <button onClick={() => {
          this.setState({
            info:this.state.info.set('name', '小明').set('location', this.state.info.get('location').set('city', '北京'))
          })
        }}>修改</button>
        <div>
          {this.state.info.get('name')}
          <br/>
          {this.state.info.get('location').get('province')}----{this.state.info.get('location').get('city')}
          <br/>
          {this.state.info.get('favor').map((item, index) => {
            return <li key={item}>{item}<button style={
   
   {marginLeft:'10px'}} onClick={() => {
              console.log(index);
              this.setState({
                info:this.state.info.set('favor', this.state.info.get('favor').splice(index, 1))
              })
            }}>del</button></li> 
          })}
        </div>
      </div>
    )
  }
}

问题:同时使用Map和List会造成代码的书写很麻烦,为了解决这个问题,从Immutable中引入

fromJS进行代码的优化

fromJs实现对象的深克隆

用法说明:

1.如何读取属性-----------通过.get('属性名')获得

2.如何修改对象中的属性--------------通过setIn([ ], '修改后的值')

说明:数组中可以是一个参数,也可以是多个参数,如果只是一个参数,说明修改的值是最外层的

属性,如果有多层对象则依次写入即可

3.如何修改数组中的属性---------通过updateIn([ ], () => { } )

示例代码:

import { fromJS } from 'immutable'
import React, { Component } from 'react'

export default class App extends Component {

  state = {
    info:fromJS({
      name:'小剑',
      location:{
        province:'四川',
        city:'成都',
        a:{
          b:1111,
          h:2222
        }
      },
      favor:['读书','看报', '写代码']

    })
  }

  componentDidMount() {
    console.log(this.state.info);
  }
  render() {
    return (
      <div>
        <h1>个人信息修改页面</h1>
        {/* setIn(参数一, 参数二) 
          第一个参数是一个数组,数组可以的是一个元素,也可以是两个元素
          第二个参数是修改后的内容
        */}
        <button onClick={() => {
          this.setState({
            info:this.state.info.setIn(['name'], '小明').setIn(['location', 'city'], '上海').setIn(['location','a', 'b'], '0000000000000')
          })
        }}>修改</button>
        <div>
          {this.state.info.get('name')}
          <br/>
          {this.state.info.get('location').get('province')}----{this.state.info.get('location').get('city')}--{this.state.info.get('location').get('a').get('b')}
          <br/>
          {this.state.info.get('favor').map((item, index) => {
            return <li key={item}>{item}<button style={
   
   {marginLeft:'10px'}} onClick={() => {
              // this.setState({
              //   info:this.state.info.set('favor', this.state.info.get('favor').splice(index, 1))
              // })

              this.setState({
                info:this.state.info.updateIn(['favor'], (list) => {
                 return list.splice(index, 1)
                })
              })
            }}>del</button></li> 
          })}
        </div>
      </div>
    )
  }
}

猜你喜欢

转载自blog.csdn.net/xiaojian044/article/details/128422019