我如何:
getMyComponent(selectedMyComponentID).complexOperation()
对我来说,这听起来像是一件琐碎而有用的事情,例如从下拉菜单中。
假设我正在做某种类型的编辑器(想想待办事项列表之类的东西)。 GUI具有“选定”元素的概念。 (在我们的实际情况下,它是当前可见的bootstrap nav-tab),我想要具有菜单项的下拉菜单,这些菜单项对所选元素执行不同的操作。
假设我具有“选定”组件的ID,那么对MyComponent的引用就很难了。该MyComponent具有与ID对应的complexOperation()
方法。
也许是因为我没有采用这种“ Vue方式”。
我看到了完成complexOperationOnSelectedMyComponent()
的这些方法:
complexOperation()
从MyComponent重构到新的MyData中,因此数据上的业务逻辑将由App.vue和MyComponent.vue使用。现在,父母正在更改数据,因此正在更改道具-听起来有些虚幻。但这会导致大量样板,因为每个组件中的每个操作现在都有两个版本。我不喜欢样板和重复... 我想念什么吗?这不是很标准的东西吗?
为简单起见,我们将说有一个模板:
<template>
<div id="app">
<div v-for="elem in mydata" :key="elem.id" @click="setSelected(elem)">
<MyComponent :value="elem"/>
</div>
<button @click="complexOperationOnSelectedComponent">
Complex operation on Selected Component
</button>
</div>
</template>
以及最初选择第一个数据的数据结构:
data() {
return {
mydata: [
{ id: 0, foo: "bar", selected: true },
{ id: 1, foo: "baz", selected: false },
{ id: 2, foo: "world", selected: false }
]
};
}
(完整codesandbox)
因此,有一个“对选定组件的复杂操作”按钮。但是我应该在complexOperationOnSelectedComponent
方法中放什么呢?
上面的codeandbox在每个MyComponent内部也具有等效的按钮。他们只是在MyComponent定义中调用complexOperation()
方法。
我在想按钮是恰好位于组件内部还是外部都是次要的细节。获取对所选ID的MyComponent的引用,然后在菜单项的selectedComponent.complexOperation()
处理程序中调用@click
。
在我们的实际情况中,用户通过单击导航栏(而不是MyComponent实例)来选择“组件”,因此我们拥有的是id(mydata[n].id
或0、1或2以上)。
我可以做的是将ref="components"
放在<MyComponents>
定义中。由于它处于v-for
循环中,因此this.$refs.components
将是MyComponents
的数组。找到具有正确ID的ID并使用它。
因为不能保证this.$refs.components
中的顺序,所以每次都必须在数组中搜索selectedMyComponentID,但是嘿...
这真的是最好的解决方案吗?
答案 0 :(得分:0)
如果您需要直接访问DOM来获取未连接/未控制到任何Vue实例属性的元素,则通常需要使用$ refs。 您可以存储在数据中选择了哪个元素,然后定位到该特定元素。
将您的方法放入父母还是孩子?这取决于您是否需要其他地方的逻辑?在这种情况下,我认为这对于孩子是有意义的,因为您也希望能够在其中执行操作。
Use an "event bus" Vue instance and $emit events from parent to child. Seems overkill.
道具从父母到孩子。事件从子级向父级发出。 Vuex和事件总线在较大的应用程序中确实很有帮助,但在这种情况下并不需要。但是,您应该发出要对道具进行的更改,而不要像现在在MyComponent中那样直接对其进行编辑。
我稍微重构了您的代码,我想重复一遍,直接修改props的值是不好的做法:https://codesandbox.io/s/button-onclick-on-selected-child-lf37c?fontsize=14
<template>
<div id="app">
<div v-for="elem in mydata" :key="elem.id" @click="selectedElem = mydata[elem.id]">
<MyComponent :value="elem" :reverse="elem.reverse"/>
</div>
<button @click="reverseSelectedFoo">Reverse Selected Foo</button>
</div>
</template>
<script>
import MyComponent from "./components/MyComponent";
export default {
name: "App",
data() {
// Ideally this data is read from an API somewhere
return {
mydata: [
{ id: 0, foo: "bar", reverse: false },
{ id: 1, foo: "baz", reverse: false },
{ id: 2, foo: "world", reverse: false }
],
selectedElem: null
};
},
methods: {
reverseSelectedFoo() {
this.selectedElem.reverse = !this.selectedElem.reverse;
}
},
components: {
MyComponent
}
};
</script>