经典面试题:
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
- // <li key=0>张三,18li>
- // <li key=1>张四,19li>
- // 页面更新后数据
- // { id: 3, name: "张五", age: 20 },
- // { id: 1, name: "张三", age: 18 },
- // { id: 2, name: "张四", age: 19 },
- // 页面更新后虚拟dom
- // <li key=0>张五,20li>
- // <li key=1>张三,18li>
- // <li key=2>张四,19li>
- // 此时新旧虚拟dom根据key进行对比发现里面的内容变了,便替换掉了页面中之前真实的dom,而这意味着两条重复的数据没有重复利用,当数据庞大时效率可想而知
- add() {
- const { persons } = this.state
- const p = { id: persons.length + 1, name: "张五", age: 20 }
- this.setState({
- persons: [p, ...persons]
- })
- }
- render() {
- return (
- <div>
- <button onClick={() => { this.add() }}>点击添加一个张五button>
- <ul>
- {
- this.state.persons.map((personObj, index) => {
- return <li key={index}>{personObj.name},{personObj.age}li>
- })
- }
- ul>
- div>
- )
- }
- }
- 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
- // <li key=1>张三,18li>
- // <li key=2>张四,19li>
- // 页面更新后数据
- // { id: 3, name: "张五", age: 20 },
- // { id: 1, name: "张三", age: 18 },
- // { id: 2, name: "张四", age: 19 },
- // 页面更新后虚拟dom
- // <li key=3>张五,20li>
- // <li key=1>张三,18li>
- // <li key=2>张四,19li>
- // 此时新旧虚拟dom根据key进行对比发现没有的便在页面渲染,有的并且内容一样的便用之前真实的dom
- add() {
- const { persons } = this.state
- const p = { id: persons.length + 1, name: "张五", age: 20 }
- this.setState({
- persons: [p, ...persons]
- })
- }
- render() {
- return (
- <div>
- <button onClick={() => { this.add() }}>点击添加一个张五button>
- <ul>
- {
- this.state.persons.map((personObj) => {
- return <li key={personObj.id}>{personObj.name},{personObj.age}li>
- })
- }
- ul>
- div>
- )
- }
- }