我有一个AppRoot.vue,AppToolbar.vue和AppDrawer.vue
当我单击AppToolbar.vue中的按钮并在AppRoot.vue中声明时,我需要更改AppDrawer.vue的isDrawerOpen变量。
我该怎么做?任何人都可以帮助我吗?
AppRoot.vue
<template>
<v-app id="app-root">
<app-drawer></app-drawer>
<app-toolbar :title="title"></app-toolbar>
<v-content>
<v-container>
<slot><h1>Não há nada para exibir aqui!</h1></slot>
</v-container>
</v-content>
<app-footer></app-footer>
</v-app>
</template>
<script>
export default {
name: 'app-root',
props: ['title'],
}
</script>
AppToolbar.vue
<template>
<v-toolbar :color="$color" app>
<v-layout row hidden-md-and-up>
<v-toolbar-side-icon @click="openDrawer" class="white--text"></v-toolbar-side-icon>
</v-layout>
<v-toolbar-title class="white--text" v-text="title"></v-toolbar-title>
</v-toolbar>
</template>
<script>
export default {
name: 'app-toolbar',
props: ['title'],
methods: {
openDrawer() {
}
}
}
</script>
AppDrawer.vue
<template>
<v-navigation-drawer temporary v-model="isDrawerOpen" absolute>
<v-list class="pa-1">
<v-list-tile avatar>
<v-list-tile-avatar>
<img src="https://rafaeldeveloper.com.br/img/rafael_developer.jpg">
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title>Rafael de Azeredo</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
</template>
<script>
export default {
name: 'app-drawer',
data: () => ({
isDrawerOpen: false
})
}
</script>
答案 0 :(得分:2)
首先,您不需要在AppRoot.vue文件中使用props
属性,当您对孩子使用:title="title"
时,它会传递道具。 props
属性用于获取子级中的父组件属性。
对于您的查询,您可以使用事件总线在它们之间进行通信。或者,您可以使用vuex进行更好的状态管理。以下是我们如何使用事件总线实现的方法:
在main.js
文件中,定义事件中心或您想要的任何文件,但只需确保导入该文件的组件中的事件中心可用。
var eventHub = new Vue();
现在,这将用于您的所有组件。
接下来,您需要发出事件:
AppToolbar.vue
// ...
methods: {
openDrawer: function () {
eventHub.$emit('open-drawer', PASS_WHATEVER_YOU_WANT);
}
}
然后听孩子发出的事件:
AppDrawer.vue
// ...
created: function () {
eventHub.$on('open-drawer', this.openDrawer)
},
methods: {
openDrawer(value) {
// ... do whatever you want to do with value
// this.isDrawerOpen = !this.isDrawerOpen
this.isDrawerOpen = value;
}
}
答案 1 :(得分:1)
组件有两种状态:内部和外部。内部状态通常由组件data
控制,而外部状态通常通过props
进入。
当外部状态与组件的父级不紧密相关时,您可以将其视为应用程序状态或全局状态。这通常保存在每个组件都可用的“商店”中。很多人使用Vuex,但我认为大多数时候你并不真正需要Vuex,这主要涉及同步受大量可能同时输入影响的数据。
在单用户应用程序中,你只需要一个“教父”:像父母一样,你从中获取道具并发出事件,但这种关系并不直接。
实际上,如果你的应用程序是一个组件集合,$root
可用作该教父:你可以向它发出事件,你可以访问它的数据项和计算。
在您的示例中(我已将其拆分为下面的最小片段),抽屉的状态在应用程序中共享。它不在抽屉部件的内部。因此抽屉部件作为道具接收其状态;抽屉的父母 - app-root
- 使用:is-open="$root.drawerIsOpen"
来提供道具,这样抽屉就不会知道或关心它的状态是全局的;它就像任何道具一样流传下来。
工具栏组件知道应用程序中的某个抽屉,而不是它自己的父级,因此它会将open-drawer
事件发送到$root
:
this.$root.$emit('open-drawer');
顶级Vue($root
)在其created
挂钩中设置了事件处理,因为无法在模板中全局标记@open-drawer
。
这应该感觉非常类似于“道具向下,事件向上”的方式,通信被设计为在Vue中工作。
Vue.component('app-root', {
template: '#root-template',
props: ['title']
});
Vue.component('app-toolbar', {
template: '#toolbar-template',
methods: {
openDrawer() {
this.$root.$emit('open-drawer');
}
}
});
Vue.component('app-drawer', {
template: '#drawer-template',
props: ['isOpen']
});
new Vue({
el: '#app',
// This is your store!
data: {
drawerIsOpen: false
},
created() {
this.$on('open-drawer', () => {
this.drawerIsOpen = true;
});
}
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
<app-root title="My App!"></app-root>
</div>
<template id="root-template">
<div>
<h1>{{title}}</h1>
<app-toolbar></app-toolbar>
<app-drawer :is-open="$root.drawerIsOpen"></app-drawer>
</div>
</template>
<template id="toolbar-template">
<div>
<button @click="openDrawer">Open Drawer</button>
</div>
</template>
<template id="drawer-template">
<div v-show="isOpen">
Drawer here
</div>
</template>