最近开发时组件化了一个功能,接触到了插槽的概念,抽空看了下Vue文档中对插槽的讲解,这边做些简单的应用,总结下。
默认插槽
Vue文档里讲的插槽主要有三种:默认插槽(单个插槽),具名插槽,作用域插槽;默认插槽(有的地方叫匿名插槽)是相对于具名插槽来说的,区别在于不用设置name属性,不区分内容。插槽允许在slot里面编写一些默认的内容,在父组件没有写具体东西时展示出这些,当在父组件中写入代码时,这部分内容将会被覆盖掉。
// 子组件
<template>
<div class="block" v-on:click="clickEvent">
<slot>
<span>默认内容</span>
</slot>
</div>
</template>
// 父组件
<template>
<div class="block" v-on:click="clickEvent">
<block title="组件标题" @click="walletView(1)" >
<span>这边的内容将会覆盖掉子组件中的默认内容</span>
</block>
</div>
</template>
具名插槽
很多时候我们的组件是需要区分如header, content,footer这样的结构,这时就需要具名插槽来解决这个问题,具名插槽是在匿名插槽的基础上加入name属性来区分不同的部分,父组件在引用时需要用<template>元素和slot属性来找到对应的部分
// 子组件
<template>
<div class="block" v-on:click="clickEvent">
<el-row>
<p class="title-txt"><b>{{title}}</b></p>
</el-row>
<slot name="header">
</slot>
<el-row>
<hr class="hr-line"/>
</el-row>
<slot name="footer">
</slot>
</div>
</template>
// 父组件
<template>
<block title="组件标题" @click="walletView(1)">
<template slot="header">
<p class="amount">
账户状态:<span class="red" v-text="bookStatusMap[status]"></span>
</p>
</template>
<template slot="footer">
<p class="amount">
账户余额: <span class="red" v-text="actualBalance"></span>
</p>
</template>
</block>
</template>
作用域插槽
Vue文档上对于作用域插槽的描述很简练,对它的作用和意义比较模糊,后来在其他地方搜了下,我大致理解为父组件可以引用子组件提供来的数据,应用场景在表格中体现较典型,表格组件返回对应的一行数据内容,在父组件中根据数据自由拼接。
// 子组件
<template>
<div class="block" v-on:click="clickEvent">
<el-row>
<p class="title-txt"><b>{{title}}</b></p>
</el-row>
<slot name="content" :prop="data">
</slot>
</div>
</template>
简单提一下slot-scope这个属性,之前在项目里用它是会直接报错([Vue warn]: Property or method "props" is not defined on the instance but referenced during render. )后来才注意到它是在vue2.5.x后代替scope存在的(试了下在vue2.5.9版本中使用slot-scope和scope都是可以的),之前我的Vue版本是2.1.8的,很久都没找着是什么原因,气死。。。
附赠Vue文档描述关于slot和slot-scope的问题 https://cn.vuejs.org/v2/api/#slot-scope
// 父组件
<template>
<block title="组件标题" @click="walletView" :data="ymmWalletData">
<!-- vue2.5.X中 scope被slot-scope替代 -->
<template slot="content" scope="data">
<p class="amount">
<span>账户状态:</span> <span class="red" v-text="bookStatusMap[data.prop.status]"></span>
</p>
</template>
</block>
</template>