07-数组更新检测与Vue生命周期

6/3/2022

# 1, 数组响应式注意事项

# 1.1, 数组更新检测

数组更新检测

  • Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新
    • push()
    • pop()
    • shift()
    • unshift()
    • splice()
    • sort()
    • reverse()
  • 上面的方法会直接修改原来的数组
  • 某些方法不会替换原来的数组,而是会生成新的数组,比如 filter()、concat() 和 slice();
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
     <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
</head>
<body>  
    <!-- 定义的容器 -->
    <div id="app">
        <ul>
            <li>{{name}}</li>
            <li>{{age}}</li>
            <li>{{sex}}</li>
            <li>{{hobby}}</li>
        </ul>
        <button @click="updateHobby">修改睡觉为打代码</button>
    </div>

    <script>
        let vm = new Vue({
            el:"#app",
            data(){
                return {
                    name:"wc",
                    age:18,
                    sex:"man",
                    hobby:["睡觉","吃饭","打豆豆"]
                }
            },
            methods:{
                updateHobby(){
                    // 这样修改,数据已经变了,但是模板没有刷新
                    // 这个修改数据,并非是响应式的
                    // 如果数组中的数据是基本数据类型,通过索引去修改它,界面并不会更新
                    // this.hobby[0] = "打代码";

                    // 数据变了,界面也没有刷新
                    // 通过数组的length修改数据,并排是响应式的
                    // this.hobby.length = 2;

                    // 调用数组的push,pop方法,也是响应式的
                    // this.hobby.push("写代码")
                    // 下面的7个方法,会引起界面更新
                    // push()
                    // pop()
                    // shift()
                    // unshift()
                    // splice()
                    // sort()
                    // reverse()
                    // this.hobby.pop()
                    // this.hobby.splice(0,1,"打代码")

                    // map返回一个加工后的新数组
                    // console.log(this.hobby.map(item=>item=="睡觉" ? "打代码" : item));
                    this.hobby = this.hobby.map(item=>item=="睡觉" ? "打代码" : item);
                }
            }
        });
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
</head>

<body>
    <!-- 定义的容器 -->
    <div id="app">
        <p>a==>{{a}}</p>
        <p>a.b==>{{a.b}}</p>
        <p>a.b.c==>{{a.b.c}}</p>
        <hr>
        <p>{{arr}}</p>
        <button @click="handle">修改data中的数据</button>
    </div>

    <script>
        let vm = new Vue({
            el: "#app",
            data() {
                return {
                    // a是响应式数据   b也是响应式数据    c也是响应式数据
                    // 在data中,一个对象不管嵌套多深,所有数据都是响应式数据
                    a: {
                        b: {
                            c: 100
                        }
                    },
                    // 
                    arr: ["xq", 123, { name: 'wangcai' }, true]
                }
            },
            methods:{
                handle(){
                    // 数据变了,但是界面没有更新,不是响应式的
                    // this.arr[0] = "666";

                    // 调用数据的7个方法,是响应式的

                    // 如果数组中的元素是一个对象的话,通过索引去修改对象中的属性,也会引起界面的更新
                    this.arr[2].name = "xiaoqiang";
                }
            }
        });

        // 总结数据更新检测:
        //      在data中定义的数据都是响应式数据,有特殊情况:
        //           数组中的元素有可能是响应式的【数组中的元素是对象】,也有可能不是响应式的【基本类型】
        //           调用数组上的7个方法,也会引起界面更新
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

# 2, Vue生命周期

# 2.1, Vue框架生命周期函数体验

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
     <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
</head>
<body>  
    <!-- 

     -->
    <!-- 定义的容器 -->
    <div id="app">
        <p :style="{opacity:tmd}">Vue是一个很NB的框架!!!</p>
    </div>

    <script>
        let vm = new Vue({
            el:"#app",
            data(){
                return {
                    tmd:1
                }
            },
            // 生命周期函数,也叫钩子函数
            // 这个函数会在合适的时机自动调用
            // 函数的名字,不能随便,都是vue定死的
            // 每一个钩子函数,都有特定的含义
            mounted(){
                setInterval(()=>{
                    this.tmd -= .1;
                    if(this.tmd<=0) this.tmd = 1;
                },500)
            }
        });
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 2.2, 生命周期函数完整版(八个)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
     <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
</head>
<body>  
    <!-- 定义的容器 -->
    <div id="app">
        <button @click="add">加1</button>
        <span ref="cur">{{count}}</span>
        <button @click="minus">减1</button>
        <br>
        <button @click="handle">销毁vm</button>
    </div>

    <script>
        let vm = new Vue({
            el:"#app",
            data(){
                return {
                    count:1
                }
            },
            methods:{
                add(){
                    this.count++
                },
                minus(){
                    this.count--
                },
                handle(){
                    // 销毁vm
                    this.$destroy(); 
                }
            },
            // 生成周期函数,最先执行执行的是beforeCreate,
            // 说明:vm还没有初始化完成   不能通过vm使用data中的方法和methods中的方法
            // 项目中没有什么用,了解就OK了
            beforeCreate(){
                // vm还没有初始化配置完毕,在这里不能获取vm的属性或方法
                console.log("初始化阶段:beforeCreate","vm没有初始化完毕",this.count);
            },
            // vm实例已经初始化完成了
            // 有用,在项目中,通常可以在这里发送ajax请求
            created(){
                // 此处,就可以获取vm的属性或方法了
                console.log("初始化阶段:created","vm初始化完毕", this.count);
            },
            // vm挂载之前调用
            // 项目中用的也不多 
            beforeMount(){
                // 可以获取vm实例,可以得到vm实例上的属性或方法,但是不能获取真实DOM
                console.log("挂载阶段:beforeMount","vm挂载之前执行一次",this.count,this.$refs.cur);
            },
            // vm已经挂载完毕了
            mounted(){
                // 挂载完毕,就可以获取DOM元素
                // 在这里,也可以发生ajax请求  个人一般在mounted中发请求
                console.log("挂载阶段:mounted","vm挂载完毕",this.$refs.cur);
            },
            // 更新阶段,当响应式数据发生了变化,就会触发一次
            beforeUpdate(){
                console.log("更新阶段:beforeUpdate",this.count);
            },
            // 更新阶段:当vm的响应式数据发生变化,更新界面会触发一次
            updated(){
                // 能不能在updated中更新状态?
                // 答:不能,会导致死循环
                console.log("更新阶段:updated",this.count);
            },
            // vm销毁之前调用
            beforeDestroy(){
                console.log("销毁阶段:beforeDestroy",this.count);
            },
            // vm销毁完毕:处理后事,如关闭之前开的一些定时器,或其它的收尾工作
            destroyed(){
                console.log("销毁阶段:destroyed",this.count);
            }
        });

        // 总结:
        //    初始化阶段:beforeCreate  created  只会执行一次
        //    挂载阶段:beforeMount  mounted  只会执行一次
        //    更新阶段:beforeUpdate  updated  只响应式数据发生变化,都会调用,调用N次
        //    销毁阶段:beforeDestroy  destroyed  
        //      销毁后,并不是说界面看不见了,vm实例还可以访问,但是它不工作了!!!!
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
Last Updated: 12/25/2022, 10:02:14 PM