将父虚拟机作为prop传递给组件



所以我正在构建一个next应用程序与文档工作(在广义上),它将有一个菜单,我显然会使一个组件。菜单将是对文档本身的许多操作的所在地,例如打开/保存文件,编辑等。

我知道将信息从组件传递给它的父组件(本例中是doc vm)的标准方式是通过消息,但它感觉有点多余,语法(在这种情况下emit处理程序对我来说不太自然)和其他诸如此类的。

出于这个原因,我想知道为什么我不能把父虚拟机作为道具传递给菜单组件?它将包含各种方法,我将能够轻松地通过菜单调用它们。比如:

父(Document.vue):

<template>
<main-menu :document='vm'/>
</template>
<script>
import MainMenu from '~/components/MainMenu.vue'
export default {
data(): {
return {
vm: this,
//...
}
},
methods: {
save() {
//...
}
}
//...
</script>

菜单组件(MainMenu.vue):

<template>
<button @click='document.save()'>Save document</button>
</template>
<script>
export default {
props = ['document']
}
</script>

问题是:这种方法有什么本质上不好的地方吗?(我想如果应用程序架构可能会改变,这可能会有问题,但很难想象我会出于某种原因需要一个没有底层文档的菜单。)

如果你的Menu总是组件的子元素,那么你就不需要传递父元素。它已经保存在一个名为this.$parent.

的Vue变量中。我做了一个小沙箱给你一个例子。

父节点有一个函数,例如:

/// PARENT
export default {
name: "App",
components: {
HelloWorld,
},
methods: {
iExist(add) {
console.log("I am in parent" + add);
},
},
};

那么你可以从this.$parent.iExist('something')的子节点调用它。

因为这。$parent在计算模板时没有定义,我们必须在子元素中创建一个方法,在其父元素上调用(super)相应的函数。

/// CHILD
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<button @click="iExist(', but was called from child')">Click Me</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
methods: {
iExist(add) {
this.$parent.iExist(add);
},
},
};
</script>

问题是:这种方法有什么本质上不好的地方吗?

(我想如果应用程序架构可能会改变,这可能会有问题,但很难想象我会出于某种原因需要一个没有底层文档的菜单。)

是的,这是糟糕的设计。父母可以意识到孩子,孩子不应该意识到父母。子组件可以单独测试,也可以嵌套在没有此方法的包装器组件中。

正如另一个答案所建议的那样,访问父节点的一种方法是使用$parent属性。在Vue中,这部分是从AngularJS 1借鉴来的。因此,即使在当时访问它也被认为是不好的做法。

这通常是通过提供来自父类的回调来实现的,该回调正好做了所需的事情,而不允许访问整个实例并破坏封装。没有必要在Vue中显式定义回调函数,因为这是由Vue模板语法自然提供的:

在父元素中:

<child @save="save()">

儿童:

<button @click="$emit('save')">

如果是深度嵌套的组件,事件可以通过它们传递给父组件。

最新更新