🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 插槽(slot) ## 简介 插槽的目的是让原来的设备具备更多的扩展性。比如电脑的USB我们可以插入U盘、硬盘、手机、音响、键盘、鼠标等等。 ## 组件的插槽 >[success] 释义:子组件需要显示的内容并非来自本身,而是父组件传递进来的. > 理解:**组件的插槽也是为了让我们封装的组件更加具有扩展性**。 ## 为什么要使用插槽 先看一个案例,父组件向子组件传递的不是简单数据而一段结构代码 ``` <div id="root"> <child content="<p>Dell</p>"></child> </div> Vue.component('child', { props: { content:String }, template: `<div> <p>hello</p> <div v-html="this.content"></div> </div>`, }) let vm = new Vue({ el: '#root' }) ``` 这种写法有两个问题: 1. `p`标签外面会有一层`div`,这个`div`是无法去掉的,有人会想,能不能用`template`代替,其实是不可以的,在这里模版占位符是不能用的。 2. 如果`content`传递的内容很多,代码就会变得很难阅读。 当我的子组件有一部分内容,是根据父组件传递过来的`dom`进行显示的话,这时候可以换一种语法。 ## 使用插槽 ~~~ <div id="root"> <child> <p>Dell</p> //这种语法看起来非常像,用子组件,我向里插入内容 </child> </div> Vue.component('child', { props: { content:String }, template: `<div> <p>hello</p> <slot></slot> //slot 标签显示的内容就是父组件向子组件插入进来的内容 </div>`, }) let vm = new Vue({ el: '#root' }) ~~~ `<p>Dell</p>`这种语法看起来非常像,用子组我向里插入内容,所以我们把它叫做插槽。 `slot`标签显示的内容就是父组件向子组件插入进来的内容。 通过插槽可以更方便的向子组件传递`dom`元素,同时子组件只需通过`slot`来使用就可以了。 ## 项目中的使用 移动网站中的导航栏、底部tabbar、焦点图等等 >[success] 我们来看一下导航栏吧 > 导航栏我们必然会封装成一个组件,比如nav-bar组件 > 一旦有了这个组件,我们就可以在多个页面中复用了 > 但是,每个页面的导航是一样的吗?No,我以京东M站为例 :-: ![](https://img.kancloud.cn/12/23/12236d5e1ff7081da6de4d83dcf3226e_377x46.png) :-: ![](https://img.kancloud.cn/cb/5f/cb5f709cecd0ac8a7d133efbb6505b77_375x48.png) :-: ![](https://img.kancloud.cn/0f/e3/0fe3ab624256203cdd4a2a96307f5901_385x53.png) :-: ![](https://img.kancloud.cn/4d/05/4d056ca5977f812d3392620494c7d0db_388x52.png) >[warning] vue 2.5.x 插槽用法不一样 2.6.x,2.6.x可以书写2.5.x的写法 > 2.6.x是2019年2.5号更新的。 ## 如何去封装这类的组件呢? 它们也很多区别,但是也有很多共性。 如果,我们每一个单独去封装一个组件,显然不合适:比如每个页面都返回,这部分内容我们就要重复去封装。 但是,如果我们封装成一个,好像也不合理:有些左侧是菜单,有些是返回,有些中间是搜索,有些是文字,等等。 ## 如何封装合适呢? >[success] 抽取共性,保留不同。 最好的封装方式就是将共性抽取到组件中,将不同暴露为插槽。 一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容。 是搜索框,还是文字,还是菜单。由调用者自己来决定。