本次对
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
只能获取属性,所以结合上面$attrs
jiu可以完整的实现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>