繁体   English   中英

Vue.js 更改道具

[英]Vue.js Changing props

我对如何更改组件内部的属性有点困惑,假设我有以下组件:

{
    props: {
        visible: {
            type: Boolean,
            default: true
        }
    },
    methods: {
         hide() {
              this.visible = false;
         }
    }
} 

虽然它有效,但它会给出以下警告:

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

现在我想知道处理这个问题的最佳方法是什么,显然在 DOM 中创建组件时传入了visible属性: <Foo :visible="false"></Foo>

引用小提琴中的代码

不知何故,你应该决定一个国家居住的地方,而不是两个。 我不知道将它放在Alert中还是放在它的父级中是否更适合您的用例,但您应该选择一个。

如何决定国家在哪里

父组件或任何兄弟组件是否依赖于状态?

  • 是:那么它应该在父级(或在某些外部状态管理中)
  • 否:那么更容易让它处于组件本身的状态
  • 两者兼而有之:见下文

在极少数情况下,您可能需要组合。 也许你想让父母和孩子都能够隐藏孩子。 然后你应该在父母和孩子中都有状态(所以你不必在孩子里面编辑孩子的道具)。

例如,child 可以在以下情况下可见: visible && state_visible ,其中visible来自 props 并反映父级状态中的值,而state_visible来自子级状态。

我不确定这是否是您想要的行为,但这里有一个片段。 我有点假设您实际上只想在单击子组件时调用父组件的toggleAlert

 var Alert = Vue.component('alert', { template: ` <div class="alert" v-if="visible && state_visible"> Alert<br> <span v-on:click="close">Close me</span> </div>`, props: { visible: { required: true, type: Boolean, default: false } }, data: function() { return { state_visible: true }; }, methods: { close() { console.log('Clock this'); this.state_visible = false; } } }); var demo = new Vue({ el: '#demo', components: { 'alert': Alert }, data: { hasAlerts: false }, methods: { toggleAlert() { this.hasAlerts = !this.hasAlerts } } })
 .alert { background-color: #ff0000; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="demo" v-cloak> <alert :visible="hasAlerts"></alert> <span v-on:click="toggleAlert">Toggle alerts</span> </div>

如果 prop 只对这个子组件有用,则给孩子一个类似于initialVisibleprop ,和一个类似于mutableVisibledata ,并在created钩子中(在组装组件的数据结构时调用),只需this.mutableVisible = this.initialVisible

如果 prop 被父组件的其他子组件共享,您需要将其设为父组件的data以使其可用于所有子组件。 然后在 child 中, this.$emit('visibleChanged', currentVisible)通知 parent 改变visible 在父母的模板中,使用<ThatChild ... :visibleChanged="setVisible" ...> 看看指南: https ://v2.vuejs.org/v2/guide/components.html

根据Vue.js 组件文档

当父属性更新时,它会向下流向子属性,但不会反过来。 那么,当事情发生时,我们如何与父母沟通呢? 这就是 Vue 的自定义事件系统的用武之地。

使用来自孩子$emit('my-event)将事件发送给父母。 使用v-on:my-event (或@my-event )在父级内的子级声明中接收事件。

工作示例:

 // child Vue.component('child', { template: '<div><p>Child</p> <button @click="hide">Hide</button></div>', methods: { hide () { this.$emit('child-hide-event') } }, }) // parent new Vue({ el: '#app', data: { childVisible: true }, methods: { childHide () { this.childVisible = false }, childShow () { this.childVisible = true } } })
 .box { border: solid 1px grey; padding: 16px; }
 <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <div id="app" class="box"> <p>Parent | childVisible: {{ childVisible }}</p> <button @click="childHide">Hide</button> <button @click="childShow">Show</button> <p> </p> <child @child-hide-event="childHide" v-if="childVisible" class="box"></child> </div>

在阅读了您的最新评论后,您似乎担心有逻辑来显示/隐藏父级警报。 因此,我建议如下:

父母

# template
<alert :alert-visible="alertVisible"></alert>

# script
data () {
  alertVisible: false,
  ...
},
...

然后在子警报上,您将 $watch 道具的值并将所有逻辑移动到警报中:

孩子(警告)

# script
data: {
  visible: false,
  ...
},
methods: {
  hide () {
    this.visible = false
  },
  show () {
    this.visible = true
  },
  ...
},
props: [
  'alertVisible',
],
watch: {
  alertVisible () {
    if (this.alertVisible && !this.visible) this.show()
    else if (!this.alertVisible && this.visible) this.hide()
  },
  ...
},
...

为了帮助任何人,我面临着同样的问题。 我刚刚将 v-model="" 中的 var 从 props 数组更改为数据。 记住道具和数据之间的区别,我的情况是改变它不是问题,你应该权衡你的决定。

例如:

<v-dialog v-model="dialog" fullscreen hide-overlay transition="dialog-bottom-transition">

前:

export default {
    data: function () {
        return {
            any-vars: false
        }
    },
    props: {
            dialog: false,
            notifications: false,
            sound: false,
            widgets: false
        },
    methods: {
        open: function () {
            var vm = this;

            vm.dialog = true;
        }
    }
}

后:

export default {
    data: function () {
        return {
            dialog: false
        }
    },
    props: {
            notifications: false,
            sound: false,
            widgets: false
        },
    methods: {
        open: function () {
            var vm = this;

            vm.dialog = true;
        }
    }
}

也许它看起来像 hack 并且违反了单一数据源的概念,但它的工作原理)这个解决方案是创建本地代理变量并从 props 继承数据。 接下来使用代理变量。

Vue.component("vote", {
    data: function() {
        return {
            like_: this.like,
            dislike_: this.dislike,
        }
    },

    props: {
        like: {
            type: [String, Number],
            default: 0
        },
        dislike: {
            type: [String, Number],
            default: 0
        },
        item: {
            type: Object
        }
    },

    template: '<div class="tm-voteing"><span class="tm-vote tm-vote-like" @click="onVote(item, \'like\')"><span class="fa tm-icon"></span><span class="tm-vote-count">{{like_}}</span></span><span class="tm-vote tm-vote-dislike" @click="onVote(item, \'dislike\')"><span class="fa tm-icon"></span><span class="tm-vote-count">{{dislike_}}</span></span></div>',

    methods: {
        onVote: function(data, action) {
            var $this = this;
            // instead of jquery ajax can be axios or vue-resource
            $.ajax({
                method: "POST",
                url: "/api/vote/vote",
                data: {id: data.id, action: action},
                success: function(response) {
                    if(response.status === "insert") {
                        $this[action + "_"] = Number($this[action + "_"]) + 1;
                    } else {
                        $this[action + "_"] = Number($this[action + "_"]) - 1;
                    }
                },
                error: function(response) {
                    console.error(response);
                }
            });
        }
    }
});

使用组件并传递道具

<vote :like="item.vote_like" :dislike="item.vote_dislike" :item="item"></vote>

我想知道为什么警告有提示时会被其他人错过

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

尝试从子组件中收到的 prop 创建一个计算属性

computed: {
  isVisible => this.visible
}

并在您的子组件中使用此计算结果,并将更改发送给您的父组件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM