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

news2024/11/18 13:38:25

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(结构共享),即如果对象树中的一个节点发生变化,

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

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>
    )
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/111212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】优先级队列(堆)与PriorityQueue

目录 一、堆 二、Java里的集合类PriorityQueue 1、优先级队列的概念 2、构造方法 3、常用方法 1.入队offer 2.出队poll 3.获取队首元素peek 4.扩容机制 4、 注意事项 三、实现大根堆 1、准备字段 2、创建大根堆 3、offer 4、poll 5、peek 一、堆 如果有一个关键…

Selenium WebDriver定位策略(一)

WebDriver中使用的定位策略列表: 下面以百度搜索输入框为例进行讲解 1、按ID定位策略 通过元素的id属性来定位&#xff0c;前提&#xff1a;元素必须有id属性 driver.find_element_by_id("kw")2、按名称查找策略 通过元素的name属性来定位&#xff0c;前提&…

Go语言设计与实现 -- 关键字for和range

如果我们查看汇编代码的话&#xff0c;可以发现&#xff0c;经过优化的for-range循环的汇编代码和普通for的结构相同。也就是说&#xff0c;使用for-range的控制结构最终也会被Go语言编译器换成普通的for循环。 现象提出 现象1&#xff1a;循环永动机 func main() {arr : []…

如何在anaconda中配置graphviz包

文章目录GraphViz简介一&#xff1a;安装graphviz二&#xff1a;配置环境变量三&#xff1a;检测Graphviz是否配置成功。四&#xff1a;安装graphviz包GraphViz简介 graphviz是贝尔实验室开发的一个开源的工具包&#xff0c;它使用一个特定的DSL(领域特定语言):dot作为脚本语言…

android apk 目录结构

APK的目录结构 更改APK的后缀后&#xff0c;可以看到APK的组成如下&#xff1a; assets 其中assets中存放静态资源。 Res res中存放静态资源。 与assets不同之处&#xff0c;res文件夹下的所有文件会生成资源Id.lib 包括依赖的jar包库&#xff0c;so文件等。 so文件是利…

GD32F450以太网(2-2): PHY芯片IP101GR介绍

PHY芯片IP101GR 文章目录PHY芯片IP101GR1. 预备知识2. IP101GR简介3. IP101GR基于RMII接口的PCB设计重点解析3.1 时钟设置3.2. led灯设计3.3. PHY芯片地址设置4. pcb设计5. 寄存器描述6. 附加&#xff1a;IP101GR和GD32F450引脚连接情况1. 预备知识 接上文 《GD32F450以太网(…

液晶OLED接口MIPI之DSI协议学习

文章目录一、概念介绍MIPI----MIPI联盟发起的为移动应用处理器制定的开放标准MIPI-DSI---Display Serial Interface 2定义了处理器和显示模组之间的高速串行接口DCS---Display Command Set 显示命令集合&#xff08;MIPI-DSI的command模式使用通用标准命令&#xff09;DSC---Di…

字符串函数剖析(3)---strstr函数

1.strstr函数的巧妙 – 查找子字符串 1.1模拟实现strstr函数 strstr函数&#xff1a;在一个字符串中查找子串 学习新函数时&#xff0c;先去c库查找该函数的相关资料&#xff0c;更加助于你的学习 const char * strstr ( const char * str1, const char * str2 );先看函数的…

测开工具:spring boot 实现同步数据库表结构(持续更新)

一、使用场景 一个项目&#xff0c;有多套开发环境。有一套标准的数据库&#xff0c;不同的开发环境&#xff0c;有各自的一套数据库。 标准数据库的表结构经常发生变化&#xff0c;不同的开发环境中的数据库&#xff0c;需要与标准数据库的表结构保持一致。当标准数据库表结…

HNU编译原理实验一cminus_compiler-2022-fall

前言&#xff1a;实验不是很难&#xff0c;主要考察正则表达式部分 lab1实验报告实验要求 根据cminux-f的词法补全lexical_analyer.l文件&#xff0c;完成词法分析器&#xff0c;能够输出识别出的token&#xff0c;type ,line(刚出现的行数)&#xff0c;pos_start(该行开始位置…

[机缘参悟-95] :不同人生、社会问题的本质

事情的本质是物极必反&#xff08;轮回、周期&#xff09; 社会的本质是优胜劣汰&#xff08;迭代、发展&#xff09; 道德的本质是伦理秩序&#xff08;未定、秩序&#xff09; 战争的本质是资源占用&#xff08;弱肉、强食&#xff09; 商业的本质是价值交换 金钱的本质…

基于JAVA SpringBoot+ JWT+Redis的ERP系统,VUE+Element-UI 前后端分离的Saas平台

项目简介 简云Saas平台 基于SpringBoot2.2.0, Mybatis, JWT, Redis, VUEElement-UI 的前后端分离的Saas平台管理系统 在线报表开发 在线表单设计 工作流设计 自定义打印模板定义 **产品分二个版本: 开源版本(包含了系统基础架构在线表单设计). 此版本代码完全开源ERP版本…

Flink-基本的合流操作

文章目录1.基本的合流操作2.1联合&#xff08;Union&#xff09;2.2 连接&#xff08;Connect&#xff09;2.基于时间的合流——双流联结&#xff08;Join&#xff09;2.1 窗口联结&#xff08;Window Join&#xff09;2.2 间隔联结&#xff08;Interval Join&#xff09;2.3 窗…

《面向对象分析与设计》总结

面向对象的软件工程1 面向对象的演化1.1 生活中复杂系统的特点1.2 软件系统的复杂性1.2.1 复杂性的四个方面1.2.1.1 问题域的复杂性1.2.1.2 管理开发的困难性1.2.1.3 软件中的灵活性1.2.1.4 描述离散系统行为1.2.2 复杂系统的五个属性1.2.2.1 层次结构1.2.2.1.1 对象结构1.2.2.…

数据分析神器:数据自动录入并生成BI报表

做报表、分析数据、做汇报是许多打工人的日常&#xff0c;每天都要耗费不少的时间用Excel来整理、清洗数据和生成好看的报表。如果这些数据都是手动整理、复制粘贴的话&#xff0c;不仅费时费力&#xff0c;而且很容易出错。 在越来越多企业采用SaaS产品和不同数据应用的今天&…

来看一个vue-element-表单之登录页面,最后送上一个登录页面

vue-element 表单之登录页面使用 0. 先留下属性表格 表单验证&#xff1a;Form 组件提供了表单验证的功能&#xff0c;只需要通过 rules 属性传入约定的验证规则&#xff0c;并将 Form-Item 的 prop 属性设置为需校验的字段名即可。 1. 表单属性表(el-form) 2. 表单项属性表…

php工作流引擎再发新版本—Tpflow7.0重磅发布

2022年已接近尾声&#xff0c;又到了每年发布大版本的时候&#xff0c;Tpflow历经一个多月的意见征集及版本优化&#xff0c;从底层改进&#xff0c;从UI调整&#xff0c;增强了事件功能。 发布日期&#xff1a;2022年12月23日 发布版号&#xff1a;V7.0.0 Tpflow 工作流引擎…

短视频引流+私域流量沉淀,一个全新的短视频和链动模式结合方案

在微盟企微助手微盟智慧零售团队的协助下&#xff0c;今年7月底么么茶正式开始运营企微私域&#xff0c;截至当前&#xff0c;在短短3个月时间已成功沉淀7万私域客户&#xff0c;线上商城GMV超145万。 么么茶旅拍的核心流量来源自公域短视频平台&#xff0c;品牌基于服务覆盖下…

OB0206 obsidian 表格编辑插件:advanced Tables插件使用

序号解读&#xff1a; 01——软件基础使用、基础语法 02——插件使用 03——综合实战 0 写在前面 Ob社区插件汇总&#xff1a;Airtable - OB社区插件汇总 - Johnny整理 - 每周更新 - B站 Johnny学Explore the "OB社区插件汇总 - Johnny整理 - 每周更新 - B站 Johnny学&qu…

执行操作后的变量值,我的题解首次优于官方

2011. 执行操作后的变量值 难度简单46 存在一种仅支持 4 种操作和 1 个变量 X 的编程语言&#xff1a; X 和 X 使变量 X 的值 加 1--X 和 X-- 使变量 X 的值 减 1 最初&#xff0c;X 的值是 0 给你一个字符串数组 operations &#xff0c;这是由操作组成的一个列表&#xf…