本次对
el-input进行简单封装进行演示
- 封装很简单,就给激活样式的边框(主要是功能)
本次封装主要使用到vue自带的几个对象
- $attrs:获取绑定在组件上的所有属性
- $listeners: 获取绑定在组件上的所有函数方法
- $slots: 获取应用在组件内的所有插槽
1、属性传递
element 的input组件有很多属性,
- 想要实现在封装好后的组件上使用
el-input组件的属性,会直接传递到el-input组件上,包括v-model。- 在组件中,可以使用
this.$attrs获取所有绑定在组件上的属性(不包括方法)- 这样,我们就可以在封装的组件内,使用
v-bind="$attrs",直接把属性传递到内部组件上。- 在下列案例中,由于
v-model是:value 和 @input两个组合的语法糖,$attrs只能获取属性,所以只能传递:value属性
1.1、父组件
<template><div class="wrapper"> <my-input v-model="val"></my-input></div>
</template><script>import MyInput from '@/components/MyInput'export default {components: {MyInput,},data() {return {val: '111',}},methods: {inputChange(val){console.log(val);}}}
</script><style lang="scss" scoped>.wrapper {padding: 10vh;}
</style>
1.2、子组件
<template><el-input v-bind="$attrs"></el-input>
</template>
<script>export default {created() {console.log("attrs:",this.$attrs);}}
</script>
<style lang="scss" scoped>
::v-deep {.el-input__inner:focus {border-color: red;
}
}</style>
1.3、效果
- 这时候给输入框输入值是无效的,因为目前只能把
value属性绑定到el-input上,并没有把input函数绑定上去,所以不能修改父组件传过来的value的值。

2、方法传递
element的组件,也有很多方法,比如:change等函数
- 想要实现在封装好后的组件上使用
el-input组件的方法,会直接传递到el-input组件上。- 在组件中,可以使用
this.$listeners获取所有绑定在组件上的属性(不包括属性)- 这样,我们就可以在封装的组件内,使用
v-on="$listeners",直接把方法传递到内部组件上。- 在下列案例中,由于
v-model是:value 和 @input两个组合的语法糖,$listeners只能获取属性,所以结合上面$attrsjiu可以完整的实现v-model的效果了
2.1、父组件
<template><div class="wrapper"> <my-input v-model="val" @change="inputChange"></my-input></div>
</template><script>import MyInput from '@/components/MyInput'export default {components: {MyInput,},data() {return {val: '111',}},methods: {inputChange(val){console.log("inputChange:", val);}}}
</script>
2.2、子组件
<template><el-input v-bind="$attrs" v-on="$listeners"></el-input>
</template>
<script>export default {created() {console.log("attrs:",this.$attrs);console.log("listeners:",this.$listeners);}}
</script>
<style lang="scss" scoped>
::v-deep {.el-input__inner:focus {border-color: red;}
}</style>
2.3、效果
这时候搭配
$attrs就可以实现v-model的完整效果了,以及@change函数也会传递过去

3、插槽传递
element的组件,也包括了很多的插槽
- 想要给封装好后的组件,使用的插槽,传递到
el-input中- 在组件中,可以使用
this.$attrs获取所有绑定在组件上的插槽- 这样,我们就可以在封装的组件内,使用
v-for="(val, key) in $slots",所有插槽,遍历放到组件中,当作组件的插槽- 注意插槽传参也要处理(我这里没处理)
3.1、父组件
<template><div class="wrapper"> <my-input v-model="val" @change="inputChange"><template slot="prepend">Http://</template><el-button slot="append" icon="el-icon-search"></el-button></my-input></div>
</template><script>import MyInput from '@/components/MyInput'export default {components: {MyInput,},data() {return {val: '111',}},methods: {inputChange(val){console.log("inputChange:", val);}}}
</script><style lang="scss" scoped>.wrapper {padding: 10vh;}
</style>
3.2、子组件
<template><el-input v-bind="$attrs" v-on="$listeners"><template v-for="(val, key) in $slots"><slot :name="key"></slot></template></el-input>
</template>
<script>export default {created() {console.log("attrs:",this.$attrs);console.log("listeners:",this.$listeners);console.log("slots",this.$slots);}}
</script>
<style lang="scss" scoped>
::v-deep {.el-input__inner:focus {border-color: red;}
}</style>
3.3、效果

4、ref伪传递(适用于vue3)
- 为什么说伪传递呢,因为在vue中,根本就拿不到外层组件的
ref属性,所以只能另换思路- 你要用ref,无非就是想调用组件里面的函数。那我封装的组件里面,可以把被封装的组件的函数,直接提取出来,当作我封装组件的函数即可实现
- 适用于Vue3,vue2会卡死
4.1、父组件
<template><div class="wrapper"> <my-input ref="muInput" v-model="val" @change="inputChange"><template slot="prepend">Http://</template><el-button slot="append" icon="el-icon-search"></el-button></my-input></div>
</template><script>import MyInput from '@/components/MyInput'export default {components: {MyInput,},data() {return {val: '111',}},mounted() {this.$refs.muInput.focus()},methods: {inputChange(val){console.log("inputChange:", val);}}}
</script><style lang="scss" scoped>.wrapper {padding: 10vh;}
</style>
4.2、子组件
<template><el-input ref="input" v-bind="$attrs" v-on="$listeners"><template v-for="(val, key) in $slots" #[key]><slot :name="key"></slot></template></el-input>
</template>
<script>export default {mounted() {console.log("attrs:",this.$attrs);console.log("listeners:",this.$listeners);console.log("slots",this.$slots);for (const [key, value] of Object.entries(this.$refs.input)) {this[key] = value}}}
</script>
<style lang="scss" scoped>
::v-deep {.el-input__inner:focus {border-color: red;}
}</style>