插槽的作用
相信看过前一篇组件化开发后,你对组件化开发有了新的认识。
插槽是干什么的呢?它其实是配合组件一起使用的,让一个组件能够更加的灵活多变,如下图所示,你可以将组件当作一块电脑主板,将插槽当作主板上的插槽,你可以随意的更换该主板上的零件。
常见的应用场景,如淘宝的导航条:
其实他们大体框架都是一样的,只是内容不同罢了。我们就可以将这个导航条定义为一个组件,而内容不同的地方都定义为一个插槽,到了不同的场景更换不同插槽即可。
匿名插槽
使用<slot>
定义插槽,当父组件模板中引用子组件时,可向该插槽插入内容,如下所示:
@H_404_43@
- 一个组件中最多只能拥有一个匿名插槽,它其实也叫默认插槽
- 每个插槽都可以有默认值
<body> <div id="app"> <navigation> <span>这是导航</span> </navigation> </div> <template id="navigation"> <main> <slot>没有内容时显示我</slot> </main> </template> <script src="./vue.js"></script> <script> Vue.component("navigation",{ template: "#navigation",}) const app = new Vue({ el: "#app",}) </script> </body>
具名插槽
实际开发中使用最多的还是具名插槽,给每个
<slot>
添加一个name
属性。在插入内容时,指定
slot
属性为<slot>
的name
属性进行一一插入即可。如下所示,定义了三种不同的搜索框,都是用的同一个组件:
<style> @font-face { font-family: 'iconfont'; /* project id 1953712 */ src: url('//at.alicdn.com/t/font_1953712_uiyayrse2ul.eot'); src: url('//at.alicdn.com/t/font_1953712_uiyayrse2ul.eot?#iefix') format('embedded-opentype'),url('//at.alicdn.com/t/font_1953712_uiyayrse2ul.woff2') format('woff2'),url('//at.alicdn.com/t/font_1953712_uiyayrse2ul.woff') format('woff'),url('//at.alicdn.com/t/font_1953712_uiyayrse2ul.ttf') format('truetype'),url('//at.alicdn.com/t/font_1953712_uiyayrse2ul.svg#iconfont') format('svg'); } .iconfont { font-family: "iconfont"; font-size: 16px; font-style: normal; } i { flex-grow: 2; text-align: center; } * { padding: 0; margin: 0; Box-sizing: border-Box; } nav { width: 100%; background-color: rgba(255,162,109,0.8); padding: 10px; margin-bottom: 20px; } .navigation { display: inline-flex; justify-content: space-around; align-items: center; width: 100%; } input { flex-grow: 6; border-radius: 3rem; text-align: center; outline: none; } </style> <body> <div id="app"> <!-- 第一个个导航条,中间用默认的input框 --> <nav> <navigation class="navigation"> <!-- 插入时,指定slot属性 --> <i class="iconfont" slot="left" :style="{fontSize:'2rem'}"></i> <i class="iconfont" slot="right" :style="{fontSize:'2rem'}"></i> </navigation> </nav> <!-- 第二个导航条,不需要默认的input框,所以用div填充 --> <nav style="background-color: aliceblue"> <navigation class="navigation"> <i class="iconfont" slot="left" :style="{fontSize:'2rem'}"></i> <div slot="mid" style="width: 70%;text-align: center">双十一狂欢夜</div> <i class="iconfont" slot="right" :style="{fontSize:'2rem'}"></i> </navigation> </nav> <!-- 第三个导航条,不需要默认的input框,所以用div填充 --> <nav style="background-color: #ffaad8"> <navigation class="navigation"> <i class="iconfont" slot="left" :style="{fontSize:'2rem'}"></i> <div slot="mid" style="width: 70%;text-align: center">我的资料</div> <i class="iconfont" slot="right" :style="{fontSize:'2rem'}"></i> </navigation> </nav> </div> <template id="navigation"> <main> <!-- 给插槽取名 name属性--> <slot name="left"></slot> <slot name="mid"><input type="text" placeholder="输入你的搜索项" :style="{height:'2rem'}"></slot> <slot name="right"></slot> </main> </template> <script src="./vue.js"></script> <script> Vue.component("navigation",}) </script> </body>
编译作用域
编译作用域的意思是,在那个组件的模板中,渲染时的数据就查找那个组件。
如下所示,父组件和子组件都有一个变量
show
,同时子组件中拥有一个插槽,将插槽插入子组件时用了v-show
指令,那么这个被插入的元素会去找子组件的show
还是找父组件的show
呢?答案是父组件,因为插入插槽的元素是书写在父组件中的。
<body> <div id="app"> <cpn> <span slot="cpn-slot" v-show="show">引用父组件的show</span> </cpn> </div> <!-- 子组件模板 --> <template id="cpn-template"> <div> <span v-show="show">引用子组件的show</span> <slot name="cpn-slot"></slot> </div> </template> <script src="./vue.js"></script> <script> var cpn = { template: "#cpn-template",data() { return { show: false,} } } const app = new Vue({ el: "#app",data: { show: true,},components: { // Vue实例内部进行注册 cpn,}) </script> </body>
作用域插槽
作用域插槽使用较少,它核心理念就是用父组件来渲染子组件。
如下代码中出现一个问题,我们如果直接进行渲染,就把代码写死了,要想改变样式那么所有引用该子组件的地方样式都会改变:
<body> <div id="app"> <cpn :user-msg="msg"></cpn> </div> <!-- 子组件模板 --> <template id="cpn-template"> <div> <ul> <li v-for="row in userMsg">{{row}}</li> </ul> </div> </template> <script src="./vue.js"></script> <script> var cpn = { template: "#cpn-template",props: ["userMsg",],} const app = new Vue({ el: "#app",data: { msg: { id: 1,name: "yunya",age: 18,} },components: { cpn,} }) </script> </body>
此时就可以使用作用域插槽,由父组件来渲染子组件。
使用作用域插槽遵循三个点:
1.必须使用DOM不识别的标签,如template进行接收子组件插槽属性
3.scope是一个对象
@H_404_43@以下是渲染结果,由父组件渲染子组件,给他加粗:
<body> <div id="app"> <cpn :user-msg="msg"> <template slot="message" scope="v"> <ul> <li><b>{{v.field}}</b></li> </ul> </template> </cpn> </div> <!-- 子组件模板 --> <template id="cpn-template"> <div> <slot name="message" v-for="row in userMsg" :field="row"></slot> </div> </template> <script src="./vue.js"></script> <script> var cpn = { template: "#cpn-template",} }) </script> </body>
再配一张图吧,看看每次的
v
是长什么样子:原文链接:https://www.f2er.com/vue/994727.html