1. 程式人生 > >Vue 進階之路(十三)

Vue 進階之路(十三)

之前的文章我們介紹了一下 vue 中的作用域插槽,本章我們來看一下動態元件與 v-once 指令。

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>vue</title>
 6     <script src="https://cdn.jsdelivr.net/npm/vue"></script>
 7 </head>
 8 <body>
 9 <div id="app">
10     <child-one v-if="type === 'child-one'"></child-one>
11     <child-two v-if="type === 'child-two'"></child-two>
12     <p @click="handleClick">clickMe</p>
13 </div>
14 <script>
15     Vue.component("child-one", {
16         template: `<p>我是第一個子元件</p>`
17     });
18     Vue.component("child-two", {
19         template: `<p>我是第二個子元件</p>`
20     });
21     var app = new Vue({
22         el: '#app',
23         data: {
24             type: "child-one"
25         },
26         methods: {
27             handleClick() {
28                 console.log("type 資料更改前", this.type);
29                 this.type = this.type === "child-one" ? "child-two" : "child-one";
30                 console.log("type 資料更改後", this.type)
31             }
32         }
33     })
34 </script>
35 </body>
36 </html>

上面的程式碼中,我們定義了兩個子元件 child-one 和 child-two,並且我們在父元件中定義了一個 handleClick() 方法,當點選時我們通過父元件中 type 的值來使兩個子元件進行顯隱,結果如下:

當點選 clickMe 時顯示結果符合我們的預期,其實上面的程式碼可以改成如下:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>vue</title>
 6     <script src="https://cdn.jsdelivr.net/npm/vue"></script>
 7 </head>
 8 <body>
 9 <div id="app">
10     <component :is="type"></component>
11     <p @click="handleClick">clickMe</p>
12 </div>
13 <script>
14     Vue.component("child-one", {
15         template: `<p>我是第一個子元件</p>`
16     });
17     Vue.component("child-two", {
18         template: `<p>我是第二個子元件</p>`
19     });
20     var app = new Vue({
21         el: '#app',
22         data: {
23             type: "child-one"
24         },
25         methods: {
26             handleClick() {
27                 console.log("type 資料更改前", this.type);
28                 this.type = this.type === "child-one" ? "child-two" : "child-one";
29                 console.log("type 資料更改後", this.type)
30             }
31         }
32     })
33 </script>
34 </body>
35 </html>

我們將 <child-one> <child-two> 標籤刪除掉,改為 <component> 標籤內,並在標籤內寫上 :is="type",<component> 標籤是一個動態標籤的意思,我們也可以將它寫成 <p> 或者 <h1> 都行,:is="type" ,根據父元件 type 資料的值和 handleClick() 方法對 type 資料改變來確定 :is="type" 內 type 的值是 child-one 還是 child-two,這樣就能動態地改變時顯示 child-one 元件還是 child-two 元件,結果如下:

執行結果和上面是一樣的。

接下來我們來看一下 v-once 指令。

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>vue</title>
 6     <script src="https://cdn.jsdelivr.net/npm/vue"></script>
 7 </head>
 8 <body>
 9 <div id="app">
10     <child-one v-if="type === 'child-one'"></child-one>
11     <child-two v-if="type === 'child-two'"></child-two>
12     <p @click="handleClick">clickMe</p>
13 </div>
14 <script>
15     Vue.component("child-one", {
16         template: `<p v-once>我是第一個子元件</p>`
17     });
18     Vue.component("child-two", {
19         template: `<p v-once>我是第二個子元件</p>`
20     });
21     var app = new Vue({
22         el: '#app',
23         data: {
24             type: "child-one"
25         },
26         methods: {
27             handleClick() {
28                 console.log("type 資料更改前", this.type);
29                 this.type = this.type === "child-one" ? "child-two" : "child-one";
30                 console.log("type 資料更改後", this.type)
31             }
32         }
33     })
34 </script>
35 </body>
36 </html>

 

上面的程式碼中我們在每一個子元件的 template 模板中的 <p> 表內都加了一個 v-once 屬性,如果不加這個指令的話我們每次通過 handleClick() 方法來判斷 type 時,子元件就會進行一個銷燬,另一個重新掛載,就會消耗不必要的記憶體。加上 v-once 時,當第一次掛載時需要渲染一次,當銷燬時並不是徹底刪除掉,而是留在了記憶體中,當需要重新掛載時就不需要重新渲染,而是直接去記憶體中拿,這樣就能減少不必要的記憶體消耗。

&n