slot
当某个组件被多个地方使用 , 每个地方使用该组件时对该组件的内部有一部分需要特殊定制 , 这个时候slot可以让我们更好的复用组件的同时并对其定制
当组件中某一项需要单独定义,那么就应该使用solt
例如项目中需要一个模态框提示 付款成功,付款失败。那么这个模态框也就仅仅差这几个字或者是状态图片而已。那么此时应用solt就是一个非常不错的选择。
- 子组件模板包含至少一个 插口,否则父组件的内容将会被丢弃
- 当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身
子组件没有插口
<template>
<div id="app">
<children>
<span>子组件内部元素</span>
</children>
</div>
</template>
<script>
export default {
name: 'hello',
components: {
children: {
template: '<div>这里是子组件</div>'
}
}
}
</script>
<!--渲染结果-->
<div id="app">
<div>这里是子组件</div>
</div>
复制代码
如果想让span显示那么此刻就应该使用slot。
<template>
<div id="app">
<children>
<span>子组件内部元素</span>
</children>
</div>
</template>
<script></script>
<!--渲染结果-->
<div id="app">
<span>子组件内部元素</span>
"这里是子组件"
</div>
复制代码
具名slot
- 如果想使用多个slot那么此时就应该使用具名slot
- 元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。
- 仍然可以有一个匿名 slot ,它是默认 slot ,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot ,这些找不到匹配的内容片段将被抛弃。
<template>
<div id="app">
<children>
<div slot="header">
<ul>
<li>首页</li>
<li>商城</li>
</ul>
</div>
<div>
这个是默认的没有具名的solt
</div>
<div slot="footer">
<p>备案号</p>
</div>
</children>
</div>
</template>
<script></script>
<!--渲染结果为-->
<div id="app">
<div>
"这是子组件"
<div></div>
<div>
<ul>
<li>首页</li>
<li>商城</li>
</ul>
</div>
<div>
"这个是默认没有具名的slot"
</div>
<div>
<p>备案号</p>
</div>
</div>
</div>
复制代码
作用域插槽
作用域插槽的关键之处就在于,父组件能接收来自子组件的slot传递过来的参数
<div id="app2">
<!-- 组件使用者只需传递users数据即可 -->
<my-stripe-list :items="users" odd-bgcolor="#D3DCE6" even-bgcolor="#E5E9F2">
<!-- props对象接收来自子组件slot的$index参数 -->
<template slot="cont" scope="props">
<span>{{users[props.$index].id}}</span>
<span>{{users[props.$index].name}}</span>
<span>{{users[props.$index].age}}</span>
<!-- 这里可以自定[编辑][删除]按钮的链接和样式 -->
<a :href="'#edit/id/'+users[props.$index].id">编辑</a>
<a :href="'#del/id/'+users[props.$index].id">删除</a>
</template>
</my-stripe-list>
</div>
<script>
Vue.component('my-stripe-list', {
/*slot的$index可以传递到父组件中*/
template: `
<div>
<div v-for="(item, index) in items" style="line-height:2.2;" :style="index % 2 === 0 ? 'background:'+oddBgcolor : 'background:'+evenBgcolor">
<slot name="cont" :$index="index"></slot>
</div>
</div>
`,
props: {
items: Array,
oddBgcolor: String,
evenBgcolor: String
}
});
new Vue({
el: '#app2',
data: {
users: [
{id: 1, name: '张三', age: 20},
{id: 2, name: '李四', age: 22},
{id: 3, name: '王五', age: 27},
{id: 4, name: '张龙', age: 27},
{id: 5, name: '赵虎', age: 27}
]
}
});
</script>
复制代码
<div id="demo1">
<div>
<h3>1、单个插槽</h3>
<single>
dsafd
</single>
</div>
<muli-slots>
<!--在html中不支持驼峰式的标签名,需改为横线式-->
<h3 slot="header">2、多插槽/具名插槽</h3>
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
<p slot="footer">这里有一些联系信息</p>
</muli-slots>
<!--作用域插槽-->
<!--在父级中,具有特殊特性 slot-scope 的 <template> 元素必须存在,表示它是作用域插槽的模板。
slot-scope 的值将被用作一个临时变量名,此变量接收从子组件传递过来的 prop 对象:-->
<div class="parent">
<h3>3、作用域插槽</h3>
<scoped-slot>
<template slot-scope="props">
<!--这里的props指的是子组件的props-->
<span>this is from parent</span>
<span>{{props.msg}}</span>
</template>
</scoped-slot>
</div>
<div>
<h3>4、使用render代替子组件中的template</h3>
<render-slot></render-slot>
</div>
<div>
<h3>5、子组件中同时存在template和render函数</h3>
<render-template></render-template>
</div>
<div>
<h3>6、在render函数中使用作用域插槽</h3>
<render-scope>
<template slot-scope="props">
<p>{{props.msg}}</p>
</template>
</render-scope>
</div>
<!--父组件通过props向子组件传值-->
<div class="parent">
<h3>7、父组件通过props向子组件传值,值在template的slot标签中接收</h3>
<!--传递的值需要写在子组件的标签中-->
<child datamsg="传递的值" msg2="第二个值"></child>
</div>
<div>
<h3>8、父组件通过props向子组件传值,值在render函数返回的createElement函数中接收</h3>
<child-render msg="render send data">
<template slot-scope="props">
<em>{{props.text}}</em>
</template>
</child-render>
</div>
<div>
<h3>9、与8等价的template</h3>
<child-render-template msg="template send data">
<template slot-scope="props">
<em>{{props.text}}</em>
</template>
</child-render-template>
</div>
</div>
<script></script>
复制代码