列表渲染,key作用与原理,列表过滤,列表排序

Posted 阿瞒有我良计15

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了列表渲染,key作用与原理,列表过滤,列表排序相关的知识,希望对你有一定的参考价值。

v-for指令:

  • 用于展示列表数据
  • 语法:<li v-for="(item, index) in xxx" :key="yyy">,其中key可以是index,也可以是遍历对象的唯一标识
  • 可遍历:数组、对象、字符串(用的少)、指定次数(用的少)

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <!--    遍历列表-->
    <h2>人员列表</h2>
    <ul>
        <li v-for="p in persons" :key="p.id">p.name - p.age</li>
    </ul>

    <!--    <h2>人员列表</h2>-->
    <!--    <ul>-->
    <!--        <li v-for="(p,index) in persons" :key="index">p.name - p.age</li>-->
    <!--    </ul>-->

    <!--    <h2>人员列表</h2>-->
    <!--    <ul>-->
    <!--        <li v-for="(a,b,c) in persons">a - b &#45;&#45; c</li>-->
    <!--    </ul>-->

    <!--    遍历对象-->
    <h2>汽车信息</h2>
    <ul>
        <li v-for="(value,k) in cars" :key="k">k -- value</li>
    </ul>

    <!--    遍历字符串-->
    <h3>测试遍历字符串</h3>
    <ul>
        <li v-for="(char,index) in strs" :key="index">
            char -- index
        </li>
    </ul>

    <!--    遍历指定次数-->
    <h2>测试遍历指定次数</h2>
    <ul>
        <li v-for="(number,index) in  5">number -- index</li>
    </ul>
</div>
<script>
    Vue.config.productionTip = false
    const vm = new Vue(
        el: "#app",
        data: 
            persons: [
                id: '001', name: '张三', age: 18,
                id: '002', name: '李四', age: 19,
                id: '003', name: '王五', age: 20
            ],
            cars: 
                name: 'aodi',
                price: '18',
                color: 'balck'
            ,
            strs: 'hello'
        
    )
</script>
</body>
</html>

key作用与原理

react、vue中的key有什么作用?(key的内部原理)

虚拟DOM中key的作用:key是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

对比规则:

旧虚拟DOM中找到了与新虚拟DOM相同的key:

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

用index作为key可能会引发的问题:

若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低
若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题
 

开发中如何选择key?

最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值
如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,使用index作为key是没有问题的
 

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <h2>人员列表</h2>
    <button @click.once="add">添加老刘</button>
    <ul>
        <h3>index作为key</h3>
        <!--        index作为key-->
        <li v-for="(p,index) in persons" :key="index">
            p.name - p.age<input type="text">
        </li>
    </ul>

    <ul>
        <!--        p.id作为key-->
        <h3>p.id作为key</h3>
        <li v-for="(p,index) in persons" :key="p.id">
            p.name - p.age<input type="text">
        </li>
    </ul>
</div>
<script>
    Vue.config.productionTip = false
    const vm = new Vue(
        el: "#app",
        data: 
            persons: [
                id: '001', name: '张三', age: 18,
                id: '002', name: '李四', age: 19,
                id: '003', name: '王五', age: 20
            ]
        ,
        methods: 
            add() 
                const p = id: '004', name: '老刘', age: 40
                this.persons.unshift(p)
            
        
    )
</script>
</body>
</html>

列表过滤

方法一:使用监听属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入姓名" v-model="keyWord">
    <ul>
        <li v-for="(p,index) in filpersons" :key="p.id">
            p.name - p.age - p.sex
        </li>
    </ul>
</div>
<script>
    Vue.config.productionTip = false
    const vm = new Vue(
        el: "#app",
        data: 
            keyWord: "",
            persons: [
                id: '001', name: '马冬梅', age: 19, sex: '女',
                id: '002', name: '周冬雨', age: 20, sex: '女',
                id: '003', name: '周杰伦', age: 21, sex: '男',
                id: '004', name: '温兆伦', age: 22, sex: '男'
            ],
            filpersons: []
        ,
        watch: 
            keyWord: 
                immediate: true,
                handler(newval) 
                    this.filpersons = this.persons.filter((p) => 
                        return p.name.indexOf(newval) !== -1
                    )
                
            
        
    )
</script>
</body>
</html>

方法二:使用计算属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入姓名" v-model="keyWord">
    <ul>
        <li v-for="(p,index) in filpersons" :key="p.id">
            p.name - p.age - p.sex
        </li>
    </ul>
</div>
<script>
    Vue.config.productionTip = false
    const vm = new Vue(
        el: "#app",
        data: 
            keyWord: "",
            persons: [
                id: '001', name: '马冬梅', age: 19, sex: '女',
                id: '002', name: '周冬雨', age: 20, sex: '女',
                id: '003', name: '周杰伦', age: 21, sex: '男',
                id: '004', name: '温兆伦', age: 22, sex: '男'
            ],
        ,
        computed: 
            filpersons() 
                return this.persons.filter((p) => 
                    return p.name.indexOf(this.keyWord) !== -1
                )
            
        
    )
</script>
</body>
</html>

列表排序

先过滤在排序

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入姓名" v-model="keyWord">
    <button @click="sortType = 2">年龄升序</button>
    <button @click="sortType = 1">年龄降序</button>
    <button @click="sortType = 0">原顺序</button>
    <ul>
        <li v-for="(p,index) in filpersons" :key="p.id">
            p.name - p.age - p.sex
        </li>
    </ul>
</div>
<script>
    Vue.config.productionTip = false
    const vm = new Vue(
        el: "#app",
        data: 
            keyWord: "",
            sortType: 0,// 0原顺序  1降序 2升序
            persons: [
                id: '001', name: '马冬梅', age: 19, sex: '女',
                id: '002', name: '周冬雨', age: 20, sex: '女',
                id: '003', name: '周杰伦', age: 21, sex: '男',
                id: '004', name: '温兆伦', age: 22, sex: '男'
            ],
        ,
        computed: 
            filpersons() 
                const arr = this.persons.filter((p) => 
                    return p.name.indexOf(this.keyWord) !== -1
                )
                if (this.sortType) 
                    arr.sort((a, b) => 
                        return this.sortType === 1 ? b.age - a.age : a.age - b.age
                    )
                
                return arr
            
        
    )
</script>
</body>
</html>

Vue 条件渲染,列表渲染,key的作用和原理,列表过滤,列表排序,Vue监测数据原理和注意事项

1. 条件渲染

使用v-show做条件渲染,使用v-if做条件渲染,v-if是连结构也能消除的。

v-if,v-else-if,v-else是一起的。其中有一个验证成功,其他的就不会验证了。注意这些内容必须紧紧靠在一起!!

但在这我们可以用template实现。不会破坏dom结构 ,此外template不能和v-show配合。
源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=
    , initial-scale=1.0">
    <title>条件渲染</title>    
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <style>
        /* h2{
            visibility: hidden;
            color: transparent;
            display: none;
            以上这些都可以达到不显示的效果。
        } */
    </style>
</head>
<body>
    <div id="root">
        <!-- 使用v-show做条件渲染 -->
        <!-- v-show为true显示,为false隐藏。 -->
        <h2 v-show="false">欢迎来到,{{name}}</h2>
        <h2 v-show="1 === 1">欢迎来到,{{name}}</h2>
        <hr>
        <!-- 使用v-if做条件渲染,v-if是连结构也能消除的 -->
        <h2 v-if="false">欢迎来到,{{name}}</h2>
        <h2 v-if="1 === 1">欢迎来到,{{name}}</h2>
        <hr>

        <h2>当前的n值为:{{n}}</h2>
        <button @click="n++">n加1</button>

        <!-- v-if,v-else-if,v-else是一起的。其中有一个验证成功,其他的就不会验证了。注意这些内容必须紧紧靠在一起!! -->
        <div v-if=" n === 1">Angular</div>
        <div v-else-if=" n === 2">React</div>
        <div v-else-if=" n === 3">Vue</div>
        <div v-else>哈哈</div>

        <hr>
        <!-- 对于存在多个的标签我们可以定义div来实现,但这种实现修改了dom结构。 -->
        <div v-if="n === 1">
            <h2>你好</h2>
            <h2>我是</h2>
            <h2>div</h2>
        </div>
        <!-- 但在这我们可以用template实现。不会破坏dom结构 ,此外template不能和v-show配合。-->
        <template v-if="n===1">
            <h2>你好</h2>
            <h2>我是</h2>
            <h2>template</h2>
        </template>
    </div>
    
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el:"#root",
            data:{
                name:"北京大学",
                n:0
            }
        });
    </script>
</body>
</html>

2. 列表渲染

形式上分为下面几种:

使用v-for遍历数组。
使用v-for遍历对象。
遍历字符串 (用的少)。
遍历指定次数 (用的少)。

注意事项:
一定注意下面的注释,value,key,index的各个关系位置,搞清楚!!

源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>列表渲染</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <!-- 使用v-for遍历数组 -->
        <h2>人员列表(遍历数组)</h2>
        <ul>
            <!-- 这里的p和index指的就是内容和索引值,此外这里的key我们可以用index来区分,也可以用p.id这样的形式来。 -->
            <li v-for="(p,index) in persons" :key="index">{{p.name}}-{{p.age}} ---索引值:{{index}}</li>
             <hr> <!--这里的in也可以用of来对待一样的效果 -->
            <li v-for="(p,index) in persons" :key="p.id">{{p.name}}-{{p.age}} ---索引值:{{index}}</li>
        </ul>

        <!-- 使用v-for遍历对象 -->  
        <!-- 对象这里的value和key的相关了 -->
        <h2>汽车信息(遍历对象)</h2>
        <ul>
            <li v-for="(value,key) in car" :key="key">value:{{value}}} ---key:{{key}}</li>
        </ul>

        <!-- 遍历字符串 (用的少)-->
        <h2>遍历字符串</h2>
        <ul>
            <li v-for="(char,index) in str" :key="index">{{char}}----{{index}}</li>
        </ul>

        <!-- 遍历指定次数  (用的少)-->
        <h2>遍历指定次数</h2>
        <ul>
            <li v-for="(number,index) in 5" :key="index">{{number}}----{{index}}</li>
        </ul>
    </div>

    <script>
        Vue.config.productionTip = false;
        new Vue({
            data:{
                persons:[
                    {id:"001",name:"张三",age:18},
                    {id:"002",name:"李四",age:19},
                    {id:"003",name:"王五",age:20}
                ],
                car:{
                    name:"奥迪",
                    price:"70w",
                    color:'黑色'
                },
                str:'hello'
            }
        }).$mount('#root');
    </script>
</body>
</html>

3. key的作用和原理

需要我们注意的是,在我们定义key时,使用index和id的这种作法有什么区别,什么使用用index?什么使用用id?

注意事项:
如果没有定义key属性,默认就是index作为key的值,作为唯一标识。

3.1 index作为key 的效果和问题

一定理解好虚拟DOM和真实DOM,以及中间的虚拟DOM对比算法。

上图对比虚拟DOM时,对比了三部分,第一个key,第二个内容(张三–18),第三个input标签。大体上就这样一步步对比,在这key作为唯一标识,内容不同就会覆盖。注意这里我们添加的时真实DOM中的input,在虚拟dom中input还是一样的,因此直接会使用真实DOM中的内容。

这里使用index来操作的话,就会出现这种问题:

源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>列表渲染</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>人员列表(遍历数组)</h2>
        <button v-on:click.once="add">添加个人</button>
        <ul>
            <li v-for="(p,index) in persons" :key="index">
                {{p.name}}-{{p.age}} ---索引值:{{index}}
                <input type="text">
            </li>
        </ul>
    </div>

    <script>
        Vue.config.productionTip = false;
        new Vue({
            data:{
                persons:[
                    {id:"001",name:"张三",age:18},
                    {id:"002",name:"李四",age:19},
                    {id:"003",name:"王五",age:20}
                ]
            },
            methods: {
                add(){
                        const p = {id:'004',name:'老李',age:"30"};
                        this.persons.unshift(p); //unshift(xxx),将xxx插入 arrayObject 的头部,并将已经存在的元素顺次地移到较高的下标处,以便留出空间
                    }
            },
        }).$mount('#root');
    </script>
</body>
</html>


点击添加个人后,就会出现下面这样的问题。

一定注意index这样类似的改变顺序的错误。

3.1 id作为key 的效果(最佳)


使用id来实现,就可以避免上面index所出现的问题。

源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>列表渲染</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>人员列表(遍历数组)</h2>
        <button v-on:click.once="add">添加个人</button>
        <ul>
            <li v-for="(p,index) in persons" :key="p.id">
                {{p.name}}-{{p.age}} ---索引值:{{index}}
                <input type="text">
            </li>
        </ul>
    </div>

    <script>
        Vue.config.productionTip = false;
        new Vue({
            data:{
                persons:[
                    {id:"001",name:"张三",age:18},
                    {id:"002",name:"李四",age:19},
                    {id:"003",name:"王五",age:20}
                ]
            },
            methods: {
                add(){
                        const p = {id:'004',name:'老李',age:"30"};
                        this.persons.unshift(p); //unshift(xxx),将xxx插入 arrayObject 的头部,并将已经存在的元素顺次地移到较高的下标处,以便留出空间
                    }
            },
        }).$mount('#root');
    </script>
</body>
</html>

3.3 两个总结

4. 列表过滤

4.1 通过watch,filter和indexOf()来实现

我们通过使用Vue,来实现一个模糊查询。通过watch,filter和indexOf来实现,一定注意indexOf在空字符串情况下怎么操作的。

源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>列表渲染</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>人员列表</h2>
        <input type="text" placeholder="请输入名字" v-model="keyWord"> 
        <ul>
            <li v-for="(p,index) in filePersons" :key="index">
                {{p.name}}-{{p.age}}-{{p.sex}}
            </li>
        </ul>
    </div>

    <script>
        Vue.config.productionTip = false;
        new Vue({
            data:{
                keyWord:'',
                persons:[
                    {id:"001",name:"马冬梅",age:18,sex:"女"},
                    {id:"002",name:"周冬雨",age:19,sex:"女"},
                    {id:"003",name:"周杰伦",age:20,sex:"男"},
                    {id:"004",name:"温兆伦",age:20,sex:"男"}
                ],
                filePersons:[]
            },
            watch:{
                //通过监视keyWord来实现功能。
                keyWord:{
                    //这里的immediate和indexOf相结合可以完美达到在页面显示的内容。
                    //immediate会先调用一下handler函数,同时indexOf在val为空字符串的情况下,刚好可以得到所有内容。
                    immediate:true,
                    handler(val){
                        console.log("修改了");
                        this.filePersons = this.persons.filter((p)=>{
                            return p.name.indexOf(val) !== -1;
                            //注意indexOf()如果不包含返回-1,包含返回对应的索引值。
                            //此外,我们定义空字符串也是包含的,索引值为0.
                        });
                    }
                }
            }
        }).$mount('#root');
    </script>
</body>
</html>

4.2 通过使用computed,filter和indexOf()来实现

#region和#endregion,这两个可以将注释的内容折叠起来。
computed比watch要简单一些,推荐使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>列表渲染</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>人员列表</h2>
        <input type="text" placeholder="请输入名字" v-model="keyWord"> 
        <ul>
            <li v-for="(p,index) in filePersons" :key="index">
                {{p.name}}-{{p.age}}-{{p.sex}}
            </li>
        </ul>
    </div>

    <script>
        Vue.config.productionTip = false;

        new Vue({
            data:{
                keyWord:'',
                persons:[
                    {id:"001",name:"马冬梅",age:18,sex:"女"},
                    {id:"002",name:"周冬雨",age:19,sex:"女"},
                    {id:"003",name:"周杰伦",age:20,sex:"男"},
                    {id:"004",name:"温兆伦",age:20,sex:"男"}
                ],
            },
            computed:{
                filePersons(){
                    //需要给filePersons返回我们过滤后的结果。
                    return this.persons.filter((p)=>{
                        //这里的return是返回的filter函数中的值。
                        //此外我们可以用this.keyWord来替代。
                        return p.name.indexOf(this.keyWord) !== -1;
                    });
                }
            }
        }).$mount('#root');
        new Vue
    </script>
</body>
</html>

5. 列表排序

需要注意的是sort()函数判断a-b升序,b-a降序。以及下面所实现的形式。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>列表渲染</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>人员列表</h2>
        <input type="text" placeholder="请输入名字" v-model="keyWord"> 
        <button @click="sortType = 2">年龄升序</button>
        <button @click="sortType = 1">年龄降序</button>
        <button @click="sortType = 0">原顺序</button>
        <ul>
            <li v-for="(p,index) in filePersons" :key="index">
                {{p.name}}-{{p.age}}-{{p.sex}}
            </li>
        </ul>
    </div>

    <script>
        Vue.config.productionTip = false;

        new Vue({
            data:{
                keyWord:'',
                sortType:0,
                persons:[
                    {id:"001",name:"马冬梅",age:30,sex:"女"},
                    {id:"002",name:"周冬雨",age:21,sex:"女"},
                    {id:"003",name:"周杰伦",age:23,sex:"男"},
                    {id:"004",name:"温兆伦",age:20,sex:"男"}
                ],
            },
            computed:{
                filePersons(){
                    //需要给filePersons返回我们过滤后的结果。
                    const arr =  this.persons.filter((p)=>{
                        //这里的return是返回的filter函数中的值。
                        //此外我们可以用this.keyWord来替代。
                        return p.name.indexOf(this.keyWord) !== -1;
                    });

                    // 判断一下是否需要排序
                    if(this.sortType){
                        //sort()函数判断a-b升序,b-a降序。
                        arr.sort((a,b)=>{
                            return this.sortType === 1 ? b.age-a.age : a.age-b.age; 
                        });
                    }

                    return arr;
                }
            }
        }).$mount('#root');
        new Vue
    </script>
</body>
</html>

6. 深度了解Vue如何监测data对象中的数据改变

需要了解一下Observer对象和它的构造函数。下面我们重写一下它的Observer。

我们平时所看到的vm._data的本质就是Observer对象。

源码:
通过Observer来模拟一下,data和vm._data,obs之间的一个数据监测(被修改什么的)。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        let data = {
            name:"清华大学",
            address:"北京"
        }

        //通过Observer来模拟一下,data和vm._data,obs之间的一个数据监测(被修改什么的)。
        const obs = new Observer(data);
        console.log(obs);

        let vm = {};
        vm._data = data = obs;

        function Observer(obj){
            //Object.keys(xxx)可以汇总xxx对象中的所有的属性形成一个数组
            const keys = Object.keys(obj);
            keys.forEach((k)=>{
                Object.defineProperty(this,k,{
                    get(){
                        return obj[k];
                    },
                    set(val){
                        console.log(`${k}被修改了,我要去解析模板,生成虚拟DOM...我要开始了`)
                        obj[k] = val;
                    }
                })
            })

        }
    </script>
</body>
</html>

上面的代码虽然实现了,监测data中的数据变化,但是如果遇到对象中包含对象,数组等特例(见下图),就不行了,但Vue中的监视原理就是这样的。这里我们只是了解一下他的特性而已。

7. Vue中set方法使用的方式和注意事项

在这具体的set修改方式有两种:如下图一样:

1. Vue.set(vm._data.student.‘sex’,‘男’)
2. vm.$set(vm._data.student,‘sex’,‘女’)



因为上面的vm._data.student 和vm.student 是数据代理的,所以他们两个是一样的。


因此,我们直接就可以写vm.student来设置属性什么的了。

源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <title>Document</title>
</head>
<body>
    <div id="root">
        <h1>学校信息</h1>
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
        <h2>班主任:{{leader}}</h2>
        <hr>
        <h1>学生信息</h1>
        <button @click = 'addSex'>添加一个性别属性,默认为男</button>
        <h2>学生姓名:{{student.name}}</h2>
        <h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
        <h2>学生年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}</h2>
        <h2>朋友们</h2>
        <ul>
            <li v-for="(f,index) in student.friends" :key="index">
                {{f.name}} -- age:{{f.age}}
            </li>
        </ul>
    </div>
</body>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el:"#root",
            data:{
                name:"清华大学",
                address:"北京",
                student:{
                    name:'tom',
                    sex:undefined,
                    age:{
                        rAge:40,
                        sAge:29
                    },
                    friends:[
                        {name:'jerry',age:35},
                        {name:"tony",age:36}
                    ]
                }
            },
            methods: {
                addSex(){
                    //我们可以直接用这两种方式来定义怎加属性。
                    // Vue.set(this.student,'sex','男');
                    this.$set(this.student,"sex",'女');
                }
            },
        });
    </script>
</html>

我们直接给data对象设置属性,是不可以的!!!

8. Vue 对于data中数组的监测原理和注意事项

对于数组Vue并没有给他们生成一定的get和set。

既然没有get和set,那如何得到响应监测的目的呢?
可能最先想到的就是通过索引值的方法来达到效果,这样是直接修改了数组,页面并不会监测到!!也就是页面并不会变化!

解决上面的问题办法就是通过下面的这7个方法,调用它们操作数组来达到监测效果。


注意事项:

这里的push和array.prototype.push是不一样的。前者是被Vue管理的push。被Vue管理的push包含了array.prototype.push的原始功能,还包装了一些类似重新解析模板的一些功能。

除了上面的7个数组的方法可以监测修改,还可以通过Vue.set()和vm.$set()来操作修改,也是没问题的。

注意事项:

数组中的对象的属性是包含get和set,因此数组中对象本身是没有get和set监视,但对象内部属性有get和set。如下图:

9. 数据监测总结


数据劫持就是将原来data内的数据,加工成了vm._data这样的数据的过程叫做数据劫持,因为中间给它添加了很多Vue方面的功能。

以上是关于列表渲染,key作用与原理,列表过滤,列表排序的主要内容,如果未能解决你的问题,请参考以下文章

Vue -- 列表渲染(基本列表 & key的原理 & 列表过滤 & 列表排序 )

Vue基础(下):条件渲染列表渲染(key)过滤器内置和自定义指令

VUE:列表的过滤与排序

Vue 核心

Vue 学习总结笔记

Vue基础系列列表渲染-—v-forkey=列表过滤_监视属性实现_computed实现_列表实时排序