【发布时间】:2021-11-24 16:16:21
【问题描述】:
问题
如何在运行时修改开槽元素的prop?
我是否使用了错误的生命周期方法?
是否也需要更改slottedElement.type.props?
示例
A.vue
<template>
<B key="tag-outer">
<B key="tag-inner" />
</B>
</template>
<script>
import B from "./B.vue";
export default {
name: "A",
components: {
B,
},
};
</script>
B.vue
<template>
<p>{{ mode }}</p>
<slot />
</template>
<script>
export default {
name: "B",
props: {
mode: {
type: String,
default: "outer",
},
key: String,
},
computed: {
hasSlot() {
return !!this.$slots.default;
},
},
beforeMount() {
this.modifySlottedElements();
},
beforeUpdate() {
this.modifySlottedElements();
},
methods: {
modifySlottedElements() {
if (this.hasSlot) {
this.$slots.default().forEach((slottedElement) => {
if (slottedElement.type.name === "B") {
// prevent concurrency issues
const copiedSlottedElement = JSON.parse(JSON.stringify(slottedElement));
console.log("before");
console.log(copiedSlottedElement);
slottedElement.props.mode = "inner";
console.log("modified");
console.log(slottedElement);
}
});
}
},
},
};
</script>
输出
before
type = Object {name: "B", props: Object, computed: Object, methods: Object, __file: "C:/dev/git/csx-vue/src/demo/test/B.vue", ...}
props = Object {key: "tag-inner"}
...
modified
type = Object {name: "B", props: Object, computed: Object, beforeMount: Function, beforeUpdate: Function, ...}
props = Object {key: "tag-inner", mode: "inner"}
...
渲染
<p>outer</p>
<p>outer</p>
谢谢
解决方法
使用反转逻辑(检查父级)
<template>
<p>{{ modeProxy }}</p>
<slot />
</template>
<script>
export default {
name: "B",
props: {
mode: {
type: String,
default: "outer",
},
key: String,
},
data() {
return {
modeProxy: this.mode,
};
},
beforeMount() {
this.markSubMenu();
},
beforeUpdate() {
this.markSubMenu();
},
methods: {
markSubMenu() {
if (this.$parent.$.type.name === "B") {
this.modeProxy = "inner";
}
},
},
};
</script>
【问题讨论】:
-
我认为您必须澄清示例中的用例才能提供一个好的解决方案。截至目前,您似乎想根据插槽组件的类型修改插槽组件的道具。但是这个例子表明你只是想让它知道它在一个“内部”上下文中。为什么不直接通过道具传递这些信息?
-
上下文:导航菜单子菜单需要一些差异,手动设置道具效果很好。作为一项便利功能,如果您可以简单地堆叠这些元素并且条目本身负责定义其级别/深度,那就太好了。
标签: vue.js vue-component vuejs3