列表渲染、虚拟DOM对比

92 阅读2分钟
    <div id="root">
        <li v-for="p in persons" :key="id">
            {{p.name}}-{{p.age}}
        </li>
    </div>


    let vm = new Vue({
        el: "#root",
        data: {
            persons: [
                { id: '001', name: '张三', age: 18 },
                { id: '002', name: '李四', age: 19 },
                { id: '003', name: '王总', age: 18 },
            ]},})

v-for=“(a,index) in arr ”:key=“index”

可以接受两个参数,一个是内容一个是索引

可以遍历数组、对象或字符串,或者遍历指定次数 v-for=“(a,b) of 5”

key是虚拟Dom对象的表示,当数据发生变化时,Vue会根据新数据生成新的虚拟Dom,然后进行新旧虚拟dom对比

根据key的值,虚拟dom对比(diff)

对比规则:

  • 旧虚拟dom中找到了新虚拟dom相同的key:若虚拟dom内容没变,直接使用之前的真实dom!若聂荣变了,则生成新的真实dom,随后替换掉页面中之前的真实dom
  • 未找到相同的key:创建新的真实dom,随后渲染到页面

index作为key

如果我们没有写key,Vue自动补的key是index

逆序添加复用率低,当用户操作输入型节点时、Vnode并不改变

IMG_0292(20211001-140146).PNG 图片来源:尚硅谷Vue2.0+3.0全套教程 P30 key的作用与工作原理

id作为key

复用率高,应该不出问题 IMG_0293(20211001-140839).PNG

开发中如何选取key?

最好使用每条数据的唯一标识作为key

如果不存在对数据的逆序添加、逆序删除灯破坏顺序操作,仅用于渲染列表用于展示,使用index作为key没啥问题

列表过滤

实现模糊搜索

watch实现

    <div id="root">
        <input type="text" placeholder="请输入名字">
        <li v-for="(p,index) in filPersons" :key="index">
            {{p.name}}-{{p.age}}
        </li>
    </div>


    let vm = new Vue({
        el: "#root",
        data: {

            keyword: "",
            persons: [
                { id: '001', name: '马冬梅', age: 18, },
                { id: '002', name: '周冬雨', age: 19, },
                { id: '003', name: '周杰伦', age: 23, },
                { id: '003', name: '温兆伦', age: 28, },
            ],
            filPersons: []
        },
        watch: {
            keyword: {
                immediate: true,
                handler(val) {
                    this.filPersons = this.persons.filter((p) => {
                        return p.name.indexOf(val) !== -1
})  } } } })

‘abcd’.indexOf('')结果是0,不是-1

immediate: true 先用空字符串过滤一遍

computed实现

    <div id="root">
        <input type="text" placeholder="请输入名字" v-model="keyword">
        <li v-for=" (p,index) in filPersons" :key="index">
            {{p.name}}-{{p.age}}
        </li>
    </div>


    let vm = new Vue({
        el: "#root",
        data: {

            keyword: "",
            persons: [
                { id: '001', name: '马冬梅', age: 18, },
                { id: '002', name: '周冬雨', age: 19, },
                { id: '003', name: '周杰伦', age: 23, },
                { id: '003', name: '温兆伦', age: 28, },
            ],
        },
        computed: {
            filPersons() {
                return this.persons.filter((p) => {
                    return p.name.indexOf(this.keyword) !== -1
                })}}})