一.插槽
如何在同一个组件复用多次时,渲染不同的标签?
可以使用插槽来实现.
要使用插槽,组件挂载必须使用双标签.
子组件中,通过内置组件slot来引入插槽.
组件插槽最终会替换slot组件.
1. 默认插槽
<script>
// 以下的插槽是默认插槽.
// 默认插槽可以是多个标签.
const box = {
template: `
<div>
<h3>{{title}}</h3>
<p>大家都好</p>
<slot />
</div>
`,
props: ['title']
}
const App = {
template: `
<div>
<box title='你好'>
<button>按钮111</button>
<button>按钮222</button>
</box>
<box title='他好'>
<span>span</span>
</box>
<box title='我好'>
<a href='#'>百度一下</a>
</box>
</div>
`,
components: { box }
}
new Vue({
el: '#app',
render: h => h(App)
})
</script>
2. 具名插槽
具名插槽 => 具有name属性命名的插槽。插槽内容需要通过slot来对应name属性.
具名插槽可以一对多.
如果要一对多,可以用template抽象组件包裹所有的插槽内容.然后给template组件设置slot.
template内置的抽象组件 => 最终不会渲染到页面上. => 只能在插槽中使用.
如果多个组件的模板多数类似,少数不一致,就可以使用插槽来复用组件.
<script src="js/vue.js"></script>
<script>
const box = {
template: `
<div>
<slot name='a' />
<h3>{{title}}</h3>
<slot name='span' />
<slot name='btn2' />
<p>大家都好</p>
<slot name='btn1' />
</div>
`,
props: ['title']
}
const App = {
template: `
<div>
<box title='你好'>
<button slot='btn1'>按钮1111</button>
<button slot='btn2'>按钮2222</button>
</box>
<box title='他好'>
<template slot='span'>
<span>span</span>
<span>span</span>
</template>
</box>
<box title='我好'>
<a href='#' slot='a'>百度一下</a>
</box>
</div>
`,
components: { box }
}
new Vue({
el: '#app',
render: h => h(App)
})
</script>
3. 作用域插槽
什么情况下用作用域插槽?
插槽内容中包含子组件数据时,就得用作用域插槽.
作用域插槽内有子组件数据,但是默认却在父组件上找数据,找不到会报错.
可以通过给组件添加一个v-slot指令,这样组件内部就构成了一个作用域。
插槽内部的数据,会优先在作用域内查找.
v-slot的值,默认是一个对象,这个对象的名字可以任意书写
这个对象就能获取到slot组件上的所有绑定数据.
v-slot支持解构赋值的写法.
<script>
const box1 = {
template: `
<div>
<table border='1' cellspacing='10' cellpadding='10'>
<tr v-for='({name,age,sex,nation}) in arr'>
<td>{{name}}</td>
<td>{{age}}</td>
<td>{{sex}}</td>
<slot :nation='nation' a='100' c='200' />
</tr>
</table>
</div>
`,
data() {
return {
arr: [
{
name: '幂幂',
age: 32,
sex: '女',
nation: '汉'
}, {
name: '超越',
age: 23,
sex: '女',
nation: '苗'
}, {
name: '德刚',
age: 65,
sex: '男',
nation: '蒙古'
}
]
}
}
}
const App = {
template: `
<div>
<box1></box1>
<box1 v-slot='{nation}'>
<td>{{nation}}</td>
</box1>
</div>
`,
components: { box1 }
}
new Vue({
el: '#app',
render: h => h(App)
})
</script>
如果在组件上使用v-slot,则默认只能获取到默认插槽的绑定数据。
如果是具名插槽,就不能再组件上使用v-slot指令.
需要在template组件上使用 => v-slot:插槽名
<script>
const box1 = {
template: `
<div>
<table border='1' cellspacing='10' cellpadding='10'>
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<slot name='c'></slot>
</tr>
</thead>
<tr v-for='({name,age,sex,nation,marryed}) in arr'>
<td>{{name}}</td>
<td>{{age}}</td>
<td>{{sex}}</td>
<slot name='a' :marryed='marryed' />
<slot name='b' :nation='nation'/>
</tr>
</table>
</div>
`,
data() {
return {
arr: [
{
name: '幂幂',
age: 32,
sex: '女',
nation: '汉',
marryed: '已离异'
}, {
name: '超越',
age: 23,
sex: '女',
nation: '苗',
marryed: '未婚'
}, {
name: '德刚',
age: 65,
sex: '男',
nation: '蒙古',
marryed: '已婚'
}
]
}
}
}
const App = {
template: `
<div>
<box1>
<th slot='c'>婚姻状况</th>
<template v-slot:a='{marryed}' slot='a'>
<td>{{marryed}}</td>
</template>
</box1>
<box1>
<th slot='c'>民族</th>
<template v-slot:b='{nation}' slot='b'>
<td>{{nation}}</td>
</template>
</box1>
</div>
`,
components: { box1 }
}
new Vue({
el: '#app',
render: h => h(App)
})
</script>