Vue 进阶系列教程将在本号持续发布,一起查漏补缺学个痛快!若您有遇到其它相关问题,非常欢迎在评论中留言讨论,达到帮助更多人的目的。若感本文对您有所帮助请点个赞吧!
2013年7月28日,尤雨溪第一次在 GItHub 上为 Vue.js 提交代码;2015年10月26日,Vue.js 1.0.0版本发布;2016年10月1日,Vue.js 2.0发布。
最早的 Vue.js 只做视图层,没有路由, 没有状态管理,也没有官方的构建工具,只有一个库,放到网页里就可以直接用了。
后来,Vue.js 慢慢开始加入了一些官方的辅助工具,比如路由(Router)、状态管理方案(Vuex)和构建工具(Vue-cli)等。此时,Vue.js 的定位是:The Progressive Framework。翻译成中文,就是渐进式框架。
Vue.js2.0 引入了很多特性,比如虚拟 DOM,支持 JSX 和 TypeScript,支持流式服务端渲染,提供了跨平台的能力等。Vue.js 在国内的用户有阿里巴巴、百度、腾讯、新浪、网易、滴滴出行、360、美团等等。
Vue 已是一名前端工程师必备的技能,现在就让我们开始深入学习 Vue.js 内部的核心技术原理吧!
什么是插槽
先举个生活中的小例子,生活中电源插座大家肯定不陌生,每个插座上面都有很多个电源插口,我们可以将很多电器都连接到插座上,当然,插座上也可能只有一个插口。
在 Vue.js 中,插座就相当于一个组件,插口就相当于我们这里的插槽,我们可以将任何组件(也就是DOM元素)通过插槽添加到组件中。这样可以做到内容分发,让我们的组件可以混合使用。
怎么用插槽
在 Vue.js 中,插槽的使用分两种,单个插槽和具名插槽。
单个插槽
在子组件内部通过一个 <slot> 元素就可以开启一个插槽,通过在父组件中,向子组件标签内部插入内容,就可以将这些内容替换掉子组件的 <slot> 标签及它的内容。只看文字可能理解的不是很深,举个例子:
<div>
<helloworld>
<span>父组件向子组件插槽内插入的内容</span>
</helloworld>
</div>
<script>
Vue.component('helloworld',{
template:`
<div>
<slot>
插槽内部默认内容
</slot>
</div>
`
})
</script>
上方代码最终显示内容为:父组件向子组件插槽内插入的内容
上方代码最终渲染出来的结果是:
<div>
<span>父组件向子组件插槽内插入的内容</span>
</div>
在子组件 helloworld 中,定义了一个插槽,当父组件调用子组件的时候,没有向子组件标签内部传入数据的时候,会展示子组件插槽内的默认内容。当向子组件标签内部插入数据的时候,就会将插入的内容,替换掉子组件 <slot>标签以及标签内所有内容。
具名插槽
上方我们展示了一个插槽的情况,当有多个插槽的时候,我们插入的内容不知道他会插入到那个插槽内部,这个时候就要使用具名插槽了。用来指定插入的内容插入到指定的插槽上。举例如下:
<div>
<helloworld>
<span slot="top">上面</span>
<span>父组件向子组件插槽内插入的内容</span>
<span slot="bottom">下面</span>
</helloworld>
</div>
<script>
Vue.component('helloworld',{
template:`
<div>
<slot name="top"></slot>
<slot></slot>
<slot name="bottom"></slot>
</div>
`
})
</script>
上方代码最终渲染结果如下:
<div>
<span>上面</span>
<span>父组件向子组件插槽内插入的内容</span>
<span>下面</span>
</div>
我们定义了三个插槽,分别是具名插槽 top,没有 name 特性的默认插槽,还有具名插槽 bottom。在父组件中,通过 slot 选项来指定当前内容插入到子组件的哪一个插槽中,如果没有 slot 选项,插入到默认插槽。
编译作用域
在讲编译作用域之前,先举个小例子:
<div>
<helloworld v-show="isShow">
{{name}}
</helloworld>
</div>
上方的 name,绑定的是父组件的数据,上方的 isShow,也是父组件的数据。
Vue.component('helloworld',{
template:`
<div v-show="isShow">
{{name}}
</div>
`,
data(){
return{
name:'',
isShow:true
}
}
})
上方的 name,绑定的是子组件 helloworld 中的数据,上方的 isShow,也是子组件的数据。
引用官网说的一句话就是,父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
作用域插槽的使用
作用域插槽,就是可以让我们在父组件中使用插槽时,插槽的数据可以来自子组件。举个例子:
<div>
<helloworld>
<template slot="props">
<p>{{props.name}}</p>
</template>
</helloworld>
</div>
<script>
Vue.component('helloworld',{
template:`
<div>
<slot name="子组件向插槽传递的数据"></slot>
</div>
`
})
</script>
上方代码最终渲染结果如下:
<div>
<p name="子组件向插槽传递的数据"></p>
</div>
通过在父组件中,使用 template 元素,并且指定了 scope="props" 特性,然后子组件通过类似父子组件传值的形式,向插槽内部传递数据,这样我们就可以在父组件插槽中使用子组件的数据了。
访问插槽
最后,我们可以通过 $slot 访问插槽中的内容。
<div>
<helloworld>
<span slot="top">上面</span>
<span>父组件向子组件插槽内插入的内容</span>
<span slot="bottom">下面</span>
</helloworld>
</div>
<script>
Vue.component('helloworld',{
template:`
<div>
<slot name="top"></slot>
<slot></slot>
<slot name="bottom"></slot>
</div>
`,
mounted(){
// 具名插槽top的内容
console.log(this.$slots.top)
// 非具名插槽的内容
console.log(this.$slots.default)
// 具名插槽bottom的内容
console.log(this.$slots.bottom)
}
})
</script>
Vue 进阶系列教程将在本号持续发布,一起查漏补缺学个痛快!若您有遇到其它相关问题,非常欢迎在评论中留言讨论,达到帮助更多人的目的。若感本文对您有所帮助请点个赞吧!
叶阳辉
HFun 前端攻城狮
往期精彩: