1.1 插槽
-
组件的最大特性就是复用性,而用好插槽能大大提高组件的可复用能力
-
在Vue中插槽是很重要的存在,通过插槽,我们可以把 父组件中指定的DOM 作用到 子组件的任意位置,后面我们做项目用到的组件库比如element-ui,vant-ui都频繁用到的插槽,Vue的插槽主要有匿名插槽,具名插槽,作用域插槽三种,下面我们分别来认识一下他们。
插槽插槽实质是对子组件的扩展,通过<slot>插槽-----向组件内部“指定位置” 放置内容。
插槽设置的地方:一定是在子组件中。子组件可以在任意位置添加slot。
父组件提供插槽内容。
1.1.1 匿名插槽
故名思义就是没有名字的插槽,只需要在子组件中使用<slot></slot>
引入即可
我们来看一下案例,如何引入匿名插槽的:
<div id="app">
<!-- 组件复用的时候,父组件向子组件的插槽中放置内容 -->
<alert-box>小马过河</alert-box>
<alert-box>这里有一个bug</alert-box>
</div>
<template id="alert-box">
<div>
<h1>我是子组件alert-box</h1>
<strong>ERROR:</strong>
<h1 style="color:red">
<slot>
默认内容
</slot>
</h1>
</div>
</template>
<script src="./js/vue.js"></script>
<script>
Vue.component('alert-box',{
template:`#alert-box`,
data(){
return{
}
}
})
var vm=new Vue({
//模板选择器
el:'#app',
//数据中心
data(){
return{
}
},
methods:{
}
})
</script>
预览:
1.1.2 具名插槽
-
具有名字的插槽就是具名插槽
-
使用
<slot>
中的 "name" 属性绑定元素,name就是插槽的名字
.title{
font-size: 30px;
color: blue;
}
.price{
font-size: 26px;
color: green;
}
.descriptions{
font-size: 22px;
color: purple;
}
<div id="app">
<parent></parent>
</div>
<template id="child">
<div>
<h1>我是子组件</h1>
<div class="title">
<slot name="t"></slot>
</div>
<div class="price">
<slot name="p"></slot>
</div>
<div class="descriptions">
<slot name="des"></slot>
</div>
</div>
</template>
<template id="parent">
<div>
<h1>我是父组件</h1>
<child>
<h1 slot="t">{{title}}</h1>
<h2 slot="p">{{price}}</h2>
<p slot="des">{{descriptions}}</p>
</child>
</div>
</template>
<script src="./js/vue.js"></script>
<script>
//子组件
var child={
template:`#child`,
data(){
return{
}
}
}
//父组件
var parent={
template:`#parent`,
data(){
return{
title:'活着 (余华著长篇小说)',
price:'56.9',
descriptions:'讲述了在大时代背景下,随着内战、三反五反,大跃进,文化大革命等社会变革,徐福贵的人生和家庭不断经受着苦难,到了最后所有亲人都先后离他而去,仅剩下年老的他和一头老牛相依为命。'
}
},
components: {
child
}
}
//根组件
var vm=new Vue({
//模板选择器
el:'#app',
//数据中心
data(){
return{
}
},
methods:{
},
components:{
parent
}
})
</script>
预览:
1.1.3 作用域插槽
作用域插槽(带数据的插槽):绑定数据的插槽slot插槽scope作用域
作用域插槽要求,在slot上面绑定数据。
-
可以让父组件对子组件的内容进行加工处理。
-
既可以复用子组件的slot,又可以使slot内容不一致。
-
父组件中使用
slot-scope
绑定一个属性 -
子组件中给
<slot>
标签绑定一个自定义属性,可以传递子组件的内容 -
父组件通过
slot-scope
接受子组件传递过来的值即可
-
.current{
font-size: 30px;
color: red;
}
.active{
font-size: 45px;
color: green;
}
.yty{
font-size: 39px;
color: pink;
}
<div id="app">
<fruit-list :list="list">
<!--2.父组件中使用`slot-scope`绑定一个属性
scopes在这里只是临时变量
-->
<template slot-scope="scopes">
<strong v-if="scopes.info.id==3" class="current">
{{scopes.info.name}}
</strong>
<span>{{scopes.info.name}}</span>
</template>
</fruit-list>
<fruit-list :list="list">
<!--2.父组件中使用`slot-scope`绑定一个属性
scopes在这里只是临时变量
-->
<template slot-scope="scopes">
<strong v-if="scopes.info.id==2" class="active">
{{scopes.info.name}}
</strong>
<span>{{scopes.info.name}}</span>
</template>
</fruit-list>
</div>
<template id="fruit-list">
<div>
<ul>
<li v-for="item in list" :key="item.id">
<!-- 作用域插槽使用的第一步:在子组件的slot上定义一个属性:info -->
<!-- 如果有数据传递过来,数据会被渲染到这个插槽上 -->
<!-- :绑定数据的插槽,这个就叫做作用域插槽 -->
<slot :info="item">默认内容</slot>
</li>
</ul>
</div>
</template>
<script src="./js/vue.js"></script>
<script>
//子组件
Vue.component('fruit-list',{
props:['list'],
template:`#fruit-list`,
data(){
return{
}
}
})
//父组件
var vm=new Vue({
//模板选择器
el:'#app',
//数据中心
data(){
return{
list:[
{
id: 1,
name: 'apple'
},
{
id: 2,
name: 'orange'
},
{
id: 3,
name: 'banana'
}
]
}
},
methods:{
}
})
</script>
预览:
分析:
可以让 父组件 对 子组件的内容 进行加工处理
-
父组件中使用
slot-scope
绑定一个属性 -
子组件中给
<slot>
标签绑定一个自定义属性,可以传递子组件的内容 -
父组件通过
slot-scope
接受子组件传递过来的值即可
1.2 插槽综合案例讲解-分页组件
分页组件
.sync修饰符,可以对 单个 prop进行双向绑定
.sync
修饰符可以像v-model
一样实现类似双向绑定
的场景用法 。
我们在父组件中,使用 :page.sync="uPage" 实现的作用是:双向数据绑定,即:子传父,子组件将数据传递给父组件。父组件同时,在这里可以将数据传递给子组件。
父组件设置如下:
<w-pagination :total="list.length" :page.sync="uPage" :prepage="prePage"></w-pagination>
子组件设置如下:
我们用下面这种形式传参
$emit('update:xx', 参数)
例如:
this.$emit('update:page',p);
因为如果不用这种方法
子组件内的props参数将无法成功修改,而是没有反应
,所以Vue官方建议我们在子组件触发传递父组件事件中
也同样用update:xx
这种写法。
.current{
font-size: 30px;
color: red;
}
.active{
font-size: 45px;
color: green;
}
.yty{
font-size: 39px;
color: pink;
}
<div id="app">
<fruit-list :list="list">
<!--2.父组件中使用`slot-scope`绑定一个属性
scopes在这里只是临时变量
-->
<template slot-scope="scopes">
<strong v-if="scopes.info.id==3" class="current">
{{scopes.info.name}}
</strong>
<span>{{scopes.info.name}}</span>
</template>
</fruit-list>
<fruit-list :list="list">
<!--2.父组件中使用`slot-scope`绑定一个属性
scopes在这里只是临时变量
-->
<template slot-scope="scopes">
<strong v-if="scopes.info.id==2" class="active">
{{scopes.info.name}}
</strong>
<span>{{scopes.info.name}}</span>
</template>
</fruit-list>
</div>
<template id="fruit-list">
<div>
<ul>
<li v-for="item in list" :key="item.id">
<!-- 作用域插槽使用的第一步:在子组件的slot上定义一个属性:info -->
<!-- 如果有数据传递过来,数据会被渲染到这个插槽上 -->
<!-- :绑定数据的插槽,这个就叫做作用域插槽 -->
<slot :info="item">默认内容</slot>
</li>
</ul>
</div>
</template>
<script src="./js/vue.js"></script>
<script>
//子组件
Vue.component('fruit-list',{
props:['list'],
template:`#fruit-list`,
data(){
return{
}
}
})
//父组件
var vm=new Vue({
//模板选择器
el:'#app',
//数据中心
data(){
return{
list:[
{
id: 1,
name: 'apple'
},
{
id: 2,
name: 'orange'
},
{
id: 3,
name: 'banana'
}
]
}
},
methods:{
}
})
</script>
预览: