目录
测试页面代码
这里主要记录如何封装element的el-input
并且封装后具有el-input原本的属性 事件 插槽
下面为测试页面即组件调用
<script>
import CustomInput from '@/components/CustomInput.vue';
export default {
name: 'TestPage',
components: { CustomInput },
data() {
return {
testInput: 'Hello World'
}
},
};
</script>
<template>
<div style='margin-left: 50px;width: 600px'>
<!-- 测试代码-->
<CustomInput v-model='testInput' placeholder='Hello World'>
<template slot='append'>
<el-button>搜索</el-button>
</template>
</CustomInput>
</div>
</template>
<style scoped lang='scss'>
</style>
组件的封装代码
先看看实际效果和是否生效
在 Vue.js 中,v-bind="$attrs"
、v-on="$listeners"
和 inheritAttrs: false
是与组件的属性 (props) 和事件监听器相关的选项,它们通常用于自定义组件中以确保父组件传递的所有属性和事件能够正确地应用到子组件上。以下是每个选项的详细解释:
v-bind="$attrs"
v-bind="$attrs"
是一个 Vue 指令,用于将父组件传递给子组件的非 prop 属性 (即普通 HTML 属性和自定义属性,但不包括 class 和 style) 绑定到子组件的根 DOM 元素上。- 使用
$attrs
变量可以获得父组件传递下来的所有属性 (除了通过props
定义的属性之外),然后一次性绑定到内部元素上。v-on="$listeners"
v-on="$listeners"
也是一个 Vue 指令,用于添加父组件在子组件上设置的所有事件监听器。$listeners
对象包含了在子组件上侦听的所有事件 (这些事件还没有配置相应的方法或尚未作为 prop 被识别)。使用这个指令可以方便地将所有父组件绑定的事件监听器添加到子组件的根 DOM 元素上。inheritAttrs: false
inheritAttrs: false
是一个组件选项,使得所有的非 prop 属性 (比如class
,style
等) 不会默认绑定到组件的根 DOM 元素上。- 默认情况下,Vue 会将任何不被识别为 prop 的属性自动添加到组件的根元素上。当你不希望建立这种默认行为时(比如你希望手动确定哪些属性应该被添加到哪个元素上),可以设置
inheritAttrs: false
。
此处为了继承原组件的所有插槽
需要依次声明它们
<template>
<el-input
v-bind="$attrs"
v-on="$listeners"
:value="inputValue"
@input="updateValue"
>
<!-- 默认插槽 -->
<slot></slot>
<!-- 具名插槽 -->
<slot name="prepend" slot="prepend"></slot>
<slot name="append" slot="append"></slot>
<slot name="prefix" slot="prefix"></slot>
<slot name="suffix" slot="suffix"></slot>
</el-input>
</template>
<script>
export default {
name: 'CustomInput',
// 使用 inheritAttrs: false 选项,避免 attribute 被自动应用到组件根元素上
inheritAttrs: false,
props: ['value'], // 如果需要处理 value 属性,需要显式声明
computed: {
inputValue: {
get() {
return this.value;
},
set(value) {
this.$emit('update:value', value);
}
}
},
methods: {
updateValue(value) {
this.$emit('input', value); // 当输入时触发 input 事件,并将新值通过事件发送给父组件
}
}
};
</script>
多组件事件处理
下面示例如何处理一个组件中封装了多个子组件并且有相同子组件时,如何处理相同子组件的事件。
组件<CustomInput.vue>实例代码
此组件中有两个<el-button 组件,需要处理两个el-button的click事件
<template>
<el-input
v-bind="$attrs"
v-on="$listeners"
:value="inputValue"
@input="updateValue"
>
<!-- 默认插槽 -->
<slot></slot>
<!-- 具名插槽 -->
<slot name="prepend" slot="prepend"><el-button @click="handleClickA">搜索A</el-button></slot>
<slot name="append" slot="append"><el-button @click="handleClickB">搜索B</el-button></slot>
<slot name="prefix" slot="prefix"></slot>
<slot name="suffix" slot="suffix"></slot>
</el-input>
</template>
<script>
export default {
name: 'CustomInput',
// 使用 inheritAttrs: false 选项,避免 attribute 被自动应用到组件根元素上
inheritAttrs: false,
props: ['value'], // 如果需要处理 value 属性,需要显式声明
computed: {
inputValue: {
get() {
return this.value;
},
set(value) {
this.$emit('update:value', value);
}
}
},
methods: {
updateValue(value) {
this.$emit('input', value); // 当输入时触发 input 事件,并将新值通过事件发送给父组件
},
handleClickA() {
this.$emit('click-a');
},
handleClickB() {
this.$emit('click-b');
}
}
};
</script>
测试页面代码
<script>
import CustomInput from '@/components/CustomInput.vue';
export default {
name: 'TestPage',
components: { CustomInput },
data() {
return {
testInput: 'Hello World'
}
},
methods: {
clickA() {
console.log('click A');
this.testInput = '.........click A';
},
clickB() {
console.log('click B');
this.testInput = '.........click B';
}
}
};
</script>
<template>
<div style='margin-left: 50px;width: 600px'>
<!-- 测试代码-->
<CustomInput v-model='testInput' placeholder='Hello World' @click-a="clickA" @click-b="clickB">
</CustomInput>
</div>
</template>
<style scoped lang='scss'>
</style>
测试运行
成功触发两个组件的事件