前端總結--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 歸納

相關文章
相關標籤/搜索