【问题标题】:v-bind v-model or v-bind.sync?v-bind v-model 还是 v-bind.sync?
【发布时间】:2019-05-31 09:05:36
【问题描述】:

我不明白v-bindv-modelv-bind.sync有什么区别?

也许为时已晚,但阅读文档后我无法区分v-bind.syncv-model

Sync modifier

Passing Data to Child Components with Props

v-model

示例

我使用“vue-property-decorator”用 Typescript 编写了以下组件。我不知道如何在不必自己编写事件处理的情况下更新传递给组件的date 对象。如果你问我,它应该适用于 v-modelv-bind.sync 绑定(以及标记和装饰器中的相应更改)。

HTML

<Datepicker v-model="date"/>

打字稿

import { Component, Prop, Vue, Model } from "vue-property-decorator";

@Component({})
export default class Datepicker extends Vue {
    @Prop()
    private label!: string;
    @Model()
    private date!: Date;
    private internalDate = new Date().toISOString().substr(0, 10);
    private menu = false;

    private onDateChanged() {
        const isoDate = this.date.toISOString();
        const newDate =
            this.internalDate + this.date.toISOString().substring(10);
        this.date = new Date(newDate);
    }
}

每次我更改 this.date 对象时,都会收到警告:

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

【问题讨论】:

  • 我不熟悉打字稿,但使用 v-model 是此类事情的推荐方式。您收到的警告可能是完全不同的事情,可能是转译器有问题并且源没有正确更新或类似的东西?

标签: vue.js


【解决方案1】:

在 Vue.js 中,您不应更改组件传递给您的输入 prop。例如,在您的情况下,请考虑 label 道具。在您的DatePicker 中,您不应该有任何类似this.label = 'Hello! Change Prop!'; 的语句。

TLDR:不要改变组件中的 prop。让父母对其进行变异。

回到你的组件,你应该有一个这样的组件:

import { Component, Prop, Vue, Watch } from 'vue-property-decorator';

@Component({})
export default class Datepicker extends Vue {

    @Prop()
    private label!: string;

    @Prop()
    private value!: Date;

    private internalDate = new Date().toISOString().substr(0, 10);

    private previouslyEmittedDate: Date;

    private menu = false;

    @Watch('value')
    public onDatePropChange() {

        // Break infinite one-way recursion
        if (this.value !== this.previouslyEmittedDate) {
            const newDate = new Date(this.internalDate + this.value.toISOString().substring(10));

            this.previouslyEmittedDate = newDate;

            // input events created a sugar coated v-model binding
            this.$emit('input', newDate);
        }
    }
}

附带说明:我注意到这里有某种代码味道。在每次更改日期时,您都会添加一些内部日期。它将导致无限的单向绑定递归。 v-model 用于input 由用户更改,而不是以编程方式更改。 v-model 只是以下内容的糖衣语法:

<Datepicker :value="date" @input="this.date = $event"/>

最后,避免使用.sync 修饰符。它有不同的用途,应谨慎使用。

【讨论】:

  • 你为什么用@Prop代替value而不是@Model
  • @Model 感觉有点神奇。而且,如果我们需要v-model,我们会尝试坚持使用@input:value 对。这是一小步,但在构建大型应用程序时有很大帮助。每个人都有一个共同的词汇。
猜你喜欢
  • 1970-01-01
  • 2017-07-04
  • 2020-07-18
  • 2017-10-01
  • 2019-12-20
  • 2018-05-15
  • 2019-05-07
  • 1970-01-01
  • 2017-06-12
相关资源
最近更新 更多