Vue 组件化开发之插槽
2020-11-21 11:26
796 查看
插槽的作用
相信看过前一篇组件化开发后,你对组件化开发有了新的认识。
插槽是干什么的呢?它其实是配合组件一起使用的,让一个组件能够更加的灵活多变,如下图所示,你可以将组件当作一块电脑主板,将插槽当作主板上的插槽,你可以随意的更换该主板上的零件。
常见的应用场景,如淘宝的导航条:
其实他们大体框架都是一样的,只是内容不同罢了。我们就可以将这个导航条定义为一个组件,而内容不同的地方都定义为一个插槽,到了不同的场景更换不同插槽即可。
匿名插槽
使用
<slot>定义插槽,当父组件模板中引用子组件时,可向该插槽插入内容,如下所示:
- 一个组件中最多只能拥有一个匿名插槽,它其实也叫默认插槽
- 每个插槽都可以有默认值
<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框 --& 56c gt; <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> &l 564 t;/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", { template: "#navigation", }) const app = new Vue({ el: "#app", }) </script> </body>
编译作用域
编译作用域的意思是,在那个组件的模板中,渲染时的数据就查找那个组件。
如下所示,父组件和子组件都有一个变量
show,同时子组件中拥有一个插槽,将插槽插入子组件时用了
v-show指令,那么这个被插入的元素会去找子组件的
show还是找父组件的
show呢?
答案是父组件,因为插入插槽的元素是书写在父组件中的。
<body> <div id="app"> <cpn> 1e30 <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进行接收子组件插槽属性
2.接收子组件插槽属性的属性是scope
3.scope是一个对象
以下是渲染结果,由父组件渲染子组件,给他加粗:
<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", props: ["userMsg",], } const app = new Vue({ el: "#app", data: { msg: { id: 1, name: "yunya", age: 18, } }, components: { cpn, } }) </script> </body>
再配一张图吧,看看每次的
v是长什么样子:
相关文章推荐
- Vue.js系列第二集——组件化开发
- Vue组件化开发 组件通信 父子组件传值
- vue组件化开发-vuex状态管理库
- Vue.js组件化开发实践
- vue.js组件化开发实践
- vue.js原生组件化开发——父子组件
- 我们为什么要用Vue.js的组件化开发
- Vue学习笔记 6 - 使用 Vue 的配置过程/组件化开发引入/文件封装处理/ plugin /搭建本地服务器/配置文件的分离
- Vue-router 类似Vuex实现组件化开发的示例
- 【vue开发 环境搭建】从 vuejs环境搭建到组件化编程----Hello World!
- vue.js原生组件化开发(二)——父子组件
- Vue学习笔记 3 - 组件化 / slot(插槽)
- Vue组件化开发
- 前端架构组件化开发系列二 (基于VUE 扩展组件)
- Laravel 中使用 Vue 组件化开发(配置)
- Vue学习笔记六:组件化开发
- 详解vue组件化开发-vuex状态管理库
- (5)Vue组件化开发
- vue-组件化-插槽(slot)
- Vue全家桶-组件化开发