[javascript] Vue 2-Vue-warn 뮤팅 소품

나는 https://laracasts.com/series/learning-vue-step-by-step 시리즈를 시작했습니다 . 이 오류로 Vue, Laravel 및 AJAX 레슨을 중단했습니다 .

vue.js : 2574 [Vue warn] : 부모 구성 요소가 다시 렌더링 될 때마다 값을 덮어 쓰므로 prop를 직접 변경하지 마십시오. 대신 소품의 값을 기준으로 데이터 또는 계산 된 속성을 사용하십시오. 소품이 변경 중 : “list”(component에 있음)

main.js 에이 코드가 있습니다.

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    created() {
        this.list = JSON.parse(this.list);
    }
});
new Vue({
    el: '.container'
})

목록 소품을 덮어 쓸 때 문제가 created () 에 있지만 Vue의 초보자이므로 문제를 해결하는 방법을 완전히 모릅니다. 누구나 그것을 고치는 방법을 알고 있습니까 (그리고 이유를 설명하십시오)?



답변

이것은 Vue 2에서 소품을 로컬로 변경하는 것이 안티 패턴으로 간주 된다는 사실과 관련이 있습니다.

소품을 로컬로 변경 하려면 지금해야 할 일은 값을 초기 값으로 data사용 하는 필드를 선언 한 props다음 사본을 변경하는 것입니다.

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    data: function () {
        return {
            mutableList: JSON.parse(this.list);
        }
    }
});

이에 대한 자세한 내용은 Vue.js 공식 안내서를 참조하십시오.


주 1 : 것을 제발 참고 는해야 하지 당신에 같은 이름을 사용 prop하고data , 즉 :

a
data: function () { return { list: JSON.parse(this.list) } // WRONG!!

2 주 : 이후 나는 약간의 혼동이 느낌 에 대한 props반응성 , 나는에보고해야 할 제안 스레드를


답변

Vue 패턴이 props위아래로 움직 events입니다. 간단하게 들리지만 사용자 컴포넌트를 작성할 때 잊어 버리기 쉽습니다.

Vue 2.2.0부터 v-model을 사용할 수 있습니다 ( 계산 된 속성 포함 ). 이 조합은 구성 요소 사이에 간단하고 깨끗하며 일관된 인터페이스를 만듭니다.

  • props구성 요소에 전달 된 모든 항목 은 반응 상태로 유지됩니다 (즉, watch변경 사항이 감지 될 때 복제되지 않았거나 로컬 복사본을 업데이트하는 기능이 필요하지 않습니다 ).
  • 변경 사항은 자동으로 부모에게 전달됩니다.
  • 여러 레벨의 구성 요소와 함께 사용할 수 있습니다.

계산 된 속성을 사용하면 setter와 getter를 별도로 정의 할 수 있습니다. 이를 통해 Task컴포넌트를 다음과 같이 다시 작성할 수 있습니다.

Vue.component('Task', {
    template: '#task-template',
    props: ['list'],
    model: {
        prop: 'list',
        event: 'listchange'
    },
    computed: {
        listLocal: {
            get: function() {
                return this.list
            },
            set: function(value) {
                this.$emit('listchange', value)
            }
        }
    }
})  

모델 프로퍼티 정의 prop와 연관된 v-model및 이벤트의 변경에 출사한다. 그런 다음 다음과 같이 부모에서이 구성 요소를 호출 할 수 있습니다.

<Task v-model="parentList"></Task>

listLocal계산 재산권 부품 내에 간단하고 게터 세터 인터페이스를 제공한다 (전용 가변되는 것처럼 생각). 내에서 #task-template렌더링 할 수 listLocal있으며 반응 상태를 유지합니다 (즉, parentList변경하면 Task구성 요소 가 업데이트 됩니다). listLocalsetter (예 🙂 를 호출하여 음소거 할 수 this.listLocal = newList있으며 변경 사항이 부모에게 전달됩니다.

이 패턴의 장점 listLocalTask(의 v-model) 하위 구성 요소에 전달할 수 있으며 하위 구성 요소의 변경 사항이 최상위 구성 요소로 전파된다는 것입니다.

예를 들어, EditTask작업 데이터를 수정하기위한 별도의 구성 요소가 있다고 가정합니다. 동일 v-model하고 계산 된 속성 패턴 을 사용하여을 사용하여 listLocal구성 요소에 전달할 수 있습니다 v-model.

<script type="text/x-template" id="task-template">
    <div>
        <EditTask v-model="listLocal"></EditTask>
    </div>
</script>

만약 EditTask이 방출이 적절하게 호출 변화 set()listLocal최고 수준에 이벤트를 전파함으로써합니다. 마찬가지로 EditTask구성 요소는을 사용하여 다른 자식 구성 요소 (예 : 양식 요소)를 호출 할 수도 있습니다 v-model.


답변

Vue는 경고합니다. 컴포넌트에서 prop을 변경하지만 부모 컴포넌트가 다시 렌더링되면 “list”가 덮어 쓰여지고 모든 변경 사항을 잃게됩니다. 따라서 그렇게하는 것은 위험합니다.

대신 다음과 같이 계산 된 속성을 사용하십시오.

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    computed: {
        listJson: function(){
            return JSON.parse(this.list);
        }
    }
});


답변

Lodash를 사용하는 경우 소품을 반환하기 전에 복제 할 수 있습니다. 이 패턴은 부모와 자식 모두에서 해당 소품을 수정하는 경우에 유용합니다.

컴포넌트 그리드 에 소품 목록 이 있다고 가정 해 봅시다. .

부모 구성 요소에서

<grid :list.sync="list"></grid>

하위 구성 요소

props: ['list'],
methods:{
    doSomethingOnClick(entry){
        let modifiedList = _.clone(this.list)
        modifiedList = _.uniq(modifiedList) // Removes duplicates
        this.$emit('update:list', modifiedList)
    }
}


답변

프로포즈 다운, 이벤트 업. Vue의 패턴입니다. 요점은 부모로부터 전달되는 소품을 변경하려고 할 때입니다. 작동하지 않으며 부모 구성 요소가 반복적으로 덮어 씁니다. 하위 구성 요소는 sth를 수행하도록 상위 구성 요소에 알리는 이벤트 만 생성 할 수 있습니다. 이 제한이 마음에 들지 않으면 VUEX를 사용할 수 있습니다 (실제로이 패턴은 복잡한 구성 요소 구조를 빨아들입니다 .VUEX를 사용해야합니다!)


답변

하위 구성 요소의 소품 값을 변경해서는 안됩니다. 정말로 변경해야 할 경우 사용할 수 있습니다 .sync. 이처럼

<your-component :list.sync="list"></your-component>

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    created() {
        this.$emit('update:list', JSON.parse(this.list))
    }
});
new Vue({
    el: '.container'
})


답변

VueJs 2.0에 따르면 컴포넌트 내부의 prop을 변경해서는 안됩니다. 그들은 부모에 의해서만 변이됩니다. 따라서 이름이 다른 데이터에 변수를 정의하고 실제 소품을 보면서 업데이트해야합니다. 부모가 목록 소품을 변경 한 경우 구문 분석하여 mutableList에 할당 할 수 있습니다. 다음은 완벽한 솔루션입니다.

Vue.component('task', {
    template: ´<ul>
                  <li v-for="item in mutableList">
                      {{item.name}}
                  </li>
              </ul>´,
    props: ['list'],
    data: function () {
        return {
            mutableList = JSON.parse(this.list);
        }
    },
    watch:{
        list: function(){
            this.mutableList = JSON.parse(this.list);
        }
    }
});

mutableList를 사용하여 템플릿을 렌더링하므로 구성 요소에서 목록 소품을 안전하게 유지합니다.


댓글 달기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다