react htmlh1无效,详解react阻止无效重渲染的多种方式_而已_前端开发者
在开发React组件的过程中,我们经常会遇到这个问题:什么情况下组件会重新渲染?
当内部data发生改变,state发生改变(通过调用this.setState()) 以及父组件传过来的props发生改变时,会导致组件重新渲染。
以下几个问题同样值得我们思考:
setState()函数在任何情况下都会导致组件重渲染吗?如果setState中的state没有发生改变呢?
如果state和从父组件传过来的props都没变化,那他就一定不会发生重渲染吗?
首先,我们来解决这两个问题
没有导致state的值发生变化的this.setState()是否会导致重渲染 — 会
import React from 'react'
class Test extends React.Component{
constructor(props) {
super(props);
this.state = {
Number:1//设state中Number值为1
}
}
//这里调用了setState但是并没有改变setState中的值
handleClick = () => {
const preNumber = this.state.Number
this.setState({
Number:this.state.Number
})
}
render(){
//当render函数被调用时,打印当前的Number
console.log(this.state.Number)
return(
{this.state.Number}
)
}
}
从控制台的打印结果可以看出:共打印了15次1,但是组件并没有发生任何变化!!!
这样的结果不是我们想要的,如何阻止组件的重渲染呢?这时我们想到了React的一个生命周期钩子 shouldComponentUpdate
react生命周期中有这样一个钩子,叫shouldComponentUpdate函数,是重渲染时render()函数调用前被调用的函数,
两个参数 nextProps和nextState ,分别表示下一个props和state的值。
当函数返回false时,阻止接下来的render()函数的调用,阻止组件重渲染,返回true时,组件照常渲染
//加入shouldComponentUpdate钩子
//在render函数调用前判断:如果前后state中Number不变,通过return false阻止render调用
shouldComponentUpdate(nextProps,nextState){
if(nextState.Number == this.state.Number){
return false
}
}
加入上述代码后,打开控制台,点击按钮,还是白白的,说明无效的重渲染被我们阻止了
第二个问题,组件的state和从父组件传递过来的props都没改变,组件还会重渲染吗 — 可能
同样可以通过shouldComponentUpdate钩子进行阻止
所以说,前后不改变state的值的setState和无数据交换的父组件的重渲染都会导致组件的重渲染,但我们可以通过shouldComponentUpdate来阻止这两种情况
shouldComponentUpdate并不是完美的,只能阻止扁平的对象
nextState.Number == this.state.Number
如果调用层次比较深
nextState.NumberObject.number == this.state.NumberObject.number
Number 是一个数字变量
NumberObject是一个
数字变量(number类型)和
这时候,因为两者都指向堆中的同一个
对于number,string,boolean,undefined,null这些基本类型变量,值存在栈中
对于object,Array,function这些引用类型变量,引用存在栈中,而不同的引用却可以指向堆内存中的同一个
那么,问题就来了
怎么样才能取到不同的NumberObject呢?
四种方法:
1、ES6的扩展语法Object.assign()
2、深拷贝/浅拷贝或利用JSON.parse(JSON.stringify(data))相当于深拷贝,但使用受一定限制
3、引入immutable.
4、继承react的PureComponent组件(代替Component)
在
为了解决这种问题,出现了immutable对象,每次修改immutable对象都会创建一个新的不可变对象,而老的对象不会改变。
immutable.js主要有三大特性:
Persistent data structure (持久化数据结构)
structural sharing (结构共享)
support lazy operation (惰性操作)
Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享
三个最重要的数据结构: Map List Set
Map:键值对集合,对应于 Object,ES6 也有专门的 Map 对象
List:有序可重复的列表,对应于 Array
Set:无序且不可重复的列表
//Map() 原生object转Map对象 (只会转换第一层,注意和fromJS区别)
immutable.Map({name:'danny', age:18})
//List() 原生array转List对象 (只会转换第一层,注意和fromJS区别)
immutable.List([1,2,3,4,5])
//fromJS() 原生js转immutable对象 (深度转换,会将内部嵌套的对象和数组全部转成immutable)
immutable.fromJS([1,2,3,4,5]) //将原生array --> List
immutable.fromJS({name:'danny', age:18}) //将原生object --> Map
//toJS() immutable对象转原生js (深度转换,会将内部嵌套的Map和List全部转换成原生js)
immutableData.toJS();
//查看List或者map大小
immutableData.size 或者 immutableData.count()
// is() 判断两个immutable对象是否相等
immutable.is(imA, imB);
//merge() 对象合并
var imA = immutable.fromJS({a:1,b:2});
var imA = immutable.fromJS({c:3});
var imC = imA.merge(imB);
console.log(imC.toJS()) //{a:1,b:2,c:3}
对于两个一样的数据,只有通过equals进行比较才是相等的 == ===都不行
如果 某个是另一个克隆出来的,那么全部都相等
push添加 unshift在头部添加 concat组合 返回的是新数据,而不是数据的长度
//增删改查(所有操作都会返回新的值,不会修改原来值)
var immutableData = immutable.fromJS({
a:1,
b:2,
c:{
d:3
}
});
var data1 = immutableData.get('a') // data1 = 1
var data2 = immutableData.getIn(['c', 'd']) // data2 = 3 getIn用于深层结构访问
var data3 = immutableData.set('a' , 2); // data3中的 a = 2
var data4 = immutableData.setIn(['c', 'd'], 4); //data4中的 d = 4
var data5 = immutableData.update('a',function(x){return x+4}) //data5中的 a = 5
var data6 = immutableData.updateIn(['c', 'd'],function(x){return x+4}) //data6中的 d = 7
var data7 = immutableData.delete('a') //data7中的 a 不存在
var data8 = immutableData.deleteIn(['c', 'd']) //data8中的 d 不存在复制代码
优点:
降低mutable带来的复杂度
节省内存
历史追溯性(时间旅行):时间旅行指的是,每时每刻的值都被保留了,想回退到哪一步只要简单的将数据取出就行,想一下如果现在页面有个撤销的操作,撤销前的数据被保留了,只需要取出就行,这个特性在redux或者flux中特别有用
拥抱函数式编程:immutable本来就是函数式编程的概念,纯函数式编程的特点就是,只要输入一致,输出必然一致,相比于面向对象,这样开发组件和调试更方便
缺点:
需要重新学习api
容易与原生对象混淆:由于api与原生不同,混用的话容易出错。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持
react htmlh1无效,详解react阻止无效重渲染的多种方式_而已_前端开发者相关推荐
- React Router路由详解
React Router路由详解 一.基础 1.安装使用 2.React Router 中通用的组件 路由组件 BrowserRouter 和 HashRouter 路径匹配组件: Route 和 S ...
- android 回退函数,详解React Native监听Android回退按键与程序化退出应用
详解React Native监听Android回退按键与程序化退出应用 发布时间:2020-09-29 09:25:52 来源:脚本之家 阅读:137 作者:lqh 详解React Native监听A ...
- React 路由react-router-dom详解
React 路由react-router-dom详解 ( 路由嵌套 + 路由传参 + 路由权限 + 路由优化 按需导入 + 404页面 ) 前面我们先了解一下 路由是什么? 路由分类有哪些?内置API ...
- 视频教程-React Hooks 案例详解(React 进阶必备)-其他
React Hooks 案例详解(React 进阶必备) Leo 1978年8月生,河北石家庄人. 曾任职中软股份. 计算科学导师: 刘坤起博士. 开发的<电商分销系统>获得淘宝Top10 ...
- 回退监听android,详解React Native监听Android回退按键与程序化退出应用
详解React Native监听Android回退按键与程序化退出应用 前言 我们知道Android回退按键,会控制页面返回, 并且退出应用并非真正意义退出,仍在后台运行,所以在某些场景下需要监控an ...
- python open 打开是什么类型的文件-详解Python中open()函数指定文件打开方式的用法...
文件打开方式 当我们用open()函数去打开文件的时候,有好几种打开的模式. 'r'->只读 'w'->只写,文件已存在则清空,不存在则创建. 'a'->追加,写到文件末尾 'b'- ...
- WebSocket安卓客户端实现详解(一)–连接建立与重连
http://blog.csdn.net/zly921112/article/details/72973054 前言 这里特别说明下因为WebSocket服务端是公司线上项目所以这里url和具体协议我 ...
- tablewidget 行数自适应_PS滤镜知识:详解自适应广角滤镜的概括以及使用方式。...
PS滤镜知识学习:详解自适应广角滤镜的概括以及使用方式."自适应广角"滤镜是Photoshop CS6中新增的滤镜,使用该滤镜可以拉直在使用广角镜头或鱼眼镜|头时产生的弯曲效果,也 ...
- python解释器在哪里_详解查看Python解释器路径的两种方式
进入python的安装目录, 查看python解释器 进入bin目录 # ls python(看一下是否有python解释器版本) # pwd (查看当前目录) 复制当前目录即可 1. 通过脚本查看 ...
最新文章
- mysql $区别_mysql 与oracle区别
- BZOJ.4144.[AMPPZ2014]Petrol(Kruskal重构树)
- 【PC工具】图片批量添加水印工具,绿色免安装工具软件,妈妈再也不用担心我.....
- sizzle分析记录:getAttribute和getAttributeNode
- 用JavaScript实现2+2=5的奥秘
- python开发跟淘宝有联系没_Python爬取淘宝店铺和评论
- c语言为什么运行慢,【图片】今天写几个性能测试,为什么C语言跑得这么慢呢??【c语言吧】_百度贴吧...
- 清理服务器挖矿木马病毒
- red5 1.0.7 集成tomcat 并且 进行整合 官方例子oflaDemo
- C语言编程学习制作最好玩的报数游戏
- 论机器学习中数据的重要性
- linux 关闭系统中多余的服务
- mysql 怎么加上撇号_php - 如何在写入Mysql数据库时处理撇号
- html两行字的上下间隔,css字体上下间距怎么调?
- 快速排序--QuickSort()--递归版本
- 基于Linux中的通讯录管理系统(C语言+双向循环链表+MySQL)
- 软工实践第二次作业-黄紫仪
- 关于关联表用code还是id的见解
- [GoFrame学习] 报错 implement not found for interface IMenu, forgot register?
- Python ROS键盘控制机械臂