随着单个文件组件变得越来越大,我尝试对其进行一些重构。原来,我有几个对话框使.vue
文件变得巨大(800行以上)。因此,为了保持组件的清洁,我试图将对话框变成专用的子组件(mydialog
)。我正在使用vuetify(不需要熟悉vuetify)。
我在父组件中有一个启用对话框的按钮。我将dialog
道具发送到子组件,然后将其附加到v-model
对话框的。问题是,它只能在第一次使用。那是因为当我单击该close
按钮时,它将dialog
的值更改为,false
并且false
由于子组件与父组件失去了联系,它将永远存在。在这种情况下,我该如何解决?
这是代码段:
Vue.component('mydialog', {
props:{
dialog: {
type: Boolean,
default: false
}
},
template: `
<div class="text-xs-center">
<v-dialog
v-model="dialog"
width="500"
>
<v-card>
<v-card-title
class="headline grey lighten-2"
primary-title
>
A Dialog
</v-card-title>
<v-card-text>
Lorem ipsum dolor sit amet,
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="primary"
flat
@click="dialog = false"
>
Close
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
`,
data: function() {
return {
// dialog: false,
}
}
});
new Vue({
el: '#app',
data: {
dialog: false
}
});
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.2.0/vuetify.min.css" />
</head>
<body>
<div id="app">
<v-app id="inspire">
<v-btn color="red lighten-2" dark @click="dialog=true">Click Me</v-btn>
<mydialog :dialog="dialog"></mydialog>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.2.0/vuetify.min.js"></script>
</body>
</html>
您的组件通讯有点中断:基本上,您的对话框没有通知应用程序组件它已关闭。以下两项更改可启用模式与应用程序之间的上游通信:
在app
模板中:
<mydialog :dialog.sync="dialog"></mydialog>
在mydialog
控制器中:
data: function() {
return {
dialog$: false,
};
},
methods: {
onClose() {
this.dialog$ = false;
this.$emit('update:dialog', this.dialog$);
},
},
watch: {
dialog: {
immediate: true,
handler() {
this.dialog$ = this.dialog;
},
},
}
第一个更改使app
组件侦听有关dialog
道具的更新mydialog
。
mydialog
我在dialog$
其中添加了一个反映dialog
道具的数据属性(因为道具被认为是恒定的,不应更改)。观察者要确保下游在dialog
update上进行更新dialog$
。该onClose
方法dialog$
在关闭对话框时更新,并向订阅者(特别是app
)发出更新。
Vue.component('mydialog', {
props:{
dialog: {
type: Boolean,
default: false
}
},
template: `
<div class="text-xs-center">
<v-dialog
v-model="dialog$"
width="500"
>
<v-card>
<v-card-title
class="headline grey lighten-2"
primary-title
>
A Dialog
</v-card-title>
<v-card-text>
Lorem ipsum dolor sit amet,
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="primary"
flat
@click="onClose"
>
Close
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
`,
data: function() {
return {
dialog$: false,
};
},
methods: {
onClose() {
this.dialog$ = false;
this.$emit('update:dialog', this.dialog$);
},
},
watch: {
dialog: {
immediate: true,
handler() {
this.dialog$ = this.dialog;
},
},
}
});
new Vue({
el: '#app',
data: {
dialog: false
},
template: `
<v-app id="inspire">
<v-btn color="red lighten-2" dark @click="dialog=true">Click Me</v-btn>
<mydialog :dialog.sync="dialog"></mydialog>
</v-app>
`,
});
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.2.0/vuetify.min.css" />
</head>
<body>
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.2.0/vuetify.min.js"></script>
</body>
</html>
正如@ raina77ow所提到的,您也可以使用事件总线解决此类问题,但在这种情况下不是必须的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句