有一个页面用到了几种样式不同的Dropdown按钮,想将每个dropdown按钮的开关状态分组件管理,但是封装了组件之后按钮又难以自定义,所以想出这样一个 使用slot传出值方式来将封装在组件内部的方法和状态绑定到组件外自定义的按钮上 的方法。
Dropdown组件:
因为要兼容ie9,没有使用 他处点击指令(关键api contains 在ie10才受到支持)
<template>
<div class="dropdown-box">
<!-- 下拉框打开时的遮罩层 -->
<div class="backdrop" v-show="dropdownShow" @click="toggleDropdown"></div>
<!-- 关键代码 -->
<!-- 将value传出组件。将按钮的点击事件传出组件 -->
<slot :label="getDropdownValue(FilterOptions, value)" :click="toggleDropdown"/>
<!-- 此处也可使用slot自定义:将click事件、dropdownShow传出组件,在组件外绑定到元素上 -->
<ul class="select" v-show="dropdownShow">
<li class="option"
v-for="item in FilterOptions"
:key="item.value"
@click="$emit('change', item.value)"
>
<a>{{item.label}}</a>
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
FilterOptions: Array, // 接收dropdown的枚举值
value: Number, // v-model绑定的当前选择的value
},
data() {
return {
dropdownShow: false, // 是否展示下拉框
}
},
// 自定义组件的v-model
model: {
prop: 'value',
event: 'change'
},
methods: {
// 打开、关闭下拉框,回调函数
toggleDropdown() {
this.dropdownShow = !this.dropdownShow;
if(this.dropdownShow) {
this.$emit('open');
} else {
this.$emit('close');
}
},
// 获取dropdown的label值展示在按钮上
getDropdownValue(filterOptions, val) {
return filterOptions.find(item => item.value === val)?.label;
},
}
}
</script>
<style lang="less" scoped>
.backdrop{
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
z-index: 50;
}
.dropdown-box{
position: relative;
display: inline-block;
vertical-align: middle;
border: none;
.select{
position: absolute;
width: 100%;
top: 100%;
margin-top: 6px;
padding: 6px 0;
left: 0;
background: #f9f4e9;
box-shadow: 4px 4px 8px rgba(105, 105, 105, 0.2);
border: 1px solid #AE9672;
border-radius: 4px;
z-index: 51;
font-size: 12px;
text-align: center;
.option{
padding: 4px 3px;
&:hover{
text-decoration: underline;
}
}
}
}
</style>
使用:
<template>
<!-- 传入下拉框的枚举值,绑定v-model -->
<Dropdown :filter-options="filterOptions" v-model="form.filter1">
<!-- 给自定义的dropdown按钮添加Dropdown组件传出的click方法和label值 -->
<button class="dropdown" slot-scope="scope" @click="scope.click">
<span>{{scope.label}}</span>
<img src="@/assets/img/drop.png">
</button>
</Dropdown>
</template>
<script>
import Dropdown from "./Dropdown";
export default {
components: { Dropdown },
data() {
return {
filterOptions: [{ // Dropdown下拉框的枚举值格式
value: 0,
label: "全部",
}, {
value: 1,
label: "经部",
}, {
value: 2,
label: "史部",
}, {
value: 3,
label: "子部",
}, {
value: 4,
label: "集部",
}],
form: {
filter1: 0, // Dropdown的v-model
},
}
},
}
</script>