[英]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 只对这个子组件有用,则给孩子一个类似于initialVisible
的prop
,和一个类似于mutableVisible
的data
,并在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.