Vue3组合式API中组件扩展与重写的最优方案咨询
Vue组件复用+重写的最优简洁方案
最直接贴合你需求的实现方式是用Vue原生的extends组件继承,既能完整复用通用组件的模板和大部分逻辑,又能轻松重写指定的ref、函数,完全不需要额外复杂封装。
具体实现步骤
1. 通用组件(common.vue)保持原样即可
不需要做任何大改动,正常定义你的模板和逻辑:
<template> <div> <div>Title</div> <div>{{ refToOverride.value }}</div> </div> </template> <script> import { defineComponent, ref} from 'vue'; export default defineComponent({ name: "common", setup() { const refToOverride= ref("object to override"); function functionToOverride() { return "Override me!" } return { refToOverride, functionToOverride, }; }, }); </script>
2. 编写继承组件(比如叫Specific.vue)
通过extends继承通用组件,在自己的setup里重写需要修改的内容就行——Vue会自动合并逻辑,重写的部分会覆盖父组件的对应内容:
<!-- 这里不需要手动写<common/>,直接复用父组件的模板 --> <template></template> <script> import { defineComponent, ref } from 'vue'; import Common from './common.vue' export default defineComponent({ extends: Common, // 关键:继承通用组件 setup() { // 重写ref const refToOverride = ref("I override a ref"); // 重写函数 function functionToOverride() { return "I override a function!" } // 如果还需要复用父组件的其他逻辑,可以调用父组件的setup获取 // const parentLogic = Common.setup(); // 比如用parentLogic里的其他方法 return { refToOverride, functionToOverride }; }, }); </script>
为啥你原来的写法行不通?
你直接修改导入的common组件对象的属性是错的:
common是组件的构造函数,不是实例,直接改会影响所有用到这个组件的地方,相当于全局污染- 每个组件实例的ref和函数都是独立的,构造函数上根本不存在
refToOverride这类实例属性
备选方案:插槽+组合式函数(适合需要改模板的场景)
如果你的需求不止是重写逻辑,还需要替换部分模板内容,可以结合插槽和组合式函数:
- 先把通用逻辑抽成组合式函数:
// useCommonLogic.js import { ref } from 'vue'; export function useCommonLogic() { const refToOverride = ref("object to override"); function functionToOverride() { return "Override me!" } return { refToOverride, functionToOverride }; }
- 通用组件改用插槽+组合式函数:
<template> <div> <div>Title</div> <!-- 用插槽预留可替换的内容 --> <slot name="content"> <div>{{ refToOverride.value }}</div> </slot> </div> </template> <script> import { defineComponent } from 'vue'; import { useCommonLogic } from './useCommonLogic'; export default defineComponent({ name: "common", setup() { return useCommonLogic(); }, }); </script>
- 业务组件使用时:
<template> <common> <template #content> <div>{{ refToOverride.value }}</div> </template> </common> </template> <script> import { defineComponent, ref } from 'vue'; import Common from './common.vue' export default defineComponent({ components: { Common }, setup() { const refToOverride = ref("I override a ref"); function functionToOverride() { return "I override a function!" } return { refToOverride, functionToOverride }; }, }); </script>
不过如果只是单纯重写逻辑和ref,extends方案明显更简洁直接。
内容的提问来源于stack exchange,提问作者JulienRobitaille
相关产品推荐
相关产品推荐

