我需要将数据从子组件传递到父组件(嵌套(,我知道我们可以用emit
或store
来实现这一点,但我想知道,还有其他方法可以更好地实现这一目标吗?
我不想仅仅因为我的父组件是6级以上就使用emit
。
Store不需要是vuex
或pinia
。它可以是一个外部reactive()
,在使用它的所有组件中导入,而不管它们之间的关系如何。
把它想象成一个data: () => ({})
对象,但没有组件。这里有一个例子,我正在创建一个简单的反应"存储">,并将其注入App和Child(6级深度(。
const { createApp, reactive, defineComponent } = Vue;
const store = reactive({
foo: 'bar'
})
const app = createApp({
setup: () => ({ store })
});
app.component('parent', defineComponent({
template: '<div class="parent">Parent<br><slot></slot></div>'
}));
app.component('child', defineComponent({
setup: () => ({ store }),
template: '<input v-model="store.foo">'
}));
app.mount('#app')
.parent .parent {
padding-left: 1rem;
}
input {
margin-left: 1rem;
}
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="app">
<parent>
<parent>
<parent>
<parent>
<parent>
<child />
</parent>
</parent>
</parent>
</parent>
</parent>
<pre v-text="store" />
</div>
同样的事情,在Vue2:中
const store = Vue.observable({
foo: 'bar'
})
Vue.component('parent', {
template: '<div class="parent">Parent<br><slot /></div>'
});
Vue.component('child', {
computed: {
store: () => store
},
template: '<input v-model="store.foo">'
});
new Vue({
computed: {
store: () => store
}
}).$mount('#app')
.parent .parent {
padding-left: 1rem;
}
input {
margin-left: 1rem;
}
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
<div id="app">
<parent>
<parent>
<parent>
<parent>
<parent>
<child />
</parent>
</parent>
</parent>
</parent>
</parent>
<pre v-text="store" />
</div>
在一个真正的应用程序中;存储";在文件中定义,并在使用该文件的任何组件中导入。(例如:
import { reactive } from 'vue'
export const myStore = reactive({
//...stuff
})
anywhere else:
import { myStore } from './path/to/store'
注意:如果您使用的是Vue2,您可以从@vue/composition-api
插件导入reactive
,也可以使用Vue.observable()
。它提供了相同的功能。
即使上述方法有效,您使用得越多,使用pinia
或vuex
的实际好处就越多,因为它们与vue devtools集成会带来巨大好处。让您能够检查、回滚或回放对反应状态的更改。更不用说,您还可以在商店中定义操作,这样就不必将它们分散在多个组件上,当您想从两个或多个不同的组件执行相同的操作时,这一点尤其有用。
另一个选项是使用专门为绕过父/子链而开发的提供/注入。当您希望专门为当前零部件的子体提供,但不为其同级零部件的后代提供时,它非常有用。例如:
item-1
component
component
child-1
item-2
component
component
child-2
child-3
在上述情况下,如果您希望child-2
和child-3
继承/更新item-2
,但不影响item-1
,那么您将在item-2
中使用provide
,在child-2
和child-3
中使用inject
。
我个人还没有使用过注入/提供,因为我发现与外部商店合作非常强大。即使在理论上,我也有这样的情况。我使用一个单独的商店,在那里我可以唯一地识别祖先。孙子女使用该标识符来更新存储中相应的祖先。
事实上,我使用emit
的唯一地方是在不可知组件中,它可以有任何父级,接受一些输入,执行一些操作,然后更新它们的父级(例如:上下文(。一个很好的例子是通用表单组件,它们不必知道任何关于父表单的信息。
另一个这样的例子是agostic列表呈现器,它同样不在乎它们列出了什么。他们";发射";对父组件的单击操作,它知道单击的实际含义。
您可以为此目的使用eventBus。这是一个工作演示。