[javascript] Vue.js 2에서 소품을 초기 데이터로 전달하는 올바른 방법은 무엇입니까?

그래서 나는 Vue 컴포넌트에 props를 전달하고 싶지만, 이러한 props는 예를 들어 AJAX를 사용하여 내부에서 Vue 컴포넌트를 업데이트 할 때 그 컴포넌트 내부에서 미래에 변경 될 것으로 예상합니다. 따라서 구성 요소 초기화에만 사용됩니다.

cars-list초기 속성이있는 소품을 다음 위치에 전달하는 내 Vue 구성 요소 요소 single-car:

// cars-list.vue

<script>
    export default {
        data: function() {
            return {
                cars: [
                    {
                        color: 'red',
                        maxSpeed: 200,
                    },
                    {
                        color: 'blue',
                        maxSpeed: 195,
                    },
                ]
            }
        },
    }
</script>

<template>
    <div>
        <template v-for="car in cars">
            <single-car :initial-properties="car"></single-car>
        </template>
    </div>
</template>

내가 지금 수행하는 방식은 내 single-car구성 요소 this.initialPropertiesthis.data.properties에서 created()초기화 후크 에 할당 하는 것 입니다 . 그리고 그것은 작동하고 반응합니다.

// single-car.vue

<script>
    export default {
        data: function() {
            return {
                properties: {},
            }
        },
        created: function(){
            this.data.properties = this.initialProperties;
        },
    }
</script>

<template>
    <div>Car is in {{properties.color}} and has a max speed of {{properties.maxSpeed}}</div>
</template>

하지만 내 문제는 그것이 올바른 방법인지 모르겠다는 것입니다. 그것은 나에게 길을 따라 약간의 문제를 일으키지 않습니까? 아니면 더 좋은 방법이 있습니까?



답변

https://github.com/vuejs/vuejs.org/pull/567 덕분에 이제 답을 알고 있습니다.

방법 1

초기 소품을 데이터에 직접 전달합니다. 업데이트 된 문서의 예와 같습니다.

props: ['initialCounter'],
data: function () {
    return {
        counter: this.initialCounter
    }
}

그러나 전달 된 소품이 부모 구성 요소 상태에서 사용되는 객체 또는 배열 인 경우 해당 소품을 수정하면 해당 부모 구성 요소 상태가 변경됩니다.

경고 :이 방법은 권장되지 않습니다. 구성 요소를 예측할 수 없게 만듭니다. 하위 구성 요소에서 부모 데이터를 설정해야하는 경우 Vuex와 같은 상태 관리를 사용하거나 “v-model”을 사용합니다. https://vuejs.org/v2/guide/components.html#Using-v-model-on-Components

방법 2

초기 소품이 객체 또는 배열이고 자식 상태의 변경 사항이 부모 상태로 전파되는 것을 원하지 않는 경우 다음 Vue.util.extend과 같이 자식 데이터를 직접 가리키는 대신 예를 들어 [1]을 사용하여 소품의 복사본을 만듭니다.

props: ['initialCounter'],
data: function () {
    return {
        counter: Vue.util.extend({}, this.initialCounter)
    }
}

방법 3

스프레드 연산자를 사용하여 소품을 복제 할 수도 있습니다. Igor 답변에 대한 자세한 내용 : https://stackoverflow.com/a/51911118/3143704

그러나 스프레드 연산자는 이전 브라우저에서 지원되지 않으며 더 나은 호환성을 위해 코드를 변환해야합니다 (예 : babel.

각주

[1] 이것은 내부 Vue 유틸리티이며 새 버전으로 변경 될 수 있습니다. 다른 방법을 사용하여 해당 소품을 복사 할 수 있습니다 . ” JavaScript 객체를 올바르게 복제하려면 어떻게해야합니까? “를 참조하십시오.

내가 테스트 한 내 바이올린 :
https://jsfiddle.net/sm4kx7p9/3/


답변

@ dominik-serafin의 답변과 함께 :

객체를 전달하는 경우 확산 연산자 (ES6 구문)를 사용하여 쉽게 복제 할 수 있습니다.

 props: {
   record: {
     type: Object,
     required: true
   }
 },

data () { // opt. 1
  return {
    recordLocal: {...this.record}
  }
},

computed: { // opt. 2
  recordLocal () {
    return {...this.record}
  }
},

그러나 가장 중요한 것은 opt를 사용하는 것입니다. 2 계산 된 값을 전달하는 경우 또는 그 이상의 비동기 값을 전달합니다. 그렇지 않으면 로컬 값이 업데이트되지 않습니다.

데모:

Vue.component('card', {
  template: '#app2',
  props: {
    test1: null,
    test2: null
  },
  data () { // opt. 1
    return {
      test1AsData: {...this.test1}
    }
  },
  computed: { // opt. 2
    test2AsComputed () {
      return {...this.test2}
    }
  }
})

new Vue({
  el: "#app1",
  data () {
    return {
      test1: {1: 'will not update'},
      test2: {2: 'will update after 1 second'}
    }
  },
  mounted () {
    setTimeout(() => {
      this.test1 = {1: 'updated!'}
      this.test2 = {2: 'updated!'}
    }, 1000)
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>

<div id="app1">
  <card :test1="test1" :test2="test2"></card>
</div>

<template id="app2">
  <div>
    test1 as data: {{test1AsData}}
    <hr />
    test2 as computed: {{test2AsComputed}}
  </div>
</template>

https://jsfiddle.net/nomikos3/eywraw8t/281070/


답변

문서에 명시된 내용이기 때문에 올바르게하고 있다고 생각합니다.

소품의 초기 값을 초기 값으로 사용하는 로컬 데이터 속성을 정의합니다.

https://vuejs.org/guide/components.html#One-Way-Data-Flow


답변