目录前言✨一、对于第三方组件的属性props、事件events二、对于第三方组件的插槽slots三、对于第三方组件的方法methods前言✨ 对于第三方组件,如何在保持第三方组件原有
对于第三方组件,如何在保持第三方组件原有功能(属性props、事件events、插槽slots、方法methods)的基础上,优雅地进行功能的扩展了?
以Element Plus的el-input为例:
很有可能你以前是这样玩的,封装一个MyInput组件,把要使用的属性props、事件events和插槽slots、方法methods根据自己的需要再写一遍:
// MyInput.Vue
<template>
<div class="my-input">
<el-input v-model="inputVal" :clearable="clearable" @clear="clear">
<template #prefix>
<slot name="prefix"></slot>
</template>
<template #suffix>
<slot name="suffix"></slot>
</template>
</el-input>
</div>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
modelValue: {
type: String,
default: ''
},
clearable: {
type: Boolean,
default: false
}
})
const emits = defineEmits(['update:modelValue', 'clear'])
const inputVal = computed({
get: () => props.modelValue,
set: (val) => {
emits('update:modelValue', val)
}
})
const clear = () => {
emits('clear')
}
</script>
可过一段时间后,需求变更,又要在MyInput组件上添加el-input组件的其它功能,可el-input组件总共有20个多属性,5个事件,4个插槽,那该怎么办呢,难道一个个传进去,这样不仅繁琐而且可读性差。
在Vue2中,我们可以这样处理,点击此处查看 封装Vue第三方组件
此文诣在帮助大家做一个知识的迁移,探究如何使用vue3 Compositionapi优雅地封装第三方组件~
在Vue2中
而在Vue3中
//MyInput.vue
<template>
<div class="my-input">
<el-input v-bind="attrs"></el-input>
</div>
</template>
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>
当然,这样还不够。光这样写,我们绑定的属性(包括 class 和 style)同时会在根元素(上面的例子是class="my-input"的Dom节点)上起作用。要阻止这个默认行为,我们需要设置inheritAttrs为false。
下面我们来看看Vue3文档对inheritAttrs的解释
默认情况下父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会“回退”且作为普通的 html attribute 应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过实例 property $attrs 可以让这些 attribute 生效,且可以通过 v-bind 显性的绑定到非根元素上。
于是,我们对于第三方组件的属性props、事件events处理,可以写成如下代码:
// MyInput.vue
<template>
<div class="my-input">
<el-input v-bind="attrs"></el-input>
</div>
</template>
<script>
export default {
name: 'MyInput',
inheritAttrs: false
}
</script>
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>
Vue3中
基于以上几点,如果我们对于第三方组件的封装没有增加额外的插槽,且第三方组件的插槽处于同一个dom节点之中,我们也有一种取巧的封装方式?, 通过遍历$slots拿到插槽的name,动态添加子组件的插槽:
//MyInput.vue
<template>
<div class="my-input">
<el-input v-bind="attrs">
<template v-for="k in Object.keys(slots)" #[k] :key="k">
<slot :name="k"></slot>
</template>
</el-input>
</div>
</template>
<script>
export default {
name: 'MyInput',
inheritAttrs: false
}
</script>
<script setup>
import { useAttrs, useSlots } from 'vue'
const attrs = useAttrs()
const slots = useSlots()
</script>
如果不满足以上条件的话,咱还得老老实实在子组件中手动添加需要的第三方组件的插槽~
对于第三方组件的方法,我们通过ref来实现。首先在MyInput组件中的el-input组件上添加一个ref="elInputRef"属性,然后通过defineExpose把elInputRef暴露出去给父组件调用。
子组件:MyInput.vue
// MyInput.vue
<template>
<div class="my-input">
<el-input v-bind="attrs" ref="elInputRef">
<template v-for="k in Object.keys(slots)" #[k] :key="k">
<slot :name="k"></slot>
</template>
</el-input>
</div>
</template>
<script>
export default {
name: 'MyInput',
inheritAttrs: false
}
</script>
<script setup>
import { useAttrs, useSlots } from 'vue'
const attrs = useAttrs()
const slots = useSlots()
const elInputRef = ref(null)
defineExpose({
elInputRef // <script setup>的组件里的属性默认是关闭的,需通过defineExpose暴露出去才能被调用
})
</script>
父页面:Index.vue的调用代码如下:
// Index.vue
<template>
<my-input v-model='input' ref="myInput">
<template #prefix>姓名</template>
</my-input>
</template>
<script setup>
import MyInput from './components/MyInput.vue'
import { ref, onMounted } from 'vue'
const input = ref('')
const myInput = ref(null) // 组件实例
onMounted(()=> {
myInput.value.elInputRef.focus() // 初始化时调用elInputRef实例的focus方法
})
</script>
以上就是Vue3 Composition API优雅封装第三方组件实例的详细内容,更多关于Vue3 Composition API封装第三方组件的资料请关注编程网其它相关文章!
--结束END--
本文标题: Vue3 Composition API优雅封装第三方组件实例
本文链接: https://www.lsjlt.com/news/154120.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-01-12
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0