vue 插槽簡介及使用示例
Vue的插槽,是一種內容分發機制,但是我感覺它更加像組件的一種占位符的概念,通過插槽,等待組件外部傳入復雜的內容。
使用插槽的好處
在以前的例子中todo-item插槽直接寫在了todo-list插槽中,其實是比較不合理的,它會導致todo-list插槽比較死板,無法重用更多的其他組件。
Vue.component('todo-list', { template: `<ul> <todo-item v-on:delete='handleDelete' v-for='item in list' data-wen='wen' :title='item.title' :del='item.del'></todo-item></ul> `, data: function() { return { }; }, methods:{ } });
通過插槽化改造,則可以允許使用todo-list組件的用戶自行的傳入想要使用的todo-item,而不是一個固定的內容。
插槽改造過程
改造示例:
將todo-item組件從todo-list組件中移除,放到頁面的html代碼中。 將todo-list組件中原todo-item的位置修改為 因為todo-item移到了頁面html代碼中,所以需要將todo-list的data中的list,移回全局vue中,防止組件找不到list導致v-for報錯;handleDelete同理也要移至全局vue中<!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> <script src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js'></script> </head> <body> <div id='app'> <todo-list> <todo-item v-on:delete='handleDelete' v-for='item in list' data-wen='wen' :title='item.title' :del='item.del'></todo-item> </todo-list> </div> <script> Vue.component('todo-list', { template: `<ul> <slot></slot></ul> `, data: function() { return { }; }, methods:{ } }); Vue.component('todo-item', { props: { title: String, del: { type: Boolean, default: false } }, template: ` <li> <span v-if='!del'>{{title}}</span> <span v-else style='text-decoration:line-through'>{{title}}</span> <button v-show='!del' @click='handleClick'>刪除</button> </li>`, data: function() { return {}; }, methods: { handleClick(){console.log('點擊刪除按鈕!');this.$emit(’delete’,this.title); } } }); var vm = new Vue({ el: '#app', data: { list: [ {title: '新課程1',del: false }, {title: '新課程2',del: true }, {title: '新課程3',del: false } ] }, methods: { handleDelete(vtitle){console.log('刪除工程!',vtitle) } } }); </script> </body></html>
效果和改造前是一模一樣的。
插槽的種類
處理默認插槽外,還有具名插槽,作用域插槽等等。
所謂的具名插槽就是指帶有名稱的插槽,解決的是一個組件中存在多個插槽的業務場景。比如有一個母版頁組件,希望區分頁頭,頁尾和頁面主體。實現如下效果:
<div class='container'> <header> <!-- 我們希望把頁頭放這里 --> </header> <main> <!-- 我們希望把主要內容放這里 --> </main> <footer> <!-- 我們希望把頁腳放這里 --> </footer></div>
那么這個組件應該這樣編寫
<div class='container'> <header> <slot name='header'></slot> </header> <main> <slot></slot> </main> <footer> <slot name='footer'></slot> </footer></div>
具體調用組件的位置,則有兩種寫法:
一種是2.6之前的寫法。
<組件名><p slot='header'>頭部段落</p><p>主段落</p><p slot='footer'>尾部段落</p></組件名>
一種是2.6之后的寫法
<組件名><template v-slot:header> <p>頭部段落</p></template><p>主段落</p><template v-slot:footer> <label>尾部段落</label></template></組件名>
按照2.6之后的寫法,我們嘗試將todo-item組件中增加一個前置lable和后置lable
在todo-item組件的template中的html中增加slot插槽,并標記名稱 html頁面的組件調用位置,使用template和v-slot的語法插入內容<!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> <script src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js'></script> </head> <body> <div id='app'> <todo-list> <todo-item v-on:delete='handleDelete' v-for='item in list' data-wen='wen' :title='item.title' :del='item.del'><template v-slot:pretext> <label>前置文字</label></template><template v-slot:suftext> <label>后置文字</label></template> </todo-item> </todo-list> </div> <script> Vue.component('todo-list', { template: `<ul> <slot></slot></ul> `, data: function() { return { }; }, methods:{ } }); Vue.component('todo-item', { props: { title: String, del: { type: Boolean, default: false } }, template: ` <li> <slot name='pretext'></slot> <span v-if='!del'>{{title}}</span> <span v-else style='text-decoration:line-through'>{{title}}</span> <button v-show='!del' @click='handleClick'>刪除</button> <slot name='suftext'></slot> </li>`, data: function() { return {}; }, methods: { handleClick(){console.log('點擊刪除按鈕!');this.$emit(’delete’,this.title); } } }); var vm = new Vue({ el: '#app', data: { list: [ {title: '新課程1',del: false }, {title: '新課程2',del: true }, {title: '新課程3',del: false } ] }, methods: { handleDelete(vtitle){console.log('刪除工程!',vtitle) } } }); </script> </body></html>
作用域插槽:作用域插槽可以接收子組件傳遞的值,并根據不同的值顯示不同的內容。如根據用戶根據返回的值控制樣式信息。
作用域插槽示例:
為todo-item的data屬性增加返回值vRandomdata: function() { return { vrandom:Math.random() };}, 在todo-item的template的html中通過v-bind綁定組件中的屬性。
template: ` <li> <slot name='pretext' :val='vrandom'></slot> <span v-if='!del'>{{title}}</span> <span v-else style='text-decoration:line-through'>{{title}}</span> <button v-show='!del' @click='handleClick'>刪除</button> <slot name='suftext'></slot> </li>`, 在使用組件時通過模板語法調用綁定的變量
<div id='app'> <todo-list> <todo-item v-on:delete='handleDelete' v-for='item in list' data-wen='wen' :title='item.title' :del='item.del'><template v-slot:pretext='{val}'> <label>前置文字{{val}}</label></template><template v-slot:suftext> <label>后置文字</label></template> </todo-item> </todo-list> </div>
全部html代碼為
<!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> <script src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js'></script> </head> <body> <div id='app'> <todo-list> <todo-item v-on:delete='handleDelete' v-for='item in list' data-wen='wen' :title='item.title' :del='item.del'><template v-slot:pretext='{val}'> <label>前置文字{{val}}</label></template><template v-slot:suftext> <label>后置文字</label></template> </todo-item> </todo-list> </div> <script> Vue.component('todo-list', { template: `<ul> <slot></slot></ul> `, data: function() { return { }; }, methods:{ } }); Vue.component('todo-item', { props: { title: String, del: { type: Boolean, default: false } }, template: ` <li> <slot name='pretext' :val='vrandom'></slot> <span v-if='!del'>{{title}}</span> <span v-else style='text-decoration:line-through'>{{title}}</span> <button v-show='!del' @click='handleClick'>刪除</button> <slot name='suftext'></slot> </li>`, data: function() { return { vrandom:Math.random() }; }, methods: { handleClick(){console.log('點擊刪除按鈕!');this.$emit(’delete’,this.title); } } }); var vm = new Vue({ el: '#app', data: { list: [ {title: '新課程1',del: false }, {title: '新課程2',del: true }, {title: '新課程3',del: false } ] }, methods: { handleDelete(vtitle){console.log('刪除工程!',vtitle) } } }); </script> </body></html>
組件的插槽還有一種帶默認值的用法:在slot中增加默認內容
template: ` <li> <slot name='pretext' :val='vrandom'></slot> <span v-if='!del'>{{title}}</span> <span v-else style='text-decoration:line-through'>{{title}}</span> <button v-show='!del' @click='handleClick'>刪除</button> <slot name='suftext'>默認尾部</slot> </li>`,
如果調用組件時沒有在插槽位置插入內容,則html展示以默認內容進行填充,如果有插內容則以插入值填充。
<div id='app'> <todo-list> <todo-item v-on:delete='handleDelete' v-for='item in list' data-wen='wen' :title='item.title' :del='item.del'><template v-slot:pretext='{val}'> <label>前置文字{{val}}</label></template><template v-slot:suftext> <label>后置文字</label></template> </todo-item> </todo-list> </div>
效果
<div id='app'> <todo-list> <todo-item v-on:delete='handleDelete' v-for='item in list' data-wen='wen' :title='item.title' :del='item.del'><template v-slot:pretext='{val}'> <label>前置文字{{val}}</label></template><template v-slot:suftext></template> </todo-item> </todo-list> </div>
或者
<div id='app'> <todo-list> <todo-item v-on:delete='handleDelete' v-for='item in list' data-wen='wen' :title='item.title' :del='item.del'><template v-slot:pretext='{val}'> <label>前置文字{{val}}</label></template> </todo-item> </todo-list> </div>
以上就是vue 插槽簡介及使用示例的詳細內容,更多關于vue 插槽的資料請關注好吧啦網其它相關文章!
相關文章: