经典面试题:
1.react/vue中的key有什么作用?key的内部原理是什么?
2.为什么遍历列表时,key最好不要用index?
看完以下内容,轻松解决你对diff算法的认识以及以上两个常问问题。
虚拟DOM中key的作用:
1.当数据状态发生变化时,react/vue会根据新数据生成新的虚拟dom,随后会进行新旧dom的比较,比较规则如下:
①旧虚拟dom中找到了新虚拟dom相同的key:
(1)若虚拟dom中内容没变,直接使用之前的真实dom
(2)若虚拟dom中内容变了,则生成新的真实dom,并替换掉页面中之前的真实dom
②旧虚拟dom中未找到新虚拟dom相同的key:
(1)根据数据创建新的真实的dom,并渲染到页面
2.用index作为key可能会引发的问题
①若数据进行:逆序添加、逆序删除等破坏顺序的操作,此时会产生没有必要的真实的dom更新,虽然界面效果没什么问题,但效率低
②如果结构中还包含输入类的dom,会产生错误dom更新,界面会发生问题
③注意:如果不存在数据的逆序添加,逆序删除等破坏顺序性操作,仅用于渲染列表到页面,一般是没有问题的
3.开发中如何选择key值
①最好使用每条数据的唯一标识作为key,如id,身份证号等
②如果确定只是简单的展示数据,也可以用index
import React, { Component } from 'react'export default class ClassHanshu extends Component {constructor() {super()this.state = {persons: [{ id: 1, name: "张三", age: 18 },{ id: 2, name: "张四", age: 19 },]}}// 用index索引作为key时:// 初始数据: // { id: 1, name: "张三", age: 18 },// { id: 2, name: "张四", age: 19 },// 初始虚拟dom// 张三,18 // 张四,19 // 页面更新后数据// { id: 3, name: "张五", age: 20 },// { id: 1, name: "张三", age: 18 },// { id: 2, name: "张四", age: 19 },// 页面更新后虚拟dom// 张五,20 // 张三,18 // 张四,19 // 此时新旧虚拟dom根据key进行对比发现里面的内容变了,便替换掉了页面中之前真实的dom,而这意味着两条重复的数据没有重复利用,当数据庞大时效率可想而知add() {const { persons } = this.stateconst p = { id: persons.length + 1, name: "张五", age: 20 }this.setState({persons: [p, ...persons]})}render() {return ({this.state.persons.map((personObj, index) => {return - {personObj.name},{personObj.age}
})}
)}
}
import React, { Component } from 'react'export default class ClassHanshu extends Component {constructor() {super()this.state = {persons: [{ id: 1, name: "张三", age: 18 },{ id: 1, name: "张四", age: 19 },]}}// 用id作为key时:// 初始数据: // { id: 1, name: "张三", age: 18 },// { id: 2, name: "张四", age: 19 },// 初始虚拟dom// 张三,18 // 张四,19 // 页面更新后数据// { id: 3, name: "张五", age: 20 },// { id: 1, name: "张三", age: 18 },// { id: 2, name: "张四", age: 19 },// 页面更新后虚拟dom// 张五,20 // 张三,18 // 张四,19 // 此时新旧虚拟dom根据key进行对比发现没有的便在页面渲染,有的并且内容一样的便用之前真实的domadd() {const { persons } = this.stateconst p = { id: persons.length + 1, name: "张五", age: 20 }this.setState({persons: [p, ...persons]})}render() {return ({this.state.persons.map((personObj) => {return - {personObj.name},{personObj.age}
})}
)}
}