【问题标题】:Creating a Dialog component and showing/hiding from parent创建对话框组件并从父级显示/隐藏
【发布时间】:2019-12-05 12:44:07
【问题描述】:

在 Vue/Vuetify 中,我们如何从父级隐藏/显示对话框?我正在尝试使用v-model,这是我的设置的简化版本:

父组件(只是一个触发子组件显示的按钮)

<template>
<div>
    <v-btn class="ma-2" outlined fab color="red" small @click.stop="editItem()">
        <v-icon size="16">mdi-close-circle</v-icon>
    </v-btn>
    <user-dialog v-model="dialog" :eitem="editedItem" class="elevation-2" />
</div>
</template>

<script>
import UserDialog from "./UserDialog.vue";
export default {
    components:{
        UserDialog
    },
    data() {
        return {
            counter: 0,
            dialog: false,
            editedItem: {},
        }
    },
    methods: {
        editItem: function() {            
            this.counter++;       
            this.editedItem = Object.assign({}, {
                title: 'some title' + this.counter,
                details: 'some details for this item'
            });        

            this.dialog = true;
        },
    },
}
</script>

子组件(基本上是一个对话框)

<template>
    <v-dialog v-model="value" max-width="500px">
        <v-card>
            <v-card-title>
                <span class="headline">A Dialog</span>
            </v-card-title>

            <v-card-text>
                <v-container grid-list-md>
                    <v-layout wrap>
                        <v-flex xs12>
                            <v-text-field v-model="eitem.title" label="Title"></v-text-field>
                        </v-flex>
                        <v-flex xs12>
                            <v-text-field v-model="eitem.details" label="Details"></v-text-field>
                        </v-flex>
                    </v-layout>
                </v-container>
            </v-card-text>

            <v-card-actions>
                <v-spacer></v-spacer>
                <v-btn color="blue darken-1" text @click.stop="save">Save</v-btn>
                <v-btn color="blue darken-1" text @click.stop="close">Cancel</v-btn>
            </v-card-actions> 
        </v-card>
    </v-dialog>
</template>

<script>
    export default {
        props: {
            value: Boolean, 
            eitem: Object,
        },
        data() {
            return {
                editedItem: this.eitem,
            }
        },
        methods: {
            save() {
                //perform save
                this.$emit('input', false);
            },
            close() {
                this.$emit('input', false);
            },
        },
    }
</script>

此设置有效,但会发出以下警告:

避免直接改变 prop,因为每当父组件重新渲染时,该值将被覆盖。相反,使用基于道具值的数据或计算属性。正在变异的道具:“价值”

但是如果按照这个建议行事并在子组件中声明一个data 项并将v-dialogv-model 设置为此数据项,则对话框在单击时停止显示。

我也许理解它为什么会这样,但无法找出一个不显示警告的正确方法来解决这个问题。谁能帮我解决这个问题?

【问题讨论】:

  • 而不是使用v-modelv-text-field 的值绑定到道具。在input 上向父级发出一个自定义事件并让它更新道具的值。您可以将计算属性与 getter/setter 一起使用。
  • @HusamIbrahim:我听说v-model 是一种语法糖,它与您描述的完全一样。这种方法有何不同?
  • 澄清一下,这些文本字段绑定现在不是问题。目前,我实际上正在为v-dialogv-model 苦苦挣扎。我理解的问题的要点是我需要一种方法将本地data 项与prop 绑定,以便每当父组件更改其绑定的数据项时,子组件都会收到有关此更改的通知并在响应子组件更新其本地数据项(然后将触发 v-dialog 出现或消失..
  • 不同之处在于v-model 将尝试直接修改输入值,这相当于@input="value=$event.target.value"。您想要的是通过@input="()=&gt;{$emit('updateValue', newValue}" 向父级发出自定义事件,并让父级监听updateValue 事件以更新道具的值。这将在更新后自动反映在子组件中。
  • 我看到您声明 value 作为与 v-dialog 一起使用的道具,但您没有从父级传递它的值。在这种情况下,您应该指定一个默认值。而不是在值上使用v-model,而是直接使用带有getter/setter的计算属性。这样,如果从父级传递值,您可以向父级发出自定义事件以更新道具的值。否则,您可以改为更新本地值。

标签: javascript vue.js vuetify.js


【解决方案1】:

由于 Vue 在您更改 props 时会引发警告,因此您不应将 v-modelprops 一起使用。要处理此问题,请使用以下模式:

computed: {
  propModel: {
    get () { return this.value },
    set (value) { this.$emit('input', value) },
  },
},

使用 getter 定义 computed 属性,它返回 props.value,以及发出 input 事件的 setter(由于您使用 v-model,这将在父级中成功处理)

不要忘记更改您的template&lt;v-dialog v-model="propModel" max-width="500px"&gt;

【讨论】:

    猜你喜欢
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 2016-08-19
    • 1970-01-01
    相关资源
    最近更新 更多