Javascript 如何监听“道具”变化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44584292/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to listen for 'props' changes
提问by Amio.io
In the VueJs 2.0 docsI can't find any hooks that would listen on propschanges.
在VueJs 2.0 文档中,我找不到任何可以监听props更改的钩子。
Does VueJs have such hooks like onPropsUpdated()or similar?
VueJs 有类似onPropsUpdated()或类似的钩子吗?
Update
更新
As @wostex suggested, I tried to watchmy property but nothing changed. Then I realized that I've got a special case:
正如@wostex 建议的那样,我尝试了watch我的财产,但没有任何改变。然后我意识到我有一个特殊情况:
<template>
<child :my-prop="myProp"></child>
</template>
<script>
export default {
props: ['myProp']
}
</script>
I am passing myPropthat the parent component receives to the childcomponent. Then the watch: {myProp: ...}is not working.
我myProp将父组件接收到的传递给child组件。然后watch: {myProp: ...}是不工作。
回答by Egor Stambakio
You can watchprops to execute some code upon props changes:
你可以通过watchprops 在 props 改变时执行一些代码:
new Vue({
el: '#app',
data: {
text: 'Hello'
},
components: {
'child' : {
template: `<p>{{ myprop }}</p>`,
props: ['myprop'],
watch: {
myprop: function(newVal, oldVal) { // watch it
console.log('Prop changed: ', newVal, ' | was: ', oldVal)
}
}
}
}
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<child :myprop="text"></child>
<button @click="text = 'Another text'">Change text</button>
</div>
回答by BearInBox
Have you tried this ?
你试过这个吗?
watch: {
myProp: {
// the callback will be called immediately after the start of the observation
immediate: true,
handler (val, oldVal) {
// do your stuff
}
}
}
回答by JoeSchr
He,
他,
in my case I needed a solution where anytime any props would change, I needed to parse my data again. I was tired of making seperated watcher for all my props, so I used this:
在我的情况下,我需要一个解决方案,任何时候任何道具都会改变,我需要再次解析我的数据。我厌倦了为我的所有道具制作单独的观察者,所以我使用了这个:
watch: {
$props: {
handler() {
this.parseData();
},
deep: true,
immediate: true,
},
Key point to take away from this example is to use deep: trueso it not only watches $props but also it's nested values like e.g. props.myProp
从这个例子中拿走的关键点是使用deep: trueso 它不仅监视 $props 还监视它的嵌套值,例如props.myProp
You can learn more about this extended watch options here: https://vuejs.org/v2/api/#vm-watch
您可以在此处了解有关此扩展监视选项的更多信息:https: //vuejs.org/v2/api/#vm-watch
回答by The Observer Man
You need to understand, the component hierarchy you are having and how you are passing props, definitely your case is special and not usually encountered by the devs.
您需要了解您所拥有的组件层次结构以及您如何传递道具,当然您的情况很特殊,开发人员通常不会遇到。
Parent Component -myProp-> Child Component -myProp-> Grandchild Component
父组件-myProp-> 子组件-myProp-> 孙组件
If myProp is changed in parent component it will be reflectedin the child component too.
如果 myProp 在父组件中更改,它也会反映在子组件中。
And if myProp is changed in child component it will be reflectedin grandchild component too.
如果 myProp 在子组件中更改,它也会反映在孙组件中。
So if myProp is changed in parent component then it will be reflectedin grandchild component. (so far so good).
因此,如果 myProp 在父组件中更改,那么它将反映在孙组件中。(到目前为止,一切都很好)。
Therefore down the hierarchy you don't have to do anything props will be inherently reactive.
因此,在层次结构中,您不必做任何事情道具将具有内在的反应性。
Now talking about going up in hierarchy
现在谈论在层次结构中上升
If myProp is changed in grandChild component it won't be reflectedin the child component. You have to use .sync modifier in child and emit event from the grandChild component.
如果在grandChild 组件中更改了myProp,它将不会反映在子组件中。您必须在 child 中使用 .sync 修饰符并从 grandChild 组件发出事件。
If myProp is changed in child component it won't be reflectedin the parent component. You have to use .sync modifier in parent and emit event from the child component.
如果 myProp 在子组件中更改,则不会反映在父组件中。您必须在父组件中使用 .sync 修饰符并从子组件发出事件。
If myProp is changed in grandChild component it won't be reflectedin the parent component (obviously). You have to use .sync modifier child and emit event from the grandchild component, then watch the prop in child component and emit an event on change which is being listened by parent component using .sync modifier.
如果在grandChild 组件中更改了myProp,它将不会反映在父组件中(显然)。您必须使用 .sync 修饰符 child 并从孙组件发出事件,然后观察子组件中的 prop 并在父组件使用 .sync 修饰符侦听的更改时发出事件。
Let's see some code to avoid confusion
让我们看一些代码以避免混淆
Parent.vue
父.vue
<template>
<div>
<child :myProp.sync="myProp"></child>
<input v-model="myProp"/>
<p>{{myProp}}</p>
</div>
</template>
<script>
import child from './Child.vue'
export default{
data(){
return{
myProp:"hello"
}
},
components:{
child
}
}
</script>
<style scoped>
</style>
Child.vue
儿童.vue
<template>
<div> <grand-child :myProp.sync="myProp"></grand-child>
<p>{{myProp}}</p>
</div>
</template>
<script>
import grandChild from './Grandchild.vue'
export default{
components:{
grandChild
},
props:['myProp'],
watch:{
'myProp'(){
this.$emit('update:myProp',this.myProp)
}
}
}
</script>
<style>
</style>
Grandchild.vue
孙子.vue
<template>
<div><p>{{myProp}}</p>
<input v-model="myProp" @input="changed"/>
</div>
</template>
<script>
export default{
props:['myProp'],
methods:{
changed(event){
this.$emit('update:myProp',this.myProp)
}
}
}
</script>
<style>
</style>
But after this you wont help notice the screaming warnings of vue saying
但是在此之后,您将无法帮助注意到 vue 说的尖叫警告
'Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders.'
“避免直接改变 prop,因为每当父组件重新渲染时,该值都会被覆盖。”
Again as I mentioned earlier most of the devs don't encounter this issue, because it's an anti pattern. That's why you get this warning.
再次正如我之前提到的,大多数开发人员不会遇到这个问题,因为这是一种反模式。这就是您收到此警告的原因。
But in order to solve your issue (according to your design). I believe you have to do the above work around(hack to be honest). I still recommend you should rethink your design and make is less prone to bugs.
但是为了解决您的问题(根据您的设计)。我相信你必须做上述工作(老实说是黑客)。我仍然建议你应该重新考虑你的设计,并且 make 不太容易出现错误。
I hope it helps.
我希望它有帮助。
回答by m.cichacz
Not sure if you have resolved it (and if I understand correctly), but here's my idea:
不确定你是否已经解决了(如果我理解正确),但这是我的想法:
If parent receives myProp, and you want it to pass to child and watch it in child, then parent has to have copy of myProp (not reference).
如果 parent 收到 myProp,并且您希望它传递给 child 并在 child 中观看它,则 parent 必须拥有 myProp 的副本(不是引用)。
Try this:
尝试这个:
new Vue({
el: '#app',
data: {
text: 'Hello'
},
components: {
'parent': {
props: ['myProp'],
computed: {
myInnerProp() { return myProp.clone(); } //eg. myProp.slice() for array
}
},
'child': {
props: ['myProp'],
watch: {
myProp(val, oldval) { now val will differ from oldval }
}
}
}
}
and in html:
并在 html 中:
<child :my-prop="myInnerProp"></child>
actually you have to be very careful when working on complex collections in such situations (passing down few times)
实际上,在这种情况下处理复杂集合时必须非常小心(传递几次)
回答by Md Mahamudul Hasan
for two way binding you have to use .sync modifier
对于双向绑定,您必须使用 .sync 修饰符
<child :myprop.sync="text"></child>
and you have to use watch property in child component to listen and update any changes
并且您必须在子组件中使用 watch 属性来监听和更新任何更改
props: ['myprop'],
watch: {
myprop: function(newVal, oldVal) { // watch it
console.log('Prop changed: ', newVal, ' | was: ', oldVal)
}
}
回答by Wouter Schoofs
I work with a computed property like:
我使用计算属性,如:
items:{
get(){
return this.resources;
},
set(v){
this.$emit("update:resources", v)
}
},
Resources is in this case a property:
在这种情况下,资源是一个属性:
props: [ 'resources' ]
回答by Manuel Alanis
For me this is a polite solution to get one specific prop(s) changes and create logic with it
对我来说,这是一个礼貌的解决方案,可以让一个特定的道具发生变化并用它创建逻辑
I would use propsand variables computedproperties to create logic after to receive the changes
在接收更改后,我将使用props和变量computed属性来创建逻辑
export default {
name: 'getObjectDetail',
filters: {},
components: {},
props: {
objectDetail: { // <--- we could access to this value with this.objectDetail
type: Object,
required: true
}
},
computed: {
_objectDetail: {
let value = false
// ...
// if || do || while -- whatever logic
// insert validation logic with this.objectDetail (prop value)
value = true
// ...
return value
}
}
So, we could use _objectDetail on html render
所以,我们可以在 html 渲染上使用 _objectDetail
<span>
{{ _objectDetail }}
</span>
or in some method:
或以某种方法:
literallySomeMethod: function() {
if (this._objectDetail) {
....
}
}
回答by Manuel Alanis
I use propsand variables computedproperties if I need create logic after to receive the changes
如果我需要在接收更改后创建逻辑,我将使用props和变量computed属性
export default {
name: 'getObjectDetail',
filters: {},
components: {},
props: {
objectDetail: {
type: Object,
required: true
}
},
computed: {
_objectDetail: {
let value = false
...
if (someValidation)
...
}
}
回答by Rahul Sharma
You can use the watch mode to detect changes:
您可以使用监视模式来检测更改:
Do everything at atomic level. So first check if watch method itself is getting called or not by consoling something inside. Once it has been established that watch is getting called, smash it out with your business logic.
在原子级别做任何事情。所以首先通过安慰里面的东西来检查 watch 方法本身是否被调用。一旦确定 watch 被调用,就用你的业务逻辑粉碎它。
watch: {
myProp: function() {
console.log('Prop changed')
}
}

