我们在 Vue 中有一个组件,它是一个框架,缩放到窗口大小,其中包含(在 <slot>
中)一个元素(通常是 <img>
或 <canvas>
)它会缩放以适合框架并启用对该元素的平移和缩放。
组件需要在元素更改时做出反应。我们可以看到做到这一点的唯一方法是让父级在发生这种情况时刺激组件,但是如果组件可以自动检测 <slot>
元素何时发生变化并做出相应的反应,那就更好了。有没有办法做到这一点?
原文由 Euan Smith 发布,翻译遵循 CC BY-SA 4.0 许可协议
我们在 Vue 中有一个组件,它是一个框架,缩放到窗口大小,其中包含(在 <slot>
中)一个元素(通常是 <img>
或 <canvas>
)它会缩放以适合框架并启用对该元素的平移和缩放。
组件需要在元素更改时做出反应。我们可以看到做到这一点的唯一方法是让父级在发生这种情况时刺激组件,但是如果组件可以自动检测 <slot>
元素何时发生变化并做出相应的反应,那就更好了。有没有办法做到这一点?
原文由 Euan Smith 发布,翻译遵循 CC BY-SA 4.0 许可协议
据我了解 Vue 2+,当插槽内容发生变化时,应该重新渲染一个组件。在我的例子中,我有一个 error-message
组件应该隐藏,直到它有一些插槽内容要显示。起初,我将此方法附加到 v-if
在我组件的根元素上(一个 computed
属性不起作用,Vue 似乎没有对 this.$slots
)。
checkForSlotContent() {
let checkForContent = (hasContent, node) => {
return hasContent || node.tag || (node.text && node.text.trim());
}
return this.$slots.default && this.$slots.default.reduce(checkForContent, false);
},
只要 99% 的更改发生在插槽中,包括任何 DOM 元素的添加或删除,这都适用。唯一的边缘情况是这样的用法:
<error-message> {{someErrorStringVariable}} </error-message>
这里只更新了一个文本节点,出于我仍不清楚的原因,我的方法不会触发。我通过连接到 beforeUpdate()
和 created()
来解决这个问题,让我得到一个完整的解决方案:
<script>
export default {
data() {
return {
hasSlotContent: false,
}
},
methods: {
checkForSlotContent() {
let checkForContent = (hasContent, node) => {
return hasContent || node.tag || (node.text && node.text.trim());
}
return this.$slots.default && this.$slots.default.reduce(checkForContent, false);
},
},
beforeUpdate() {
this.hasSlotContent = this.checkForSlotContent();
},
created() {
this.hasSlotContent = this.checkForSlotContent();
}
};
</script>
原文由 Mathew Sonke 发布,翻译遵循 CC BY-SA 4.0 许可协议
10 回答11.1k 阅读
6 回答3k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
2 回答4.7k 阅读✓ 已解决
4 回答4.3k 阅读✓ 已解决
据我所知,Vue 没有提供这样做的方法。但是,这里有两种方法值得考虑。
观察插槽的 DOM 变化
使用 MutationObserver 检测
<slot>
中的 DOM 何时发生变化。这不需要组件之间的通信。只需在组件的mounted
回调期间设置观察者。这是一个片段,展示了这种方法的实际应用:
使用发射
如果 Vue 组件负责更改插槽,那么最好在更改发生时 发出一个事件。这允许任何其他组件在需要时响应发出的事件。
为此,请使用一个空的 Vue 实例作为全局事件总线。任何组件都可以发出/监听事件总线上的事件。在您的情况下,父组件可以发出“更新内容”事件,子组件可以对此做出反应。
这是一个简单的例子: