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
, 즉 :
data: function () { return { list: JSON.parse(this.list) } // WRONG!!
2 주 : 이후 나는 약간의 혼동이 느낌 에 대한 props
과 반응성 , 나는에보고해야 할 제안 이 스레드를
Vue는 경고합니다. 구성 요소의 소품을 변경하지만 부모 구성 요소가 다시 렌더링되면 "목록"을 덮어 쓰고 모든 변경 사항을 잃게됩니다. 따라서 그렇게하는 것은 위험합니다.
대신 다음과 같이 계산 된 속성을 사용하십시오.
Vue.component('task', {
template: '#task-template',
props: ['list'],
computed: {
listJson: function(){
return JSON.parse(this.list);
}
}
});
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
구성 요소 가 업데이트 됩니다). listLocal
setter (예 :) 를 호출하여 음소거 할 수 this.listLocal = newList
있으며 변경 사항이 부모에게 전달됩니다.
이 패턴의 장점 listLocal
은 Task
(의 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
.
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를 사용하여 템플릿을 렌더링하므로 구성 요소에서 목록 소품을 안전하게 유지합니다.
구성 요소에서 소품을 직접 변경하지 마십시오. 변경 해야하는 경우 다음과 같이 새 속성을 설정하십시오.
data () {
return () {
listClone: this.list
}
}
그리고 listClone의 값을 변경하십시오.
나는 또한이 문제에 직면했다. 경고는 내가 사용 후 사라 $on
와 $emit
. 사용 $on
과 비슷 $emit
하며 자식 구성 요소에서 부모 구성 요소로 데이터를 보내는 것이 좋습니다.
소품을 변경하려면 object를 사용하십시오.
<component :model="global.price"></component>
구성 요소:
props: ['model'],
methods: {
changeValue: function() {
this.model.value = "new value";
}
}
이와 같은 계산 방법을 추가해야합니다
component.vue
props: ['list'],
computed: {
listJson: function(){
return JSON.parse(this.list);
}
}
https://vuejs.org/v2/guide/components.html 에 따르면 단방향 데이터 흐름, 구성 요소는 단방향 데이터 흐름을 따르고 모든 소품은 자식 속성과 부모 사이의 단방향 바인딩을 형성합니다. 하나는 부모 속성이 업데이트 될 때 자식으로 흐르지 만 다른 방향으로는 흐르지 않으므로 자식 구성 요소가 실수로 부모를 변경하지 못하게하여 앱의 데이터 흐름을 이해하기 어렵게 만들 수 있습니다.
또한 상위 컴포넌트가 업데이트 될 때마다 하위 컴포넌트의 모든 소품이 최신 값으로 새로 고쳐집니다. 즉, 하위 구성 요소 내에서 소품을 변경하려고 시도해서는 안됩니다. 당신이 .vue하면 콘솔에서 경고합니다.
일반적으로 소품을 변경하려는 유혹이있는 경우는 두 가지가 있습니다. 소품은 초기 값을 전달하는 데 사용됩니다. 자식 구성 요소는 나중에 로컬 데이터 속성으로 사용하려고합니다. 소품은 변형이 필요한 원시 값으로 전달됩니다. 이러한 사용 사례에 대한 정답은 다음과 같습니다. prop의 초기 값을 초기 값으로 사용하는 로컬 데이터 특성을 정의하십시오.
props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}
prop의 값에서 계산 된 계산 된 속성을 정의하십시오.
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
Vue.js 소품은 Vue의 안티 패턴으로 간주되므로 변경되지 않습니다.
필요한 접근 방식 은 목록 의 원래 prop 속성 을 참조하는 구성 요소에 데이터 속성을 만드는 것입니다.
props: ['list'],
data: () {
return {
parsedList: JSON.parse(this.list)
}
}
이제 구성 요소에 전달 된 목록 구조가 구성 요소의 data
속성을 통해 참조되고 변경 됩니다 :-)
If you wish to do more than just parse your list property then make use of the Vue component' computed
property. This allow you to make more in depth mutations to your props.
props: ['list'],
computed: {
filteredJSONList: () => {
let parsedList = JSON.parse(this.list)
let filteredList = parsedList.filter(listItem => listItem.active)
console.log(filteredList)
return filteredList
}
}
The example above parses your list prop and filters it down to only active list-tems, logs it out for schnitts and giggles and returns it.
note: both data
& computed
properties are referenced in the template the same e.g
<pre>{{parsedList}}</pre>
<pre>{{filteredJSONList}}</pre>
It can be easy to think that a computed
property (being a method) needs to be called... it doesn't
Vue.component('task', {
template: '#task-template',
props: ['list'],
computed: {
middleData() {
return this.list
}
},
watch: {
list(newVal, oldVal) {
console.log(newVal)
this.newList = newVal
}
},
data() {
return {
newList: {}
}
}
});
new Vue({
el: '.container'
})
Maybe this will meet your needs.
Adding to the best answer,
Vue.component('task', {
template: '#task-template',
props: ['list'],
data: function () {
return {
mutableList: JSON.parse(this.list);
}
}
});
Setting props by an array is meant for dev/prototyping, in production make sure to set prop types(https://vuejs.org/v2/guide/components-props.html) and set a default value in case the prop has not been populated by the parent, as so.
Vue.component('task', {
template: '#task-template',
props: {
list: {
type: String,
default() {
return '{}'
}
}
},
data: function () {
return {
mutableList: JSON.parse(this.list);
}
}
});
This way you atleast get an empty object in mutableList
instead of a JSON.parse error if it is undefined.
Vue.js considers this an anti-pattern. For example, declaring and setting some props like
this.propsVal = 'new Props Value'
So to solve this issue you have to take in a value from the props to the data or the computed property of a Vue instance, like this:
props: ['propsVal'],
data: function() {
return {
propVal: this.propsVal
};
},
methods: {
...
}
This will definitely work.
In addition to the above, for others having the following issue:
"If the props value is not required and thus not always returned, the passed data would return undefined
(instead of empty)". Which could mess <select>
default value, I solved it by checking if the value is set in beforeMount()
(and set it if not) as follows:
JS:
export default {
name: 'user_register',
data: () => ({
oldDobMonthMutated: this.oldDobMonth,
}),
props: [
'oldDobMonth',
'dobMonths', //Used for the select loop
],
beforeMount() {
if (!this.oldDobMonth) {
this.oldDobMonthMutated = '';
} else {
this.oldDobMonthMutated = this.oldDobMonth
}
}
}
Html:
<select v-model="oldDobMonthMutated" id="dob_months" name="dob_month">
<option selected="selected" disabled="disabled" hidden="hidden" value="">
Select Month
</option>
<option v-for="dobMonth in dobMonths"
:key="dobMonth.dob_month_slug"
:value="dobMonth.dob_month_slug">
{{ dobMonth.dob_month_name }}
</option>
</select>
I want to give this answer which helps avoid using a lot of code, watchers and computed properties. In some cases this can be a good solution:
Props are designed to provide one-way communication.
When you have a modal show/hide
button with a prop the best solution to me is to emit an event:
<button @click="$emit('close')">Close Modal</button>
Then add listener to modal element:
<modal :show="show" @close="show = false"></modal>
(In this case the prop show
is probably unnecessary because you can use an easy v-if="show"
directly on the base-modal)
참고URL : https://stackoverflow.com/questions/39868963/vue-2-mutating-props-vue-warn
'IT story' 카테고리의 다른 글
Python datetime-strptime을 사용하여 일, 월, 년을 얻은 후 고정 시간과 분 설정 (0) | 2020.06.22 |
---|---|
스칼라에서 'type'키워드의 기능 이해 (0) | 2020.06.22 |
Objective-C에 강력한 형식의 컬렉션이 있습니까? (0) | 2020.06.22 |
Azure 웹 사이트에 게시 한 후 파일 또는 어셈블리 System.Web.Http.WebHost를로드 할 수 없습니다. (0) | 2020.06.22 |
Windows에서 Python 패키지를 어떻게 설치합니까? (0) | 2020.06.22 |