效果图:
参数:
参数名 | 类型 | 默认值 |
---|---|---|
value(默认值) | Array | [] |
placeholder(输入框占位文本) | String | 请选择 |
disabled(是否禁用) | Boolean | false |
clearable(是否支持清空选项) | Boolean | true |
separator(选项分隔符) | String | / |
checkStrictly(是否可以选任意一项) | Boolean | false |
level(联动级别) | Number | 4 |
getAreaData(数据返回) | Function | {} |
数据返回:
字段名称 | 类型 |
---|---|
key | Array |
value | Array |
keyText | String |
valueText | String |
返回试例:
HTML代码:
<template>
<div class="cascader">
<el-cascader
v-model="valueData"
:options="options"
:props="props"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
:separator="separator"
ref="Cascader"
class="Cascader"
@change="handleChange"
@expand-change="expandChange"
></el-cascader>
</div>
</template>
<script>
import { areaData } from "./area-vue";
export default {
name: "Cascader",
props: {
// 默认值
value: {
type: Array,
default: () => []
},
// 输入框占位文本
placeholder: {
type: String,
default: "请选择"
},
// 是否禁用
disabled: {
type: Boolean,
default: false
},
// 是否支持清空选项
clearable: {
type: Boolean,
default: true
},
// 选项分隔符
separator: {
type: String,
default: "/"
},
// 是否可以选任意一项
checkStrictly: {
type: Boolean,
default: false
},
// 联动级别
level: {
type: Number,
default: 4
},
// 数据返回
getAreaData: {
type: Function,
default: () => {
return {
key: [],
value: [],
keyText: "",
valueText: ""
};
}
}
},
data() {
return {
valueData: [],
options: [],
props: {
checkStrictly: this.checkStrictly,
value: "key",
label: "value"
}
};
},
mounted() {
this.initData();
},
methods: {
// 渲染默认数据
defaultData() {
if (this.value.length > 0) {
let data = [];
this.value.forEach((v) => {
data.push(v);
this.expandChange(data);
});
}
},
// 当选中节点变化时触发
handleChange() {
this.$nextTick(() => {
let node = this.$refs.Cascader.getCheckedNodes()[0];
let data = {
key: node ? node.path : [],
value: node ? node.pathLabels : [],
keyText: node ? node.path.join(this.separator) : "",
valueText: node ? node.pathLabels.join(this.separator) : ""
};
this.getAreaData(data);
if (this.$refs.Cascader.dropDownVisible && this.checkStrictly) {
this.$refs.Cascader.toggleDropDownVisible();
}
});
},
// 当展开节点发生变化时触发
expandChange(e) {
if (this.level >= 2) {
const dataKey = e[e.length - 1];
if (areaData[dataKey]) {
const key = Object.keys(areaData[dataKey]);
key.forEach((v) => {
let data = {
key: v,
value: areaData[dataKey][v],
children: []
};
if (!areaData[v] || e.length + 1 == this.level) {
delete data.children;
}
this.someFilter(this.options, data, dataKey);
});
}
}
},
// 递归当前选中node
someFilter(array, data, key) {
array.some((item) => {
if (item.key == key && item.children) {
item.children.push(data);
} else {
if (item.children) {
this.someFilter(item.children, data, key);
}
}
});
},
// 初始化一级菜单
initData() {
if (this.value.length >= this.level) {
this.value.forEach((v, i) => {
if (i < this.level) {
this.valueData.push(v);
}
});
} else {
this.valueData = this.value;
}
const key = Object.keys(areaData["86"]);
key.forEach((v) => {
let data = {
key: v,
value: areaData["86"][v],
children: []
};
if (this.level == 1) {
delete data.children;
}
this.options.push(data);
});
this.defaultData();
}
}
};
</script>
<style scoped>
.cascader,
.Cascader {
width: 100%;
}
</style>
父组件调用:
import Cascader from "@/components/cascader.vue";
components: {
Cascader
},
<Cascader :value="[]" :getAreaData="getAreaData" />
// 获得选中的地址数据
getAreaData(data) {
console.log(data);
}
下载原生资源 area-vue.js
适用于本封装组件,占用空间小
export const areaData = {"110000":{"110100":"北京市"},"110100":{"110101":"东城区","110102":"西城区","110105":"朝阳区","110106":"丰台区","110107":"石景山区","110108":"海淀区","110109":"门头沟区","110111":"房山区","110112":"通州区","110113":"顺义区","110114":"昌平区","110115":"大兴区","110116":"怀柔区","110117":"平谷区","110118":"密云区","110119":"延庆区"},...}
下载可直接用的 areaData.js
适用于各类应用场景,导入js就能用,占用空间大
const areaData = [
{
"key": "110000",
"value": "北京市",
"children": [
{
"key": "110100",
"value": "北京市",
"children": [
{
"key": "110101",
"value": "东城区",
"children": [...]
}
}
]
}
]
个人常用组件—不喜勿喷,谢谢!!!祝君生活愉快~~~~