在使用element-ui的时候我们会经常用到插槽。
1.element-ui里面的插槽语法
如:一个dialog组件
代码:
<template>
<div class="">
<el-button type="text" @click="dialogVisible = true"
>点击打开 Dialog</el-button
>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose"
>
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
dialogVisible: false,
};
},
methods: {
handleClose(done) {
this.$confirm("确认关闭?")
.then(() => {
done();
})
.catch(() => {});
},
},
};
</script>
<style scoped></style>
slot='footer' 默认插槽
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</span>
定义标题:
这相当于一个传值的过程。
下拉菜单:
代码:
<template>
<div class="">
<el-dropdown :hide-on-click="false">
<span class="el-dropdown-link">
下拉菜单<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>黄金糕</el-dropdown-item>
<el-dropdown-item>狮子头</el-dropdown-item>
<el-dropdown-item>螺蛳粉</el-dropdown-item>
<el-dropdown-item disabled>双皮奶</el-dropdown-item>
<el-dropdown-item divided>蚵仔煎</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<script>
export default {
name: "",
methods: {},
};
</script>
<style scoped>
.el-dropdown-link {
cursor: pointer;
color: #409eff;
}
.el-icon-arrow-down {
font-size: 12px;
}
</style>
这里面通过slot=‘dropdown’包裹着:
同样也是使用了具名插槽。
2.插槽的种类与用法
什么是插槽?
我理解的就是占位。 举个例子来讲,我们去封装一个组件,这个组件被很多的页面同时用到,但是又有些甚微的差别,这个时候我们可以用插槽来解决此问题。
用图来表示:
假设这个头部的组件在很多的地方使用,但是标题 和内容不一样这个时候就插槽排上用场了。
插槽的种类和用法
种类
1.默认插槽 没名字插槽
2.具名插槽 用名字的插槽
3.作用域插槽 传递数据的插槽
用法
在此之前组件都是全局注册过的
在main.js
import One from "@/components/One.vue";
Vue.component(One.name, One);
1.默认插槽
直接在标签里面些东西。
传:
<template>
<div class="">
<One>123</One>
</div>
</template>
收One组件:
<template>
<div class="">
<slot />
</div>
</template>
2.具名插槽
传递:
<template>
<One>
<template #aa>
<div>
<button>增加</button>
<button>删除</button>
</div>
</template>
</One>
</template>
在这个One组件里面
占位:
<template>
<div class="">
<slot name="aa" />
</div>
</template>
在当前封装的组件里面进行占位,传过来两个按钮。
3.作用域插槽
传递数据:
<template>
<div class="">
<slot :data="form" />
</div>
</template>
<script>
export default {
data() {
return {
form: {
name: "张三",
age: 20,
},
};
},
name: "One",
methods: {},
};
</script>
<style scoped></style>
接收:
<template>
<One>
<template v-slot="row">
<div>{{ row }}</div>
</template>
</One>
</template>
<script>
export default {
data() {
return {};
},
methods: {},
};
</script>
<style scoped></style>
view:
可以看到已经传递过去了。
这一幕是不是很相似呢?
请看下面的图片:
这里的slot-scope是2.60以前的写法2.60以后使用的是v-slot的写法,这是在表格里面使用的插槽。
3.案例
我们全局注册一个组件:
注册的组件:
<template>
<div class="pageTools">
<div class="left">
<i class="el-icon-info" />
<slot name="left" />
</div>
<div class="right">
<slot name="right" />
</div>
</div>
</template>
<script>
export default {
// 组件的名字
name: 'PageTools',
props: {
showLeft: {
type: Boolean,
default: true
}
},
methods: {}
}
</script>
<style lang="scss" scoped>
.pageTools {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 20px;
.left {
background-color: pink;
border: 1px solid #91d5ff;
display: flex;
align-items: center;
.el-icon-info {
color: #409eff;
}
}
.right {
display: flex;
align-items: center;
}
}
</style>
在main.js里面
import PageTools from '@/components/lib/pageTools.vue'
Vue.component(PageTools.name, PageTool
我们在一个页面通过插槽来使用自己的组件
代码:
<template>
<div class="">
<PageTools>
<template #left>
<div>
<span>有10条记录</span>
</div>
</template>
<template #right>
<div>
<el-button type="primary">新增</el-button>
<el-button type="primary"> 删除</el-button>
</div>
</template>
</PageTools>
</div>
</template>
<script>
export default {
name: '',
methods: {}
}
</script>
<style scoped></style>
view图:
现在我们在使用的使用不需要左侧的
通过给组件的传值来控制组件的显示和隐藏。
代码:
<template>
<div class="">
<PageTools :show-left="false">
<template #left>
<div>
<span>有10条记录</span>
</div>
</template>
<template #right>
<div>
<el-button type="primary">新增</el-button>
<el-button type="primary"> 删除</el-button>
</div>
</template>
</PageTools>
</div>
</template>
<script>
export default {
name: '',
methods: {}
}
</script>
<style scoped></style>
view图:
为什么还是有背景色有边框的影响
解决:
<template>
<div class="pageTools">
<div class="left">
<div v-if="showLeft" class="left-content">
<i class="el-icon-info" />
<slot name="left" />
</div>
</div>
<div class="right">
<slot name="right" />
</div>
</div>
</template>
<script>
export default {
// 组件的名字
name: 'PageTools',
props: {
// 默认有左边
showLeft: {
type: Boolean,
default: true
}
},
methods: {}
}
</script>
<style lang="scss" scoped>
.pageTools {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 20px;
.left {
.left-content {
background-color: #91d5ff;
border: 1px solid #91d5ff;
display: flex;
align-items: center;
.el-icon-info {
color: #409eff;
}
}
}
.right {
display: flex;
align-items: center;
}
}
</style>
通过包裹住一层盒子来解决问题。
4.默认插槽
别看默认插槽,里面还藏了很多的猫腻。
v-slot和#是一样的
v-slot:aa 表示为名字aa的插槽相对应。
如果v-slot啥也不写对应的就是v-slot:default,也就是对应的默认插槽。
代码:
<template>
<div>
<One #aa>aa插槽的内容</One>
<One #cc>cc插槽的内容</One>
<One>
<template v-slot>
<div>默认插槽的内容</div>
</template>
</One>
</div>
</template>
<script>
export default {
name: "",
methods: {},
};
</script>
<style scoped></style>
One组件:
<template>
<div class="">
<slot name="default"></slot>
<slot name="aa"></slot>
<slot name="cc"></slot>
</div>
</template>
<script>
export default {
name: "One",
methods: {},
};
</script>
<style scoped></style>
仔细看#default就是通过默认 转化下就是v-slot:default 就是默认插槽。
那么通过作用域获取数据的两种方式:
1.默认的方式
v-slot=‘row’ v-slot:default=‘row’ 是等价的
2.具名的方式
v-slot:aa=row 等价于#aa=‘row’
代码:
<template>
<div class="">
<One>
<template v-slot:default="row">
<div>
{{ row }}
</div>
</template>
</One>
</div>
</template>
<script>
export default {
data() {
return {
age: 20,
};
},
name: "",
methods: {},
};
</script>
<style scoped></style>
<template>
<div class="">
<slot :data="form" />
</div>
</template>
<script>
export default {
data() {
return {
form: {
name: "张三",
age: 20,
},
};
},
name: "One",
methods: {},
};
</script>
<style scoped></style>
因此我们平常在写v-slot=‘row’的时候其实v-slot:default=‘row’ 这两种都是默认插槽的写法。
平常我们只是剩去了default。
5.易错点
1.注意默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确
<!-- 无效,会导致警告 -->
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
<template v-slot:other="otherSlotProps">
slotProps is NOT available here
</template>
</current-user>
2.注意 v-slot
只能添加在 <template>
上 (只有一种例外情况),这一点和已经废弃的 slot attribute 不同。
3.v-slot的缩写是#,如#default 就是v-slot:default #header就是v-slot:header。
4.默认插槽:我们平常在写v-slot=‘row’的时候其实v-slot:default=‘row’ 这两种都是默认插槽的写法,
我们平常只是省去了default。
不能坚持到底,即使是朽木也不能折断.只要坚持不停地用刀刻,就算是 金属玉石也可以雕出花饰.
雕刻一下便放弃,即使是腐朽的木头也不能被折断;雕刻并且持之以恒,就是金石也能被雕刻.
出自:荀子《劝学》。