在我们的业务里,我们通常会二次封装一些高频业务组件。对于封装组件有一个大原则就是我们应该尽量保持原有组件的接口,除了我们需要封装的功能外,我们不应该改变原有组件的接口,即保持原有组件提供的接口如props,events,slots等不变。这里我们对element plus 的input组件做二次封装为例,Vue版本3.3.4 element-plus版本2.3.8
组件二次封装需要解决一下问题
这里我们对element plus的input组件简单封住一下,就是作为演示用的 MyInput.vue
vue<!-- --> <template> <div class="myinput"> <span class="label">{{label}}</span> <!-- 如果不希望过滤掉某些属性 可以直接使用 $attrs --> <el-input v-bind="filteredAttrs" :clearable="clearable" ref="input"> <template #[slotName]="slotProps" v-for="(slot, slotName) in $slots" > <slot :name="slotName" v-bind="slotProps"></slot> </template> </el-input> </div> </template> <script lang="ts" setup> import {useAttrs,computed,ref } from 'vue' import { ElInput } from 'element-plus' defineOptions({ name: 'MyInput' }) defineProps({ label: String, clearable: { type: Boolean, default: true, }, }); const input = ref(); defineExpose({ input }); const attrs = useAttrs() // 如果我们不希望透传某些属性比如class, 我们可以通过useAttrs来实现 const filteredAttrs = computed(() => { return { ...attrs, class: undefined }; }); </script> <style lang="scss" scoped> .myinput{ .label{ color: #333; } } </style>
上面使用defineExpose + ref的组合来获取源组件上的实例方法
在其他组件里面使用MyInput
vue<template> <div class="about"> <MyInput v-model="inputvalue" label="myinput" @input="inputHandle" ref="myInput"> <template #prepend> <el-select v-model="select" placeholder="请选择" style="width: 115px"> <el-option label="HTTPS" value="1" /> <el-option label="HTTP" value="2" /> </el-select> </template> <template #append> <el-button :icon="Search" /> </template> </MyInput> {{ inputvalue }} </div> </template> <script lang="ts" setup> import { ref,onMounted } from 'vue' import { ElButton, ElSelect, ElOption } from 'element-plus' import { Search } from '@element-plus/icons-vue' import MyInput from '../components/myinputs/index.vue' const inputvalue = ref('') const select = ref('1') const myInput = ref() const inputHandle = (e: InputEvent) => { console.log(e) } onMounted(() => { console.log(myInput.value.input); myInput.value.input.focus() }) </script> <style> @media (min-width: 1024px) { .about { min-height: 100vh; display: flex; align-items: center; } } </style>
注意事项:
ref定义名称时,不要和组件名称相似,否则会报错的


本文作者:千寻
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!