避免直接改变道具,因为每当父组件重新渲染时,该值都会被覆盖

Posted

技术标签:

【中文标题】避免直接改变道具,因为每当父组件重新渲染时,该值都会被覆盖【英文标题】:Getting avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders 【发布时间】:2017-05-04 02:27:30 【问题描述】:

我是 vuejs 的新手,我正在尝试将 active 数据同步到父级,但出现错误

vue.js:523 [Vue 警告]:避免直接改变 prop,因为只要父组件重新渲染,该值就会被覆盖。相反,使用基于道具值的数据或计算属性。正在变异的道具:“活跃” (在组件中找到)

我的 Vuejs 代码如下

<div id="app">
    <pre>
        $data
    </pre>
    <div v-for="plan in plans">
        <plan :plan="plan" :active.sync="active"></plan>
    </div>
</div>
<template id="mytemplate">
    <div>
        $data
        <span>plan.name</span>
        <span>plan.price</span>
        <button @click="setActivePlan">upgrade</button>
    </div>
</template>

<script src="vue.js"></script>
<script>
    new Vue(
        el: "#app",

        data: 
            active:this.active,
            plans: [
                name: 'Diamond', price: '1000',
                name: 'Gold', price: '500',
                name: 'Silver', price: '250',
                name: 'Free', price: '0'
            ]
        ,
        components: 
            plan: 
                template: "#mytemplate",
                props: ['plan', 'active'],
                methods: 
                    setActivePlan: function () 
                        this.active = this.plan
                    
                
            
        

    );
</script>

谁能帮我解决这个问题

【问题讨论】:

【参考方案1】:

正如错误提示的那样,您正在尝试更改其中一个道具active

正在变异的道具:“活跃”(在组件中找到)

由于 props 是从 parent 动态发送的,因此只要 parent 更改它们,它们就会更改,如果您在 child 中也更改它们,则会发生冲突,这就是您收到此错误的原因。

和documentation一样:

父子组件关系可以概括为props down,events up。父级通过 props 向下传递数据给子级,子级通过事件向父级发送消息。

因此,正确的方法是emit 一个事件,它将调用父级中的一个方法并更改定义它的父级中的变量active。以下将是代码更改:

<script src="vue.js"></script>
<script>
    new Vue(
        el: "#app",

        data: 
            active:this.active,
            plans: [
                name: 'Diamond', price: '1000',
                name: 'Gold', price: '500',
                name: 'Silver', price: '250',
                name: 'Free', price: '0'
            ]
        ,
        methods: 
           setActivePlan: function (plan) 
              this.active = plan
           
         
        components: 
            plan: 
                template: "#mytemplate",
                props: ['plan', 'active'],
                methods: 
                    setActivePlan: function () 
                        this.$emit('setActivePlan', this.plan)
                    
                
            
        

    );
</script>

【讨论】:

这个解释比文档清楚多了。 VueJS 只是通过不允许属性值向上突变来实现 MVVM 范式。【参考方案2】:

我希望这是版本问题。请显示您的 VUEJS 版本,否则请从下面的代码中获取版本。

<div id="app">
    <pre>
    $data |  json
    </pre>
        <div v-for="plan in plans">
            <plan :plan="plan" :active.sync="active"></plan>
        </div>
    </div>
    <template id="mytemplate">
        <div>
            <span>plan.name</span>
            <span>plan.price</span>
            <span>aplan.active</span>
            <button @click="setActivePlan">upgrade</button>
        </div>
    </template>

    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.25/vue.js"></script>
    <script>
        new Vue(
            el: "#app",

            data: 
                plans: [
                    name: 'Diamond', price: '1000',
                    name: 'Gold', price: '500',
                    name: 'Silver', price: '250',
                    name: 'Free', price: '0'
                ],
                active:

                
            ,
            components: 
                plan: 
                    template: "#mytemplate",
                    props: ['plan', 'active'],
                    methods: 
                        setActivePlan: function () 
                            this.active = this.plan
                        
                    
                
            

        );
    </script>

【讨论】:

以上是关于避免直接改变道具,因为每当父组件重新渲染时,该值都会被覆盖的主要内容,如果未能解决你的问题,请参考以下文章

避免直接改变道具 - Datatable VueJS

避免直接改变道具,因为该值将被覆盖

[Vue 警告]:避免直接改变 prop

避免在可重用组件中直接改变 prop

Vue关闭组件返回避免直接改变道具

Vue警告避免改变道具“taskToEdit”