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

Vue 進階之路(十一)

模板 解決 字符 如何解決 效果 height doctype 信息 自定義

之前的文章我們說了一下 vue 中組件的原生事件綁定,本章我們來所以下 vue 中的插槽使用。

 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 title="<p>你好 世界</p>"></child> 11 </div> 12 <script> 13 Vue.component("child", { 14 props: [title], 15 template: ` 16 <div> 17 {{title}} 18 <p>
hello world</p> 19 </div> 20 ` 21 }); 22 var app = new Vue({ 23 el: #app, 24 }) 25 </script> 26 </body> 27 </html>

上面的代碼中,我們通過 title="" 形式通過父組件向子組件 child 傳遞了一個 "<p>你好世界</p>" 的帶標簽的內容,然後我們在子組件中輸出,結果如下:

技術分享圖片

顯示結果是按字符串展示的,但我們想要的是不帶標簽的輸出結果,在之前的文章中我們說過可以通過 v-html 來進行轉義,代碼如下:

 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 title="<p>你好 世界</p>"></child>
11 </div>
12 <script>
13     Vue.component("child", {
14         props: [title],
15         template: `
16             <div>
17                 <div v-html="title"></div>
18                 <p>hello world</p>
19             </div>
20        `
21     });
22     var app = new Vue({
23         el: #app,
24     })
25 </script>
26 </body>
27 </html>

我們把 template 中的 {{title}} 改成了 v-html 的形式輸出,結果如下:

技術分享圖片

輸出結果沒問題,但是當我們看控制臺的 HTML 代碼時發現外層多加了一個 <div> 標簽,這顯然不友好,,這時可能有人會想到模板標簽 <template v-html="title"> 這樣寫,但是這樣的話在頁面上是不會輸出內容的。而且如果 <child> 標簽內的 title 屬性裏面的內容並不只是一個 <p> 標簽,還有很多其他的內容,例如 "<p>你好 世界<p><p>你好 世界<p><p>你好 世界<p><p>你好 世界<p><p>你好 世界<p><p>你好 世界<p>" 這麽長的內容,在代碼裏也不好看。

如何解決上面的問題,Vue 官方為我們提供插槽 slot,我們可以將代碼改成如下:

 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>
11         <p>你好 世界</p>
12     </child>
13 </div>
14 <script>
15     Vue.component("child", {
16         template: `
17             <div>
18                 <slot></slot>
19                 <p>hello world</p>
20             </div>
21        `
22     });
23     var app = new Vue({
24         el: #app,
25     })
26 </script>
27 </body>
28 </html>

我們將 p 標簽想要輸出的內容直接放在了 <child> 標簽內,然後在 template 中添加標簽 <slot>,意思就是將 <child> 內的內容通過 slot 插槽插入子組件,結果如下:

技術分享圖片

完美解決了我們的問題,而且 <slot> 標簽內還可以自定義我們想要輸出的內容,如果 <child> 標簽內沒有內容的話以自定義的內容輸出,如下:

 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></child>
11 </div>
12 <script>
13     Vue.component("child", {
14         template: `
15             <div>
16                 <slot>插槽自定義內容</slot>
17                 <p>hello world</p>
18             </div>
19        `
20     });
21     var app = new Vue({
22         el: #app,
23     })
24 </script>
25 </body>
26 </html>

我們在 <child> 標簽內沒有內容,在 slot 標簽內插入了一些內容,在頁面顯示如下:

技術分享圖片

上面的 "插槽自定義內容" 在 <child> 內沒有內容時輸出,如果有內容則輸出 <child> 標簽內的內容。

上面的插槽形式我們可以稱之為無名插槽,還有一種插槽叫具名插槽,看以下代碼:

 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>
11         <header>我是 header</header>
12         <footer>我是 footer</footer>
13     </child>
14 </div>
15 <script>
16     Vue.component("child", {
17         template: `
18             <div>
19                 <slot></slot>
20                 <p>hello world</p>
21                 <slot></slot>
22             </div>
23        `
24     });
25     var app = new Vue({
26         el: #app,
27     })
28 </script>
29 </body>
30 </html>

我們想要一種效果,就是自定義插槽的內容位置,假設上的代碼中 <header> 標簽內的內容為頭部信息,<footer> 標簽內的內容為底部信息,我們想讓它們分別輸出在 template 模板中 p 標簽的上下,結果如下:

技術分享圖片

輸出內容顯然不是我們想要的結果,我們每用一次 <slot> 標簽就會在頁面輸出一次,那該如何解決這個問題呢,我們可以使用具名插槽來為我們的插槽定義名稱,如下:

 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>
11         <header slot="header">我是 header</header>
12         <footer slot="footer">我是 footer</footer>
13     </child>
14 </div>
15 <script>
16     Vue.component("child", {
17         template: `
18             <div>
19                 <slot name="header"></slot>
20                 <p>hello world</p>
21                 <slot name="footer"></slot>
22             </div>
23        `
24     });
25     var app = new Vue({
26         el: #app,
27     })
28 </script>
29 </body>
30 </html>

在上面的代碼中,我們分別為 <header> <footer> 標簽添加 slot 屬性,然後在 template 中的 <slot> 標簽內以 name 屬性來分別對應標簽 <header> <footer> 內的 slot 屬性值,這樣就將指定的內容輸出,結果如下:

技術分享圖片

完美解決我們的問題。

Vue 進階之路(十一)