'소품'변경 사항을 듣는 방법


257

에서 VueJs 2.0 문서 나 수신 대기하는 어떤 후크 찾을 수 없습니다 props변경.

VueJ는 이와 onPropsUpdated()유사한 고리를 가지고 있습니까?

최신 정보

@wostex가 제안했듯이 watch내 재산을 시험해 보았지만 아무것도 바뀌지 않았습니다. 그런 다음 특별한 경우가 있음을 깨달았습니다.

<template>
    <child :my-prop="myProp"></child>
</template>

<script>
   export default {
      props: ['myProp']
   }
</script>

나는 통과하고 myProp부모 구성 요소가로받는 child구성 요소입니다. 그런 다음 watch: {myProp: ...}작동하지 않습니다.



1
귀하의 사례를 올바르게 이해하고 있는지 잘 모르겠습니다. 정확한 목표가 무엇인지 설명 할 수 있습니까? "무슨 일이 생겼을 때, 여기서 뭔가 일이 생기길 원합니다." 상위 소품 값을 수동으로 변경하려고합니까? 그렇다면 이것은 완전히 다른 경우입니다.
Egor Stambakio

@wostex는 CodePen 입니다. 나쁜 점은 펜에서 작동한다는 것입니다.
Amio.io

1
문제는 다른 곳에 있습니다. 코드를 보여주세요. 살펴 보겠습니다.
Egor Stambakio 2016 년

1
안녕하세요. 여기 : ChannelDetail.vue 당신은 FacebookPageDetail 구성 요소 어디를 가져올 수 있지만, 그것을 선언하지 : gist.github.com/zatziky/... 나는 FacebookChannelDetail.vue이 잘 보이는 것보다 FacebookPageDetail 기타로 ChannelDetail.vue으로 수입해야 추측
에고를 Stambakio

답변:


321

watch소품 변경시 소품을 실행할 수 있습니다 .

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>


1
wostex에 대한 Thx, 나는 이미 시도했다 watch. 당신의 모범으로 인해 나는 나의 사건이 조금 다르다는 것을 깨달았습니다. 내 질문을 업데이트했습니다.
Amio.io

1
componentWillReceiveProps ()처럼 보입니다. 예를 들어 다음과 같습니다. D
yussan

@yussan 예, 그러나 추적해야 할 단일 소품에 적용됩니다.
Egor Stambakio

1
나는 일반적으로 계산 된 속성을 사용하는 것이 더 좋기 때문에 시계가 권장되지 않는다는 것을 알고 있지만 시계 사용에 성능 문제가 있습니까?
SethWhite

1
@SethWhite 관찰자 패턴을 사용하여 Vue에서 반응성을 처리 하는 방법을 이해 한 결과 , 감시자는 계산되거나 다른 반응성 데이터보다 효율성이 떨어질 필요는 없습니다. 속성 값이 많은 값에 의존하는 경우 계산 된 소품은 결과에 의존하는 각 값에 대해 별도의 시계 콜백 대 단일 함수를 실행합니다. 가장 일반적인 유스 케이스에서 계산 된 속성은 원하는 결과를 얻을 것이라고 생각합니다.
plong0

83

이것을 시도 했습니까?

watch: {
  myProp: {
    // the callback will be called immediately after the start of the observation
    immediate: true, 
    handler (val, oldVal) {
      // do your stuff
    }
  }
}

https://vuejs.org/v2/api/#watch


7
이것은 저에게 도움이되지 않은 곳에서 효과가있었습니다. 아마도 업데이트 일 것입니다. 감사합니다 BearInBox :)
Grant

2
즉시 : 진정한 나를 위해 수정
베이스베이스

2
시계를 이렇게 설정하면 나에게도 고마워했습니다. 감사합니다!
adamk22

2
나에게도 효과가 있습니다. 이것은 정답
titou10

1
받아 들인 대답은 그렇지 않은 반면 나를 위해 일했습니다. +1
로베르토

25

그,

필자의 경우 소품이 변경 될 때마다 데이터를 다시 구문 분석 해야하는 솔루션이 필요했습니다. 나는 모든 소품에 대해 분리 된 감시자를 만드는 데 지쳤습니다.

  watch: {
    $props: {
      handler() {
        this.parseData();
      },
      deep: true,
      immediate: true,
    },

이 예제에서 벗어나는 요점은 deep: true$ props를 감시 할뿐만 아니라props.myProp

이 확장 된 시계 옵션에 대한 자세한 내용은 여기 ( https://vuejs.org/v2/api/#vm-watch)를 참조 하십시오.


앞으로 지불하게되어 기쁩니다! 행운을 빕니다!
JoeSchr

7

당신은 당신이 가지고있는 컴포넌트 계층 구조와 소품을 전달하는 방법을 이해해야합니다. 확실히 귀하의 경우는 개발자가 직면하지 않는 특별한 경우입니다.

부모 구성 요소 -myProp-> 자식 구성 요소 -myProp-> 손자 구성 요소

부모 구성 요소에서 myProp가 변경 되면 자식 구성 요소에도 반영 됩니다.

그리고 자식 구성 요소에서 myProp가 변경되면 손자 구성 요소에도 반영 됩니다.

따라서 myProp가 부모 구성 요소에서 변경되면 손자 구성 요소에 반영 됩니다. (여태까지는 그런대로 잘됐다).

따라서 계층 구조를 낮추면 아무것도 할 필요가 없으며 소품은 본질적으로 반응합니다.

이제 계층 구조에서 올라가는 것에 대해 이야기합니다.

grandChild 컴포넌트에서 myProp가 변경되면 반영되지 않습니다 되면 자식 구성 요소에 . child에서 .sync 수정자를 사용해야하고 grandChild 컴포넌트에서 이벤트를 생성해야합니다.

하위 구성 요소에서 myProp가 변경 되면 상위 구성 요소에 반영되지 않습니다 . 부모에서 .sync 수정자를 사용해야하고 자식 구성 요소에서 이벤트를 생성해야합니다.

grandChild 컴포넌트에서 myProp가 변경되면 반영되지 않습니다 되면 부모 구성 요소에 분명히 . .sync 수정 자 자식을 사용하고 손자 구성 요소에서 이벤트를 생성 한 다음 자식 구성 요소의 prop을보고 .sync 수정자를 사용하여 부모 구성 요소가 수신하는 변경 이벤트를 생성해야합니다.

혼란을 피하기 위해 몇 가지 코드를 보자

Parent.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

<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>

손자. 뷰

<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>

그러나이 후 당신은 vue 말하기의 비명 경고를 눈치 채지 못할 것입니다

'부모 컴포넌트가 다시 렌더링 될 때마다 값을 덮어 쓰므로 prop를 직접 변경하지 마십시오.'

앞서 언급했듯이 대부분의 개발자는 안티 패턴이기 때문에이 문제가 발생하지 않습니다. 그래서이 경고가 나타납니다.

그러나 (디자인에 따라) 문제를 해결하기 위해. 위의 해결 방법을 사용해야한다고 생각합니다 (정직하게 해킹하십시오). 나는 여전히 당신이 당신의 디자인을 다시 생각하고 버그가 덜 발생하는 것이 좋습니다 권장합니다.

도움이 되길 바랍니다.


6

당신이 그것을 해결했는지 (그리고 내가 올바르게 이해하고 있는지) 확실하지 않지만 여기에 내 아이디어가 있습니다.

부모가 myProp을 받고 자식에게 전달하여 자식으로 보길 원한다면 부모는 myProp의 사본 (참조 아님)을 가져야합니다.

이 시도:

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 }
      }
    }
  }
}

그리고 html로 :

<child :my-prop="myInnerProp"></child>

실제로 이러한 상황에서 복잡한 컬렉션을 작업 할 때는 매우주의해야합니다 (몇 번 지나가는 경우).


좋은 생각. 지금은 단지 그것을 확인할 수 없습니다. vue로 다시 작업하면 확인할 것입니다.
Amio.io

1
감사합니다 @ m.cichacz, 아이까지 사본을 전달하는 같은 실수를 귀하의 제안에 신속하게 감사를 고정
undefinederror

4

양방향 바인딩을 위해서는 .sync 수정자를 사용해야합니다.

<child :myprop.sync="text"></child>

자세한 내용은...

변경 사항을 듣고 업데이트하려면 하위 구성 요소에서 watch 속성을 사용해야합니다

props: ['myprop'],
  watch: { 
    myprop: function(newVal, oldVal) { // watch it
      console.log('Prop changed: ', newVal, ' | was: ', oldVal)
    }
  }

사실 이것은 자식 구성 요소의 소품 변경 사항을 감시하는 새로운 방법입니다.
Amio.io

2

나는 다음과 같은 계산 된 속성으로 작업합니다.

    items:{
        get(){
            return this.resources;
        },
        set(v){
            this.$emit("update:resources", v)
        }
    },

이 경우 리소스는 속성입니다.

props: [ 'resources' ]

1

나에게 이것은 하나의 특정 소품을 변경하고 그와 함께 논리를 만드는 정중 한 솔루션입니다

내가 사용하는 것이 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 
  }
}

HTML 렌더링에서 _objectDetail을 사용할 수 있습니다.

<span>
  {{ _objectDetail }}
</span>

또는 어떤 방법으로 :

literallySomeMethod: function() {
   if (this._objectDetail) {
   ....
   }
}

0

시계 모드를 사용하여 변경 사항을 감지 할 수 있습니다.

모든 것을 원자 수준에서 수행하십시오. 먼저 내부에서 무언가를 위로하여 watch 메소드 자체가 호출되는지 여부를 확인하십시오. 시계가 호출되면 비즈니스 로직을 사용하십시오.

watch: { 
  myProp: function() {
   console.log('Prop changed')
  }
}

0

변경 사항을 수신 한 후 로직을 작성해야하는 경우 props및 변수 computed특성을 사용 합니다.

export default {
name: 'getObjectDetail',
filters: {},
components: {},
props: {
    objectDetail: {
      type: Object,
      required: true
    }
},
computed: {
    _objectDetail: {
        let value = false
        ...

        if (someValidation)
        ...
    }
}

-1

myProp가 객체이면 평소와 같이 변경되지 않을 수 있습니다. 따라서 시계가 트리거되지 않습니다. myProp가 변경되지 않는 이유는 대부분의 경우 myProp의 일부 키만 설정했기 때문입니다. myProp 자체는 여전히 하나입니다. "myProp.a"와 같은 myProp의 소품을 보려고하면 제대로 작동합니다.


-1

watch 기능은 Child 구성 요소에 있어야합니다. 부모가 아닙니다.


-1

@JoeSchr은 좋은 답변을 가지고 있습니다. 'deep : true'를 원하지 않는 경우이를 수행하는 다른 방법이 있습니다.

 mounted() {
    this.yourMethod();
    // re-render any time a prop changes
    Object.keys(this.$options.props).forEach(key => {
      this.$watch(key, this.yourMethod);
    });
  },
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.