React state 虚拟DOM Refs key
state与props
一句话说明他们直接的关系:
一旦state或者props中的值改变,组件就会重新第哦啊用render方法
虚拟Dom
创建一个虚拟DOM需要这么写:
React.createElement(‘li’,{onClick:this.addList.bind(this)},`${你好}`)
但是我们更多的是用语法糖写:
<li onClick={this.addList}>你好</li>
二者的效果是一样的都是生成虚拟DOM
实际的dom操作:
const li = document.createElement('p')
li.innreHTML:'hello'
document.querySelector('ul').appendChild(li)
虚拟Dom就是js对象:
//name就是你创建的元素
//attr:就是你元素所有的属性,
//content:就是元素中的内容
let li={name:'li',attr:{},content:'hello'}
用虚拟Dom:(流程:)
- state数据
- JSX模板
- 数据+模板结合,生成虚拟DOM(虚拟DOM就是一个js对象,用它来描述真实的DOM),比如:
['div',{id:'abc'},{'span',{},'hello'}] // (损耗了极小的性能)
4.用虚拟DOM的结果生成真实的DOM
<div id='abc'><span>hello</span></div>
5.state发生变化
6.数据+模板生成新的虚拟DOM(极大地提升了性能)
['div',{id:'abc'},{'span',{},'bye'}]
7.比较原始虚拟DOM新的虚拟DOM的区别,找到区别是span中的内容(极大提升了性能)
8.直接操作DOM,改变span中的内容
总结:
react根据state+JSX模板生成虚拟DOM,用虚拟DOM来生成真实的DOM,这样减少了性能的损耗。
在state发生变化时,react会从你原来的虚拟DOM中找到变化的值从而替换掉,(不会从新生成所有的虚拟DOM来替换)直接操作DOM中,改变内容。
React中 state变化是虚拟DOM如何进行比较如何替换呢?
虚拟DOM中的diff算法:
diff算法中只会比较同层级的元素,一旦发现某一级别之间有所不同,,则会弃置其子级,直接用新的差异的一级以及其下的所有子级替换老的。 好处:算法简单,也就提高了比对速度,因此最后也就提升了性能
key的作用
key的作用:当进行虚拟DOM进行比对时,我们需要比较出相同的元素和不同的,没有key我们就很难一一对应,需要做两层循环比较,用上key值则我们可以清楚比较出哪一个新增或者删除了什么。
不建议使用index来做key值,因为index不是唯一的。
例如:如果我们创建了a、b、c三个item,key的值分别为index:0、1、2。当我们删除了a,则b、c的key值就会变为0、1这样可以就不是唯一的了。(建议使用id来做key值)
我来举一个例子说明一下不改变state的值,而是使用控制DOM来删除标签页面有什么变化?
我使用操作DOM删除元素后state中的数据没有变化,因为我只是删除了DOM没有改变state中的数据
我们在添加一个元素后,改变了state中的数据,所有要执行render重新渲染,会循环state中的list,所以应该循环出4个li标签,但是现在地3个没有渲染出来这个就是问题?
这个问题的原因:
虚拟DOM创建真实的DOM
就是你只是删除了DOM而没有改变state中的值,所有原来虚拟DOM没有改变,现在新增加一个元素,也就是新生成了一个虚拟DOM,新生成的虚拟DOM回去对比旧的,发现数据只是新增了一条,其余没有改变。所以原来的虚拟DOM没有变也就会认为原来的DOM没有变所以只是在旧的DOM后加入了一条数据
创建Refs
- 在constructor(props)中创建
this.ulRef=React.createRef()
- 在标签中使用ref
<input ref={this.ulRef}>
- 在事件中获取
this.ulRef.current
(this.ulRef.current获取到input本身)