【问题标题】:Vue child prop is not updated on bound value change in parentVue子道具不会在父级绑定值更改时更新
【发布时间】:2021-10-03 10:01:57
【问题描述】:

我正在使用 vue-property-decorator 库。我有 2 个组件:parentchildchild 是一个组件有一个道具 'modalHeader':

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';

@Component({
    name: "modal"
})
export default class Modal extends Vue {
    @Prop({default: "Header"}) public modalHeader!: string;
}
</script>

子组件的模板:

<template>
    <div
        class="modal fade"
        id="detailsModal"
        tabindex="-1"
        role="dialog"
        aria-labelledby="detailsModalLabel"
        aria-hidden="true"
    >
        <div class="modal-dialog modal-lg" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="detailsModalLabel">
                        {{ modalHeader }}
                    </h5>
                </div>
                ...
                </div>
            </div>
        </div>
    </div>
</template>

我的 parent 组件中有一个属性 'buttonPressed',我想将其属性绑定到子属性,因此每次都取决于在按下按钮时,我会得到一个不同的模态标题:

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import Modal from '../modal/Modal.vue';

interface ControlButtonSetting {
    id: string,
    name: string,
    enabled: boolean,
    isDanger: boolean,
    okText?: string,
    componentType?: IModalComponent,
}

@Component({
    name: "admin-dashboards-page",
    components: {
        "modal": Modal
    }
})
export default class AdminDashboardsPage extends Vue {

    private buttonsArray: ControlButtonSetting[] = [
        { id: "removeButton", name: "Remove", enabled: false, isDanger: true, okText: "Remove" }
    ];

    public buttonPressed!: ControlButtonSetting;

    private showModal = false;

    created(): void {
        this.buttonPressed = this.buttonsArray[0];
    }

    public controlButtonClicked(button: ControlButtonSetting): void {
        this.buttonPressed = button;
        this.showModal = true;
    }
}
</script>

父组件的模板:

<template>
    <div>
        ...

        <!-- Modal -->
        <modal
            :modal-header.sync="buttonPressed.name"
            <template v-slot:modalBody>
                <component
                    :is="displayComponent()"
                    :dashboard-id="selectedListItemId">
                </component>
            </template>
        </modal>
    </div>
</template>

但是,'modalHeader'值只在页面加载时设置一次,但是当'selectedButton'对象改变时,'modalHeader' strong> 子组件上的值未更新。

帮助我的是将父母的对象定义为Prop()

@Prop() public buttonPressed!: ControlButtonSetting;

这样子组件的prop会在父组件的prop更新时更新。但我开始在控制台中看到这条消息:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "buttonPressed"

我不太确定这里出了什么问题。你能帮我解决一下吗?

附:我的一个猜测是我没有改变父级中的绑定属性,而是用一个新对象替换它,这就是父子绑定可能不起作用的原因。去看看吧。

【问题讨论】:

  • 可以分享一下parent组件的模板吗?至少包含 child 组件的部分?
  • @Kapcash 是的。将其添加到帖子中。

标签: javascript typescript vue.js vue-props


【解决方案1】:

简而言之:您的buttonPressed 数据不是反应性的,因为它没有被初始化。必须正确初始化 Vue 才能将其标记为响应式。

public buttonPressed!: ControlButtonSetting; // not initialised

您有两个选项可以正确初始化它:

#1 你给它一个适当的默认值,即使是空的,在声明它之后直接。

public buttonPressed: ControlButtonSetting = {
  id: "",
  name: "",
  enabled: false,
  isDanger: false,
  okText: ""
}

#2 如果您希望其默认值依赖于其他数据/道具,请使用data 工厂。 (不要为此使用created 钩子)

public buttonPressed!: ControlButtonSetting; // use !: to tell typescript it's declared but in another place

// Even using `vue-property-decorator`, this will work and merge both data() and class properties
data () {
  return {
     buttonPressed: this.buttonsArray[0],
  }
}

不要将buttonPressed 标记为道具,因为它不是。并且 Vue 道具不能从子级更新,它会破坏父级的反应性。


注意:Vue props 应该始终提供一个类型。即使使用vue-property-decorator,您也必须指定它。

@Prop({ type: String, default: 'Header' }) <- Vue prop type, only for runtime
readonly modalHeader!: string // <- typescript type, only for build time

(我建议你使用readonly关键字告诉Typescript这个属性不能更新,因为props在Vue中是不可变的)

【讨论】:

  • 谢谢。设置有界值的默认值对我有帮助!
猜你喜欢
  • 2020-01-19
  • 2020-12-13
  • 1970-01-01
  • 2021-04-01
  • 2021-11-04
  • 2023-03-28
  • 2018-08-09
  • 2019-04-06
  • 2019-08-27
相关资源
最近更新 更多