# 插槽(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] 抽取共性,保留不同。
最好的封装方式就是将共性抽取到组件中,将不同暴露为插槽。
一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容。
是搜索框,还是文字,还是菜单。由调用者自己来决定。