前端总结--vue

1. 最简单的vue

  1. el: dom节点
  2. data: 数据
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
    <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>

<body>
    <div id="app">
        <p> {{ message }}</p>
        <input type="text" v-model="message">
    </div>
    <script type="text/javascript">
        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello Vue!'
            }
        })
    </script>
</body>

</html>

2. Vue 数据里的数组对象更新,可是视图不更新

2.1 问题

因为js的限制,Vue 不能检测以上数组的变更,以及对象的添加/删除,不少人会由于像上面这样操做,出现视图没有更新的问题。javascript

2.2 解决办法

  1. this.$set(你要改变的数组/对象,你要改变的位置/key,你要改为什么value)html

    this.$set(this.arr, 0, "aa"); // 改变数组
    this.$set(this.obj, "c", "cc"); // 改变对象
  2. 数组原生方法触发视图更新:
    Vue能够监测到数组变化的,数组原生方法:前端

    splice()、 push()、pop()、shift()、unshift()、sort()、reverse()

2.3实例

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
    <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>

<body>
    <div id="app">
        <p>arr:{{arr}}</p>
        <p>obj:{{obj}}</p>
        <button @click="arrFn1">修改数组</button>
        <button @click="arrFn2">改变数组</button>
        <button @click="objFn1">增长和删除对象</button>
        <button @click="objFn2">修改对象</button>
        <button @click="this$set">this.$set</button>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data() {
                return {
                    arr: [1, 2, 3],
                    obj: {
                        a: 1,
                        b: 2
                    }
                }
            },
            methods: {
                objFn1() {
                    this.obj.c = 'c' //增长对象属性
                    delete this.obj.a; //删除对象属性
                    console.log(this.obj) //数据变化,视图没有变化
                },
                objFn2() {
                    this.obj.a = 'aa'
                    console.log(this.obj) //数据变化,视图变化
                },
                arrFn1() {
                    this.arr[0] = '11'; //修改数组
                    this.arr.length = 1; //修改数组
                    console.log(this.arr) //数据变化,视图没有变化
                },
                arrFn2() {
                    // splice()、 push()、pop()、shift()、unshift()、sort()、reverse()
                    this.arr.push('3')
                    console.log(this.arr) //数据变化,视图变化
                },
                this$set() {
                    this.$set(this.arr, 0, "11"); // 改变数组
                    this.$set(this.obj, "c", "11"); // 改变对象
                }
            }
        })
    </script>
</body>

</html>

3. filter过滤器的做用

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
    <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>

<body>
    <div id="app">
        <div>{{message | filterTest}}</div>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data() {
                return {
                    message: 1
                }
            },
            filters: {
                filterTest(value) {
                    // value在这里是message的值
                    // return value + '%';
                    return `${value}%`;
                }
            }

        })
    </script>
</body>

</html>

4. v-for与v-if优先级

v-if尽可能不要与v-for在同一节点使用,由于v-for 的优先级比 v-if 更高,若是它们处于同一节点的话,那么每个循环都会运行一遍v-if
若是你想根据循环中的每一项的数据来判断是否渲染,那么你这样作是对的:vue

<li v-for="todo in todos" v-if="todo.type===1">
  {{ todo }}
</li>

若是你想要根据某些条件跳过循环,而又跟将要渲染的每一项数据没有关系的话,你能够将v-if放在v-for的父节点:html5

// 数组是否有数据 跟每一个元素没有关系
<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>

正确使用v-for与v-if优先级的关系,能够为你节省大量的性能。java

5.vue生命周期

5.1 实例

<!DOCTYPE html>
<html>

<head>
    <title></title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
</head>

<body>

    <div id="app">
        <p>{{ message }}</p>
    </div>

    <script type="text/javascript">
        var app = new Vue({
            el: '#app',
            data: {
                message: "xuxiao is boy"
            },
            beforeCreate: function() {
                console.group('beforeCreate 建立前状态===============》');
                console.log("%c%s", "color:red", "el     : " + this.$el); //undefined
                console.log("%c%s", "color:red", "data   : " + this.$data); //undefined 
                console.log("%c%s", "color:red", "message: " + this.message)
            },
            created: function() {
                console.group('created 建立完毕状态===============》');
                console.log("%c%s", "color:red", "el     : " + this.$el); //undefined
                console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化 
                console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
            },
            beforeMount: function() {
                console.group('beforeMount 挂载前状态===============》');
                console.log("%c%s", "color:red", "el     : " + (this.$el)); //已被初始化
                console.log(this.$el);
                console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化  
                console.log("%c%s", "color:red", "message: " + this.message); //已被初始化  
            },
            mounted: function() {
                console.group('mounted 挂载结束状态===============》');
                console.log("%c%s", "color:red", "el     : " + this.$el); //已被初始化
                console.log(this.$el);
                console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化
                console.log("%c%s", "color:red", "message: " + this.message); //已被初始化 
            },
            beforeUpdate: function() {
                console.group('beforeUpdate 更新前状态===============》');
                console.log("%c%s", "color:red", "el     : " + this.$el);
                console.log(this.$el);
                console.log("%c%s", "color:red", "data   : " + this.$data);
                console.log("%c%s", "color:red", "message: " + this.message);
            },
            updated: function() {
                console.group('updated 更新完成状态===============》');
                console.log("%c%s", "color:red", "el     : " + this.$el);
                console.log(this.$el);
                console.log("%c%s", "color:red", "data   : " + this.$data);
                console.log("%c%s", "color:red", "message: " + this.message);
            },
            beforeDestroy: function() {
                console.group('beforeDestroy 销毁前状态===============》');
                console.log("%c%s", "color:red", "el     : " + this.$el);
                console.log(this.$el);
                console.log("%c%s", "color:red", "data   : " + this.$data);
                console.log("%c%s", "color:red", "message: " + this.message);
            },
            destroyed: function() {
                console.group('destroyed 销毁完成状态===============》');
                console.log("%c%s", "color:red", "el     : " + this.$el);
                console.log(this.$el);
                console.log("%c%s", "color:red", "data   : " + this.$data);
                console.log("%c%s", "color:red", "message: " + this.message)
            }
        })
    </script>
</body>

</html>

5.2 create和mounted

  1. beforecreated:el 和 data 并未初始化
  2. created:完成了 data 数据的初始化,el没有
  3. beforeMount:完成了 el 和 data 初始化
  4. mounted :完成挂载

另外在标绿处,咱们能发现el仍是 {{message}},这里就是应用的 Virtual DOM(虚拟Dom)技术,先把坑占住了。到后面mounted挂载的时候再把值渲染进去。node

clipboard.png

5.3update 相关

clipboard.png

5.4destroy

有关于销毁,暂时还不是很清楚。咱们在console里执行下命令对 vue实例进行销毁。销毁完成后,咱们再从新改变message的值,vue再也不对此动做进行响应了。可是原先生成的dom元素还存在,能够这么理解,执行了destroy操做,后续就再也不受vue控制了。git

clipboard.png

5.5 总结

  1. beforecreate : 举个栗子:能够在这加个loading事件
  2. created :在这结束loading,还作一些初始化,实现函数自执行
  3. mounted : 在这发起后端请求,拿回数据,配合路由钩子作一些事情
  4. beforeDestroy: 你确认删除XX吗? destroyed :当前组件已被删除,清空相关内容

5.6 参考

https://segmentfault.com/a/11...
Vue的生命周期函数和beforeRouteEnter()/beforeRouteLeave()的函数github

6.vue 为何采用Virtual DOM

  1. 建立真实DOM的代价高:真实的 DOM 节点 node 实现的属性不少,而 vnode 仅仅实现一些必要的属性,相比起来,建立一个 vnode 的成本比较低。

2.触发屡次浏览器重绘及回流:使用 vnode ,至关于加了一个缓冲,让一次数据变更所带来的全部 node 变化,先在 vnode 中进行修改,而后 diff 以后对全部产生差别的节点集中一次对 DOM tree 进行修改,以减小浏览器的重绘及回流vue-router

  1. 虚拟dom因为本质是一个js对象,所以天生具有跨平台的能力,能够实如今不一样平台的准确显示。
  2. Virtual DOM 在性能上的收益并非最主要的,更重要的是它使得 Vue 具有了现代框架应有的高级特性。
例子
{
    tag: 'div',                 /*说明这是一个div标签*/
    children: [                 /*存放该标签的子节点*/
        {
            tag: 'a',           /*说明这是一个a标签*/
            text: 'click me'    /*标签的内容*/
        }
    ]
}

渲染后能够获得

<div>
    <a>click me</a>
</div>

7. 组件data为何必须是函数

  1. 由于不使用return包裹的数据会在项目的全局可见,会形成变量污染
  2. 使用return包裹后数据中变量只在当前组件中生效,不会影响其余组件

当一个组件被定义, data 必须声明为返回一个初始数据对象的函数,由于组件可能被用来建立多个实例。若是 data 仍然是一个纯粹的对象,则全部的实例将共享引用同一个数据对象!经过提供 data 函数,每次建立一个新实例后,咱们可以调用 data 函数,从而返回初始数据的一个全新副本数据对象。

8. 组件style的scoped

为何在组件中用js动态建立的dom,添加样式不生效

<template>
     <div class="test"></div>
</template>
<script>
    let a=document.querySelector('.test');
    let newDom=document.createElement("div"); // 建立dom
    newDom.setAttribute("class","testAdd" ); // 添加样式
    a.appendChild(newDom); // 插入dom
</script>
<style scoped>
.test{
   background:blue;
    height:100px;
    width:100px;
}
.testAdd{
    background:red;
    height:100px;
    width:100px;
}
</style>

结果

// test生效   testAdd 不生效
<div data-v-1b971ada class="test"><div class="testAdd"></div></div>
.test[data-v-1b971ada]{ // 注意data-v-1b971ada
    background:blue;
    height:100px;
    width:100px;
}

缘由

当 <style> 标签有 scoped 属性时,它的 CSS 只做用于当前组件中的元素。
它会为组件中全部的标签和class样式添加一个scoped标识,就像上面结果中的data-v-1b971ada。
因此缘由就很清楚了:由于动态添加的dom没有scoped添加的标识,没有跟testAdd的样式匹配起来,致使样式失效。

解决办法:

去掉scoped便可

9. vue-router实现原理

9.1更新视图而不从新请求页面

SPA(single page application):单一页面应用程序,只有一个完整的页面;它在加载页面时,不会加载整个页面,而是只更新某个指定的容器中内容。单页面应用(SPA)的核心之一是: 更新视图而不从新请求页面;vue-router在实现单页面前端路由时,提供了两种方式:Hash模式和History模式;根据mode参数来决定采用哪种方式。

9.2. Hash模式

vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,因而当 URL 改变时,页面不会从新加载。 hash(#)是URL 的锚点,表明的是网页中的一个位置,单单改变#后的部分,浏览器只会滚动到相应位置,不会从新加载网页,也就是说hash 出如今 URL 中,但不会被包含在 http 请求中,对后端彻底没有影响,所以改变 hash 不会从新加载页面;同时每一次改变#后的部分,都会在浏览器的访问历史中增长一个记录,使用”后退”按钮,就能够回到上一个位置;因此说Hash模式经过锚点值的改变,根据不一样的值,渲染指定DOM位置的不一样数据。hash 模式的原理是 onhashchange 事件(监测hash值变化),能够在 window 对象上监听这个事件

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        ul {
            height: 1000px;
            border-bottom: 1px solid #000;
        }
    </style>
</head>

<body>
    <ul>
        <li class="a">
            <a href="#a">a</a>
        </li>
        <li class="b">
            <a href="#b">b</a>
        </li>
    </ul>
    <div>
        <div id="a">a</div>
        <div id="b">b</div>
    </div>
</body>

</html>

9.3 History模式

因为hash模式会在url中自带#,若是不想要很丑的 hash,咱们能够用路由的 history 模式,只须要在配置路由规则时,加入"mode: 'history'",这种模式充分利用了html5 history interface 中新增的 pushState() 和 replaceState() 方法。这两个方法应用于浏览器记录栈,在当前已有的 back、forward、go 基础之上,它们提供了对历史记录修改的功能。只是当它们执行修改时,虽然改变了当前的 URL ,但浏览器不会当即向后端发送请求

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id,比较好看!
不过这种模式要玩好,还须要后台配置支持。由于咱们的应用是个单页客户端应用,若是后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就很差看了。
因此呢,你要在服务端增长一个覆盖全部状况的候选资源:若是 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

export const routes = [ 
  {path: "/", name: "homeLink", component:Home}
  {path: "/register", name: "registerLink", component: Register},
  {path: "/login", name: "loginLink", component: Login},
  {path: "*", redirect: "/"}]

此处就设置若是URL输入错误或者是URL 匹配不到任何静态资源,就自动跳到到Home页面

10.vue自定义指令

10.1 全局注册指令

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
    <title></title>
</head>

<body>
    <div id="app" class="demo">
        <!-- 全局注册 -->
        <input type="text" placeholder="我是全局自定义指令" v-focus>
    </div>
    <script>
        Vue.directive("focus", {
                inserted: function(el) {
                    el.focus();
                }
            })
            //new Vue要放在后面
        new Vue({
            el: "#app"
        })
    </script>


</body>

</html>

10.2 局部注册指令

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
    <title></title>
</head>

<body>
    <div id="app" class="demo">
        <!-- 局部注册 -->
        <input type="text" placeholder="我是局部自定义指令" v-focus2>
    </div>
    <script>
        new Vue({
            el: "#app",
            directives: {
                focus2: {
                    inserted: function(el) {
                        el.focus();
                    }
                }
            }
        })
    </script>



</body>

</html>

10.2 钩子函数

一个指令定义对象能够提供以下几个钩子函数 (均为可选)

  1. bind:只调用一次,指令第一次绑定到元素时调用。在这里能够进行一次性的初始化设置
  2. inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不必定已被插入文档中)。
  3. update:所在组件的 VNode 更新时调用,可是可能发生在其子 VNode 更新以前。指令的值可能发生了改变,也可能没有。可是你能够经过比较更新先后的值来忽略没必要要的模板更新 。
  4. componentUpdated:指令所在组件的 VNode 及其子 VNode 所有更新后调用。
  5. unbind:只调用一次,指令与元素解绑时调用。
<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
    <title></title>
</head>

<body>

    <div id="container">

        <!-- 准备实现需求:
    在h1标签上面,加上一个按钮,当点击按钮时候,对count实现一次
    自增操做,当count等于5的时候,在控制台输出‘it is a test’
    -->
        <button @click="handleClick">clickMe</button>
        <h1 v-if="count < 6" v-change="count">it is a custom directive</h1>
    </div>

    <script>
        //directive
        new Vue({
            el: '#container',
            data: {
                count: 0,
                color: '#ff0000'
            },
            methods: {
                handleClick: function() {
                    //按钮单击,count自增
                    this.count++;
                }
            },
            directives: {
                change: {
                    bind: function(el, bindings) {
                        console.log('指令已经绑定到元素了');
                        console.log(el);
                        console.log(bindings);
                            //准备将传递来的参数
                            // 显示在调用该指令的元素的innerHTML
                        el.innerHTML = bindings.value;
                    },
                    update: function(el, bindings) {
                        console.log('指令的数据有所变化');
                        console.log(el);
                        console.log(bindings);
                        el.innerHTML = bindings.value;
                        if (bindings.value == 5) {
                            console.log(' it is a test');
                        }
                    },
                    unbind: function() {
                        console.log('解除绑定了');
                    }
                }
            }
        })
    </script>

</body>

</html>

10.3 参考

https://www.cnblogs.com/wangr...
https://juejin.im/post/5a3933...

11.v-if 和 v-show 区别

v-if按照条件是否渲染,v-show是display的block或none

12.v-for 中 :key 到底有什么用

key的做用主要是为了高效的更新虚拟DOM。

12.1参考

https://www.zhihu.com/questio...

13. Vue.nextTick()

13.1什么是Vue.nextTick()

在下次 DOM 更新循环结束以后执行延迟回调。在修改数据以后当即使用这个方法,获取更新后的 DOM。

注意:重点是获取更新后的DOM 就是在开发过程当中有个需求是须要在created阶段操做数据更新后的节点 这时候就须要用到Vue.nextTick()

$nextTick就是用来知道何时DOM更新完成

13.2缘由

在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操做无异于徒劳,因此在created中必定要将DOM操做的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted()钩子函数,由于该钩子函数执行时全部的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操做都不会有问题

13.3$refs获取dom节点属性

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
    <title></title>
</head>

<body>

    <div id="app">
        <div ref="msg1">{{msg1}}</div>
        <div>{{msg2}}</div>
        <button @click="changeMsg">点击我</button>
    </div>

    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    msg1: "11",
                    msg2: "22"
                }
            },
            methods: {
                changeMsg() {
                    this.msg1 = "33"
                    this.msg2 = this.$refs.msg1.textContent;
                    console.log('DOM并未渲染完成' + this.$refs.msg1.textContent)  //11
                    this.$nextTick(function() {
                        console.log('DOM已经何渲染完成' + this.$refs.msg1.textContent)  //33
                    })
                }
            }

        })
    </script>

</body>

</html>

13.4 document.getElementById获取节点

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
    <title></title>
</head>

<body>

    <div id="app">
        <div ref="msg" id="msg" v-if="isShow">{{msg}}</div>
        <button @click="changeMsg">点击我</button>
    </div>

    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    msg: "aa",
                    isShow: false
                }
            },
            methods: {
                changeMsg() {
                    this.isShow = true
                    console.log(document.getElementById("msg")) //null
                    this.$nextTick(function() {
                        console.log(document.getElementById("msg").innerHTML) //aa
                    })
                }
            }
        })
    </script>

</body>

</html>

13.5 参考

https://juejin.im/post/5b6a60...

14.keep-alive

14.1实现页面缓存

14.1.1 方法一

首先在定义路由的时候配置 meta 字段,自定义一个KeepAlive字段做为该页面是否缓存的标记

routes:[{
    path: '/search',
    name: 'search',
    component: search,
    meta: {
        title: '搜索列表页',
        keepAlive: true // 标记列表页须要被缓存
    }
},
{
    path: '/detail',
    name: 'detail',
    component: detail,
    meta: {
        title: '详情页',
        // 详情页不须要作缓存,因此不加keepAlive标记
    }
}]

因为<keep-alive>组件不支持v-if指令,因此咱们在App.vue中采用两个<router-view>的写法,经过当前路由的keepAlive字段来判断是否对页面进行缓存:

<div id="app">
    <keep-alive>
        <router-view v-if="$route.meta.keepAlive" />
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive" />
</div>

14.1.1 方法二

使用<keep-alive>提供的 exclude 或者 include 选项,此处咱们使用 exclude ,在App.vue中:

<div id="app">
    <keep-alive exclude="detail">
        <router-view />
    </keep-alive>
</div>

须要注意的是,必定要给页面组件加上相应的name,例如在detail.vue中:

<script>

<script>
export default {
    name: 'detail', // 这个name要和keep-alive中的exclude选项值一致
    ...
}
</script>

这么写就表明了在项目中除了name为detail的页面组件外,其他页面都将进行缓存。

15 vue组件通讯

常见使用场景能够分为三类:

父子通讯:
父向子传递数据是经过 props,子向父是经过 events($emit);经过父链 / 子链也能够通讯($parent / $children);ref 也能够访问组件实例;provide / inject API;$attrs/$listeners
兄弟通讯:
Bus;Vuex
跨级通讯:
Bus;Vuex;provide / inject API、$attrs/$listeners

参考

https://juejin.im/post/5bd97e...
https://github.com/ljianshu/B...

16 Vue 的响应式原理中 Object.defineProperty 有什么缺陷

Vue 的响应式原理中 Object.defineProperty 有什么缺陷?为何在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?

  1. Object.defineProperty没法监控到数组下标的变化,致使经过数组下标添加元素,不能实时响应;
  2. Object.defineProperty只能劫持对象的属性,从而须要对每一个对象,每一个属性进行遍历,若是,属性值是对象,还须要深度遍历。Proxy能够劫持整个对象,并返回一个新的对象。
  3. Proxy不只能够代理对象,还能够代理数组。还能够代理动态增长的属性

16. Vue计算属性和侦听属性

16.1 计算属性

  1. 计算属性由两部分组成:get和set,分别用来获取计算属性和设置计算属性。默认只有get,若是须要set,要本身添加。另外set设置属性,并非直接修改计算属性,而是修改它的依赖
  2. computed 是能够缓存的,methods 不能缓存
data:{ //普通属性
  msg:'aa',
},
computed:{ //计算属性
  reverseMsg:function(){
  // 该函数必须有返回值,用来获取属性,称为get函数
  //能够包含逻辑处理操做,同时reverseMsg依赖于msg,一旦msg发生变化,reverseMsg也会跟着变化
    return this.msg.split(' ').reverse().join(' ');
 }
}

16.2 监听属性

  1. handler 回调
  2. deep 设置为 true 用于监听对象内部值的变化
  3. immediate 设置为 true 将当即以表达式的当前值触发回调
<template>
    <button @click="obj.a = 2">修改</button>
</template>
<script>
export default {
    data() {
        return {
            obj: {
                a: 1,
            }
        }
    },
    watch: {
        obj: {
            handler: function(newVal, oldVal) {
                console.log(newVal); 
            },
            deep: true,
            immediate: true 
        }
    }
}
</script>

16.3 二者之间对比

  1. watch:监测的是属性值, 只要属性值发生变化,其都会触发执行回调函数来执行一系列操
  2. computed:监测的是依赖值,依赖值不变的状况下其会直接读取缓存进行复用,变化的状况下才会从新计算

16.4 总结

  1. 计算属性适合用在模板渲染中,某个值是依赖了其它的响应式对象甚至是计算属性计算而来;
  2. 侦听属性适用于观测某个值的变化去完成一段复杂的业务逻辑
  3. computed能作的,watch都能作,反之则不行,能用computed的尽可能用computed

16.5 参考

详解Vue计算属性和侦听属性

17 vue组件三大核心概念

17.1 归纳

相关文章
相关标签/搜索