文章知识点
1,插槽基本使用
2,具名插槽
3,作用域插槽
什么是插槽
slot即插槽。
生活中,我们都知道USB插槽,USB插槽可以连接其他设备,从而进行操作。Vue的插槽跟它的功能类似。
使用插槽的目的:即使原有的Vue组件更具扩展行。
插槽的基本使用
在使用时,直接在组件模板中使用<slot></slot>
标签,即完成预留插槽。
话不多说,上实例
<body>
<div id="app">
<!-- 在组件标签中使用span、i或者其他标签并在里面写入内容即可替换slot -->
<cpn><span>用笔者,天也,流美者,地也</span></cpn>
<cpn><i>横如千里阵云,折如百钧弩发</i></cpn>
</div>
<template id="tem">
<div>
<h3>善书者自有风骨,尽一身之力而颂之</h3>
<!-- 预留插槽 -->
<slot></slot>
</div>
</template>
<script src="./js/vue.min.js"></script>
<script>
let cpn = {
template:"#tem"
}
Vue.component("cpn",cpn)
let app = new Vue({
el:"#app"
})
</script>
</body>
效果图:
具名插槽
具名插槽,就是具有名字的插槽。对,起名就是这么随便嘿!
假如说,我现在有一个组件
<body>
<div id="app">
<cpn></cpn>
</div>
<template id="tem">
<div>
<!-- 插槽也可以设置默认值 -->
<slot ><span>左边</span></slot>
<slot ><span>中间</span></slot>
<slot><span>右边</span></slot>
</div>
</template>
<script src="./js/vue.min.js"></script>
<script>
let cpn = {
template:"#tem"
}
Vue.component("cpn",cpn)
let app = new Vue({
el:"#app"
})
</script>
</body>
显示在页面上
那么我现在有个需求,想把中间那个插槽替换,而其他不变,该如何实现呢?
肯定是不能直接替换的,因为你替换一个那全部的内容都会变。此时,我们的具名插槽就闪亮登场了!
我们可以在模板中给插槽定义一个name属性,然后在渲染的时候指定这个插槽即可
<body>
<div id="app">
<cpn><span slot="center">我要在中间</span></cpn>
</div>
<template id="tem">
<div>
<!-- 插槽也可以设置默认值 -->
<slot ><span>左边</span></slot>
<slot name="center"><span>中间</span></slot>
<slot><span>右边</span></slot>
</div>
</template>
<script src="./js/vue.min.js"></script>
<script>
let cpn = {
template:"#tem"
}
Vue.component("cpn",cpn)
let app = new Vue({
el:"#app"
})
</script>
</body>
那我们就替换完成了
作用域插槽
编译作用域
在整明白啥叫作用域插槽之前,我们先了解一下编译作用域。
当vue实例data中有一个属性跟组件中data的属性名是相同时,在vue实例作用范围内即组件标签会使用vue实例中的data里的属性,但在组件作用范围模板中则会使用组件中data的属性。
用一句话解释就是父组件模板中的所有代码都会在父级作用域中编译,同样的子组件模板中的所有代码也都会在子级作用域中编译
Emma,语言真苍白,看实例吧
<body>
<div id="app">
<!-- 此时的isShow会使用vue实例中的isShow -->
<cpn v-show="isShow"></cpn>
</div>
<template id="tem">
<h2>剑指的方向,就是天才的故乡</h2>
</template>
<script src="./js/vue.js"></script>
<script>
const cpn = {
template:"#tem",
isShow:false
}
const app = new Vue({
el:"#app",
data:{
<!-- 如果你把这里的true改成false那页面就不会显示内容 那就证明用的正是这里的isShow-->
isShow:true
},
components:{
cpn
}
} )
那此时我们打开页面,那个天才少年的豪言壮语会显示在页面上,如下图
如果我在模板里再加一句,如下:
<template id="tem">
<div>
<h2>剑指的方向,就是天才的故乡</h2>
<h3 style="color: red;" >角木犹比蛟,亢金宛如龙,尾火形似虎、箕水貌若豹……</h3>
</div>
页面显示图:
如果我在h3里加一个v-show,那它用的就是组件里的data中的isShow属性,即页面不会显示上图红色字
<body>
<div id="app">
<cpn v-show="isShow"></cpn>
</div>
<template id="tem">
<div>
<h2>剑指的方向,就是天才的故乡</h2>
<!-- 看这里 -->
<h3 style="color: red;" v-show="isShow">角木犹比蛟,亢金宛如龙,尾火形似虎、箕水貌若豹……</h3>
</div>
</template>
<script src="./js/vue.js"></script>
<script>
const cpn = {
template:"#tem",
<!-- 此时的isShow会使用这里中的isShow -->
isShow:false
}
const app = new Vue({
el:"#app",
data:{
isShow:true
},
components:{
cpn
}
} )
</script>
</body>
呐,这就是编译作用域了。
作用域插槽
为啥在讲作用域插槽时,我要先费劲巴拉的说一下编译作用域呢,因为作用域插槽就符合编译作用域的原理的
现在我有一个组件,并且把组件里的数据渲染到页面上
<body>
<div id="app">
<div>
<cpn></cpn>
</div>
</div>
<template id="tem">
<div>
<slot>
<ul>
<li v-for="item in hero">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="./js/vue.js"></script>
<script>
const cpn = {
template:'#tem',
data(){
return {
hero:['小鲁班','李元芳','后羿','马可波罗','虞姬']
}
}
}
const app = new Vue({
el:"#app",
components:{
cpn
}
})
</script>
</body>
页面显示如下:
我现在的需求是,当我第二次使用时,我不想让让数据这么排列,我想要横着且用*隔开,注意必须要用组件data 里hero属性的数据渲染哦,像这样,
由于编译作用域,我直接用hero里的数据是拿不到的。
那怎么实现呢?
我们可以先在插槽中自定义一个属性,把子组件的hero赋值给这个属性
<template id="tem">
<div>
<!-- 自定义一个data属性并赋值 -->
<slot :data="hero">
<ul>
<li v-for="item in hero">{{item}}</li>
</ul>
</slot>
</div>
在第二次使用组件标签时,用一个template标签 也可以用别的html标签比如div,但为了更好的兼容最好还是用template。
<cpn>
<!-- 在template中使用 -->
<template slot-scope="slot">
<span v-for="item in slot.data">{{item}}*</span>
</template>
</cpn>
但最后还有一个*,真是难死强迫症。因为hero是一个数组,所以我们可以用join方法拼接啊。改良版如下
<cpn>
<!-- 在template中使用 -->
<template slot-scope="slot">
<!-- <span v-for="item in slot.data">{{item}}*</span> -->
<span>{{slot.data.join('*')}}</span>
</template>
</cpn>
嗯,舒服多了~
完整代码附上
<body>
<div id="app">
<div>
<cpn></cpn>
<!-- 当我展示第二次的时候每个英雄之间我想用一个*隔开 -->
<cpn>
<!-- 在template中使用 -->
<template slot-scope="slot">
<!-- <span v-for="item in slot.data">{{item}}*</span> -->
<span>{{slot.data.join('*')}}</span>
</template>
</cpn>
</div>
</div>
<template id="tem">
<div>
<slot :data="hero">
<ul>
<li v-for="item in hero">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="./js/vue.js"></script>
<script>
const cpn = {
template:'#tem',
data(){
return {
hero:['小鲁班','李元芳','后羿','马可波罗','虞姬']
}
}
}
const app = new Vue({
el:"#app",
components:{
cpn
}
})
</script>
</body>
这,就是插槽~