Vue 3 - 如何使模板可与 Composition API 重用?
Vue 3 - how to make templates reusable with the Composition API?
我最近刚刚将我的项目从 Vue 2 迁移到 Vue 3,目前我正在尝试支持 Vue 的新 Composition API。虽然我了解了可组合项等的概念,但有一个使用选项 API 的用例,我还无法弄清楚如何使用新的 API。
我真正喜欢 Options API 的 mixin 的地方在于,它们可以让 met 在基本模板上施加额外的行为,以便在不同的继承组件中重用它们,尽管我也看到了它们带来的问题。 (注意:我最近才发现 extends
应该用于此。)现在有了 Composition API,我不确定如何解决这个用例。举个例子:
BaseComponent.vue
<template>
<div class="base-template">
<span @click="baseBar">{{ baseFoo }}</span>
</div>
</template>
<script>
export default {
name: BaseComponent,
data() {
return {
baseFoo: "baseFoo"
};
},
methods: {
baseBar() {
alert("baseBar");
}
}
}
</script>
SubComponentA.vue
<script>
import BaseComponent from './BaseComponent.vue';
export default {
name: SubComponentA,
mixins: [BaseComponent],
data() {
return {
baseFoo: "subFooA"
};
},
methods: {
baseBar() {
alert("subBarA");
}
}
}
</script>
SubComponentB.vue
<script>
import BaseComponent from './BaseComponent.vue';
export default {
name: SubComponentB,
mixins: [BaseComponent],
data() {
return {
baseFoo: "subFooB"
};
},
methods: {
baseBar() {
alert("subBarB");
}
}
}
</script>
这样我就可以独立使用 SubComponentA
和 SubComponentB
,它们都继承自同一个基本模板。所以基本上,我可以在不同的组件中重复使用相同的模板,同时还可以处理基础数据。
现在我不知道如何将此行为转化为合成 API。虽然使用 Composables 将逻辑从 BaseComponent
导入 SubComponentA
是目前我能得到的最接近的方法,但似乎没有办法用它们导出模板结构,更不用说它们也被绑定到导出的逻辑了.我唯一能想到的就是求助于渲染函数,但重建我的模板将是一个主要的时间消耗。
那么这是怎么做到的呢?这甚至是 Composition API 的明智方法,还是我什至错过了重新思考整个概念的一些步骤?
我最终使用的解决方案是将组件的状态存储到它自己的模块中,如下所示:
BaseState.js
import { ref } from 'vue';
export const baseFoo = ref("baseFoo");
export const baseBar = () => alert("BaseBar");
export function setBaseFoo(newBaseFoo) {
baseFoo.value = newBaseFoo;
}
export function setBaseBar(newBaseBar) {
baseBar = newBaseBar;
}
BaseComponent.vue
<template>
<div class="base-template">
<span @click="baseBar">{{ baseFoo }}</span>
</div>
</template>
<script setup>
import { baseFoo, baseBar } from `./BaseState.js`;
</script>
SubComponent.vue
<template>
<BaseComponent />
</template>
<script setup>
import { ref } from 'vue';
import { setBaseFoo, setBaseBar } from `./BaseState.js`;
import BaseComponent from './BaseComponent.vue';
setBaseFoo("subFoo");
setBaseBar(() => alert("subBar"));
</script>
不确定这是预期的还是最优雅的解决方案,但对我来说效果很好。
或者您可以使用 defineExpose()
通过模板引用直接访问基本组件的状态逻辑,尽管这个解决方案对我来说似乎不太优雅,因为子组件将无法访问 onMounted()
.
BaseComponent.vue
<template>
<div class="base-template">
<span @click="baseBar">{{ baseFoo }}</span>
</div>
</template>
<script setup>
import { ref } from 'vue';
const baseFoo = ref("baseFoo");
const baseBar = () => alert("BaseBar");
defineExpose({baseFoo, baseBar});
</script>
SubComponent.vue
<template>
<BaseComponent ref="base" />
</template>
<script setup>
import { ref, onMounted } from 'vue';
import BaseComponent from './BaseComponent.vue';
const base = ref(null);
onMounted(() => {
const { baseFoo, baseBar } = base.value;
...
});
</script>
我最近刚刚将我的项目从 Vue 2 迁移到 Vue 3,目前我正在尝试支持 Vue 的新 Composition API。虽然我了解了可组合项等的概念,但有一个使用选项 API 的用例,我还无法弄清楚如何使用新的 API。
我真正喜欢 Options API 的 mixin 的地方在于,它们可以让 met 在基本模板上施加额外的行为,以便在不同的继承组件中重用它们,尽管我也看到了它们带来的问题。 (注意:我最近才发现 extends
应该用于此。)现在有了 Composition API,我不确定如何解决这个用例。举个例子:
BaseComponent.vue
<template>
<div class="base-template">
<span @click="baseBar">{{ baseFoo }}</span>
</div>
</template>
<script>
export default {
name: BaseComponent,
data() {
return {
baseFoo: "baseFoo"
};
},
methods: {
baseBar() {
alert("baseBar");
}
}
}
</script>
SubComponentA.vue
<script>
import BaseComponent from './BaseComponent.vue';
export default {
name: SubComponentA,
mixins: [BaseComponent],
data() {
return {
baseFoo: "subFooA"
};
},
methods: {
baseBar() {
alert("subBarA");
}
}
}
</script>
SubComponentB.vue
<script>
import BaseComponent from './BaseComponent.vue';
export default {
name: SubComponentB,
mixins: [BaseComponent],
data() {
return {
baseFoo: "subFooB"
};
},
methods: {
baseBar() {
alert("subBarB");
}
}
}
</script>
这样我就可以独立使用 SubComponentA
和 SubComponentB
,它们都继承自同一个基本模板。所以基本上,我可以在不同的组件中重复使用相同的模板,同时还可以处理基础数据。
现在我不知道如何将此行为转化为合成 API。虽然使用 Composables 将逻辑从 BaseComponent
导入 SubComponentA
是目前我能得到的最接近的方法,但似乎没有办法用它们导出模板结构,更不用说它们也被绑定到导出的逻辑了.我唯一能想到的就是求助于渲染函数,但重建我的模板将是一个主要的时间消耗。
那么这是怎么做到的呢?这甚至是 Composition API 的明智方法,还是我什至错过了重新思考整个概念的一些步骤?
我最终使用的解决方案是将组件的状态存储到它自己的模块中,如下所示:
BaseState.js
import { ref } from 'vue';
export const baseFoo = ref("baseFoo");
export const baseBar = () => alert("BaseBar");
export function setBaseFoo(newBaseFoo) {
baseFoo.value = newBaseFoo;
}
export function setBaseBar(newBaseBar) {
baseBar = newBaseBar;
}
BaseComponent.vue
<template>
<div class="base-template">
<span @click="baseBar">{{ baseFoo }}</span>
</div>
</template>
<script setup>
import { baseFoo, baseBar } from `./BaseState.js`;
</script>
SubComponent.vue
<template>
<BaseComponent />
</template>
<script setup>
import { ref } from 'vue';
import { setBaseFoo, setBaseBar } from `./BaseState.js`;
import BaseComponent from './BaseComponent.vue';
setBaseFoo("subFoo");
setBaseBar(() => alert("subBar"));
</script>
不确定这是预期的还是最优雅的解决方案,但对我来说效果很好。
或者您可以使用 defineExpose()
通过模板引用直接访问基本组件的状态逻辑,尽管这个解决方案对我来说似乎不太优雅,因为子组件将无法访问 onMounted()
.
BaseComponent.vue
<template>
<div class="base-template">
<span @click="baseBar">{{ baseFoo }}</span>
</div>
</template>
<script setup>
import { ref } from 'vue';
const baseFoo = ref("baseFoo");
const baseBar = () => alert("BaseBar");
defineExpose({baseFoo, baseBar});
</script>
SubComponent.vue
<template>
<BaseComponent ref="base" />
</template>
<script setup>
import { ref, onMounted } from 'vue';
import BaseComponent from './BaseComponent.vue';
const base = ref(null);
onMounted(() => {
const { baseFoo, baseBar } = base.value;
...
});
</script>