封装组件使用v-model
使用方法props接受value值,当值发生变化的时候再通过this.$emit("input", newValue),则实现了简单组件的v-model封装,如果不使用第三方UI可以接受到的值使用watch或者计算属性保存,然后再通过事件派发自己保存的值
$attrs可以透传组件上的属性,如果使用 props接收了某个属性,则从$attrs移除这个属性
代码:如elInput组件
保存值写法可使用计算属性也可以使用监听器
javascript"><template>
<div class="switchWrap">
<el-input
ref="refInput"
v-bind="$attrs"
:value="internalValue"
@input="updateValue"
>
</el-input>
</div>
</template>
<script>
export default {
props: {
value: [Boolean, String, Number],
},
data() {
return {};
},
computed: {
internalValue() {
return this.value;
},
},
methods: {
updateValue(newValue) {
this.$emit("input", newValue); // 触发内部 input 事件 让父组件可以v-model绑定
},
},
mounted() {},
};
</script>
不保存值可直接派发值
javascript"><template>
<div class="switchWrap">
<el-input
ref="refInput"
v-bind="$attrs"
:value="value"
@input="updateValue"
>
</el-input>
</div>
</template>
<script>
export default {
props: {
value: [Boolean, String, Number],
},
data() {
return {};
},
computed: {},
methods: {
updateValue(newValue) {
this.$emit("input", newValue); // 触发内部 input 事件 让父组件可以v-model绑定
},
},
mounted() {},
};
</script>
使用方法
javascript"> <elInput v-model="value"></elInput >
UI组件封装方法
$attrs和$slots可以透传属性和插槽 然后通过解构插槽——>#[插槽名]=value 就可以获取传递的值,再通过遍历组件原型上的方法,然后把原型上的方法放在组件上,就可以使用ref透传
使用计算属性 slotsKeys 和 scopedSlotsKeys
是为了动态获取父组件传递的具名插槽($slots)和作用域插槽($scopedSlots),
并根据需要排除掉某些已使用的插槽,以便在渲染时可以有选择地展示插槽内容。
javascript"><template>
<div class="switchWrap">
<el-input
ref="refInput"
v-bind="$attrs"
:value="value"
@input="updateValue"
>
<template v-for="slotName in scopedSlots" #[slotName]="scoped">
<slot :name="slotName" v-bind="scoped"></slot>
</template>
<template v-for="slotName of namedSlot" v-slot:[slotName]>
<slot :name="slotName"></slot>
</template>
</el-input>
</div>
</template>
<script>
export default {
props: {
value: [Boolean, String, Number],
},
data() {
return {
usedSlots: [], // 已使用的插槽
};
},
computed: {
// 使用计算属性 namedSlot 和 scopedSlots
// 是为了动态获取父组件传递的具名插槽($slots)和作用域插槽($scopedSlots),
// 并根据需要排除掉某些已使用的插槽,以便在渲染时可以有选择地展示插槽内容。
namedSlot() {
return Object.keys(this.$slots).filter(
(key) => !this.usedSlots?.includes(key)
);
},
scopedSlots() {
return Object.keys(this.$scopedSlots).filter(
(key) => !this.usedSlots?.includes(key)
);
},
},
methods: {
updateValue(newValue) {
this.$emit("input", newValue); // 触发内部 input 事件 让父组件可以v-model绑定
},
},
mounted() {
for (let key in this.$refs.refInput) {
if (typeof this.$refs.refInput[key] == "function") {
this[key] = this.$refs.refInput[key];
}
}
},
};
</script>
使用方法
javascript"> <inputUi v-model="inputValue" @input="getInfo" ref="refInput">
<template #prepend>Http://</template>
</inputUi>