记录二次封装 element 的备忘点
v-model 绑定输入值,在template 中属性使用 v-model, v-model 使用的值可以是 computed 来接收值,如果是需要往上级 emit 数据变化的,要在 computed 中的设置 get()、set()
级联无法在封装的组件 v-model 的值改变后反显失败,这里查看了组件源码后发现,这个地方是在渲染的时候绑定了缓存的值,所以要给 el-cascader 添加 key 来让组件能够反显渲染
省市区组件代码
<template>
<div class="city-container">
<el-cascader
:key="cascaderKey"
ref="city"
v-model="values"
:props="cAttrs"
separator="-"
clearable
width="100%"
:options="options"
@change="handleChangeValue"
/>
</div>
</template>
<script>
import dictApi from "../server/dictApi";
export default {
name: "City",
props: {
value: {
type: Array,
default() {
return [];
},
},
attrs: {
type: Object,
default() {
return {};
},
},
options: {
type: Array,
default() {
return [];
},
},
level: {
type: Number,
default: 2,
required: false,
},
},
data() {
return {
cascaderKey: 0,
};
},
computed: {
cAttrs() {
return Object.assign(
{
value: "cityCode",
label: "name",
lazy: true,
lazyLoad: (node, resolve) => {
const { level, value } = node;
dictApi
.getCityData({ level: level + 1, parentCode: value || 0 })
.then(
(data) => {
data.map((item) => {
item.leaf = level >= this.level;
return item;
});
resolve(data);
},
(err) => {
this.$message.warning(err);
}
);
},
},
this.attrs
);
},
values: {
get() {
return this.value.map((item) => {
return item;
});
},
set(val) {
this.$emit("input", val);
},
},
},
watch: {
value() {
this.cascaderKey++;
},
},
methods: {
handleChangeValue(val) {
let selectedLabels =
this.$refs.city.getCheckedNodes() !== undefined &&
this.$refs.city.getCheckedNodes().length > 0 &&
this.$refs.city.getCheckedNodes()[0].pathLabels;
this.$emit("change", val, selectedLabels);
this.$emit("input", val);
},
},
};
</script>
扩展 render 的写法继承 element 组件所有的属性和事件
有时候封装组件是为了组件的一致性限制了组件的属性,有时候需要实现不同的业务需求的时候,又需要用到 element 组件的属性或事件,这种情况就最好把属性都继承过来传递给 element 的原生组件中。
export default {
render() {
return (
<el-input
vModel={this.model}
{...{
attrs: this.$attrs,
on: this.$listeners,
}}
clearable
></el-input>
);
},
};