admin管理员组文章数量:1026205
We need to use $emit
to update the parent data in a vue ponent. This is what has been said everywhere, even vue documentation.
v-model
and .sync
both use $emit
to update, so we count them $emit
here
what I'm involved with is updating the parent data using reference
type passing
If we send an object or array as prop to the child ponent and change it in the child ponent, changes will be made to the parent data directly.
There are ponents that we always use in a specific ponent and we are not going to use them anywhere else. In fact, these ponents are mostly used to make the app codes more readable and to lighten the ponents of the app.
passing reference type values as prop to children for directly change them from children is much easier than passing values then handle emitted event. especially when there are more nested ponents
code readability is even easier when we use reference type to update parent.
For example, suppose we have grand-parent
, parent
and child
ponents. in parent
ponent we have a field that change first
property of grand-parent data and in child ponent we have another field that change second
property of grand-parent data
If we want to implement this using $emit
we have something like this : (we are not using .sync or v-model)
// grand-parent
<template>
<div>
<parent :fields="fields" @updateFields="fields = $event" >
</div>
</template>
<script>
import parent from "./parent"
export default {
ponents : {parent},
data(){
return {
fields : {
first : 'first-value',
second : 'second-value',
}
}
}
}
</script>
// parent
<template>
<div>
<input :value="fields.first" @input="updateFirstField" />
<child :fields="fields" @updateSecondField="updateSecondField" >
</div>
</template>
<script>
import child from "./child"
export default {
ponents : {child},
props : {
fields : Object,
},
methods : {
updateFirstField(event){
this.$emit('updateFields' , {...this.fields , first : event.target.value})
},
updateSecondField(value){
this.$emit('updateFields' , {...this.fields , second : value})
}
}
}
</script>
// child
<template>
<div>
<input :value="fields.first" @input="updateSecondField" />
</div>
</template>
<script>
export default {
props : {
fields : Object,
},
methods : {
updateFirstField(event){
this.$emit('updateSecondField' , event.target.value)
},
}
}
</script>
Yes, we can use .sync
to make it easier or pass just field that we need to child. but this is basic example and if we have more fields and also we use all fields in all ponent this is the way we do this.
same thing using reference type will be like this :
// grand-parent
<template>
<div>
<parent :fields="fields" >
</div>
</template>
<script>
import parent from "./parent"
export default {
ponents : {parent},
data(){
return {
fields : {
first : 'first-value',
second : 'second-value',
}
}
}
}
</script>
// parent
<template>
<div>
<input v-model="fields.first" />
<child :fields="fields" >
</div>
</template>
<script>
import child from "./child"
export default {
ponents : {child},
props : {
fields : Object,
}
}
</script>
// child
<template>
<div>
<input v-model="fields.second" />
</div>
</template>
<script>
export default {
props : {
fields : Object,
}
}
</script>
as you see using reference
type is much easier. even if there was more fields.
now my question :
- should we use reference type for updating parent data or this is bad approach ?
- even if we use a ponent always in the same parent again we should not use this method ?
- what is the reason that we should not use
reference
type to update parent? - if we should not use
reference
type why vue pass same object to children and not clone them before passing ? (maybe for better performance ?)
We need to use $emit
to update the parent data in a vue ponent. This is what has been said everywhere, even vue documentation.
v-model
and .sync
both use $emit
to update, so we count them $emit
here
what I'm involved with is updating the parent data using reference
type passing
If we send an object or array as prop to the child ponent and change it in the child ponent, changes will be made to the parent data directly.
There are ponents that we always use in a specific ponent and we are not going to use them anywhere else. In fact, these ponents are mostly used to make the app codes more readable and to lighten the ponents of the app.
passing reference type values as prop to children for directly change them from children is much easier than passing values then handle emitted event. especially when there are more nested ponents
code readability is even easier when we use reference type to update parent.
For example, suppose we have grand-parent
, parent
and child
ponents. in parent
ponent we have a field that change first
property of grand-parent data and in child ponent we have another field that change second
property of grand-parent data
If we want to implement this using $emit
we have something like this : (we are not using .sync or v-model)
// grand-parent
<template>
<div>
<parent :fields="fields" @updateFields="fields = $event" >
</div>
</template>
<script>
import parent from "./parent"
export default {
ponents : {parent},
data(){
return {
fields : {
first : 'first-value',
second : 'second-value',
}
}
}
}
</script>
// parent
<template>
<div>
<input :value="fields.first" @input="updateFirstField" />
<child :fields="fields" @updateSecondField="updateSecondField" >
</div>
</template>
<script>
import child from "./child"
export default {
ponents : {child},
props : {
fields : Object,
},
methods : {
updateFirstField(event){
this.$emit('updateFields' , {...this.fields , first : event.target.value})
},
updateSecondField(value){
this.$emit('updateFields' , {...this.fields , second : value})
}
}
}
</script>
// child
<template>
<div>
<input :value="fields.first" @input="updateSecondField" />
</div>
</template>
<script>
export default {
props : {
fields : Object,
},
methods : {
updateFirstField(event){
this.$emit('updateSecondField' , event.target.value)
},
}
}
</script>
Yes, we can use .sync
to make it easier or pass just field that we need to child. but this is basic example and if we have more fields and also we use all fields in all ponent this is the way we do this.
same thing using reference type will be like this :
// grand-parent
<template>
<div>
<parent :fields="fields" >
</div>
</template>
<script>
import parent from "./parent"
export default {
ponents : {parent},
data(){
return {
fields : {
first : 'first-value',
second : 'second-value',
}
}
}
}
</script>
// parent
<template>
<div>
<input v-model="fields.first" />
<child :fields="fields" >
</div>
</template>
<script>
import child from "./child"
export default {
ponents : {child},
props : {
fields : Object,
}
}
</script>
// child
<template>
<div>
<input v-model="fields.second" />
</div>
</template>
<script>
export default {
props : {
fields : Object,
}
}
</script>
as you see using reference
type is much easier. even if there was more fields.
now my question :
- should we use reference type for updating parent data or this is bad approach ?
- even if we use a ponent always in the same parent again we should not use this method ?
- what is the reason that we should not use
reference
type to update parent? - if we should not use
reference
type why vue pass same object to children and not clone them before passing ? (maybe for better performance ?)
2 Answers
Reset to default 3The "always use $emit
" rule isn't set in stone. There are pros and cons of either approach; you should do whatever makes your code easy to maintain and reason about.
For the situation you described, I think you have justified mutating the data directly.
When you have a single object with lots of properties and each property can be modified by a child ponent, then having the child ponent mutate each property itself is fine.
What would the alternative be? Emitting an event for each property update? Or emitting a single input
event containing a copy of the object with a single property changed? That approach would result in lots of memory allocations (think of typing in a text field emitting a cloned object for each keypress). Having said that, though, some libraries are designed for this exact purpose and work pretty well (like Immutable.js).
For simple ponents that manage only small data like a textbox with a single string value, you should definitely use $emit
. For more plex ponents with lots of data then sometimes it makes sense for the child ponent to share or own the data it is given. It bees a part of the child ponent's contract that it will mutate the data in certain circumstances and in some particular way.
what is the reason that we should not use reference type to update parent?
- The parent "owns" the data and it knows that nobody but itself will mutate it. No surprises.
- The parent gets to decide whether or not to accept the mutation, and can even modify it on-the-fly.
- You don't need a watcher to know when the data is changed.
- The parent knows how the data is changed and what caused the change. Imagine there are multiple ways that the data can be mutated. The parent can easily know which mutation originated from a child ponent. If external code (i.e. inside a child ponent) can mutate the data at any time and for any reason, then it bees much more difficult for the parent to know what caused the data to change (who changed it and why?).
if we should not use reference type why vue pass same object to children and not clone them before passing ? (maybe for better performance ?)
Well yes, for performance, but also many other reasons such as:
- Cloning is non-trivial (Shallow? Deep? Should the prototype be copied too? Does it even make sense to clone the object? Is it a singleton?).
- Cloning is expensive memory- and CPU-wise.
- If it were cloned then doing what you describe here would be impossible. It would be silly to impose such a restrictive rule.
@Vue Detailed usage of $refs, $emit, $on:
$refs - parent ponent calls the methods of the child ponent. You can pass data.
$emit - child ponents call methods of the parent ponent and pass data.
$on - sibling ponents pass data to each other.
We need to use $emit
to update the parent data in a vue ponent. This is what has been said everywhere, even vue documentation.
v-model
and .sync
both use $emit
to update, so we count them $emit
here
what I'm involved with is updating the parent data using reference
type passing
If we send an object or array as prop to the child ponent and change it in the child ponent, changes will be made to the parent data directly.
There are ponents that we always use in a specific ponent and we are not going to use them anywhere else. In fact, these ponents are mostly used to make the app codes more readable and to lighten the ponents of the app.
passing reference type values as prop to children for directly change them from children is much easier than passing values then handle emitted event. especially when there are more nested ponents
code readability is even easier when we use reference type to update parent.
For example, suppose we have grand-parent
, parent
and child
ponents. in parent
ponent we have a field that change first
property of grand-parent data and in child ponent we have another field that change second
property of grand-parent data
If we want to implement this using $emit
we have something like this : (we are not using .sync or v-model)
// grand-parent
<template>
<div>
<parent :fields="fields" @updateFields="fields = $event" >
</div>
</template>
<script>
import parent from "./parent"
export default {
ponents : {parent},
data(){
return {
fields : {
first : 'first-value',
second : 'second-value',
}
}
}
}
</script>
// parent
<template>
<div>
<input :value="fields.first" @input="updateFirstField" />
<child :fields="fields" @updateSecondField="updateSecondField" >
</div>
</template>
<script>
import child from "./child"
export default {
ponents : {child},
props : {
fields : Object,
},
methods : {
updateFirstField(event){
this.$emit('updateFields' , {...this.fields , first : event.target.value})
},
updateSecondField(value){
this.$emit('updateFields' , {...this.fields , second : value})
}
}
}
</script>
// child
<template>
<div>
<input :value="fields.first" @input="updateSecondField" />
</div>
</template>
<script>
export default {
props : {
fields : Object,
},
methods : {
updateFirstField(event){
this.$emit('updateSecondField' , event.target.value)
},
}
}
</script>
Yes, we can use .sync
to make it easier or pass just field that we need to child. but this is basic example and if we have more fields and also we use all fields in all ponent this is the way we do this.
same thing using reference type will be like this :
// grand-parent
<template>
<div>
<parent :fields="fields" >
</div>
</template>
<script>
import parent from "./parent"
export default {
ponents : {parent},
data(){
return {
fields : {
first : 'first-value',
second : 'second-value',
}
}
}
}
</script>
// parent
<template>
<div>
<input v-model="fields.first" />
<child :fields="fields" >
</div>
</template>
<script>
import child from "./child"
export default {
ponents : {child},
props : {
fields : Object,
}
}
</script>
// child
<template>
<div>
<input v-model="fields.second" />
</div>
</template>
<script>
export default {
props : {
fields : Object,
}
}
</script>
as you see using reference
type is much easier. even if there was more fields.
now my question :
- should we use reference type for updating parent data or this is bad approach ?
- even if we use a ponent always in the same parent again we should not use this method ?
- what is the reason that we should not use
reference
type to update parent? - if we should not use
reference
type why vue pass same object to children and not clone them before passing ? (maybe for better performance ?)
We need to use $emit
to update the parent data in a vue ponent. This is what has been said everywhere, even vue documentation.
v-model
and .sync
both use $emit
to update, so we count them $emit
here
what I'm involved with is updating the parent data using reference
type passing
If we send an object or array as prop to the child ponent and change it in the child ponent, changes will be made to the parent data directly.
There are ponents that we always use in a specific ponent and we are not going to use them anywhere else. In fact, these ponents are mostly used to make the app codes more readable and to lighten the ponents of the app.
passing reference type values as prop to children for directly change them from children is much easier than passing values then handle emitted event. especially when there are more nested ponents
code readability is even easier when we use reference type to update parent.
For example, suppose we have grand-parent
, parent
and child
ponents. in parent
ponent we have a field that change first
property of grand-parent data and in child ponent we have another field that change second
property of grand-parent data
If we want to implement this using $emit
we have something like this : (we are not using .sync or v-model)
// grand-parent
<template>
<div>
<parent :fields="fields" @updateFields="fields = $event" >
</div>
</template>
<script>
import parent from "./parent"
export default {
ponents : {parent},
data(){
return {
fields : {
first : 'first-value',
second : 'second-value',
}
}
}
}
</script>
// parent
<template>
<div>
<input :value="fields.first" @input="updateFirstField" />
<child :fields="fields" @updateSecondField="updateSecondField" >
</div>
</template>
<script>
import child from "./child"
export default {
ponents : {child},
props : {
fields : Object,
},
methods : {
updateFirstField(event){
this.$emit('updateFields' , {...this.fields , first : event.target.value})
},
updateSecondField(value){
this.$emit('updateFields' , {...this.fields , second : value})
}
}
}
</script>
// child
<template>
<div>
<input :value="fields.first" @input="updateSecondField" />
</div>
</template>
<script>
export default {
props : {
fields : Object,
},
methods : {
updateFirstField(event){
this.$emit('updateSecondField' , event.target.value)
},
}
}
</script>
Yes, we can use .sync
to make it easier or pass just field that we need to child. but this is basic example and if we have more fields and also we use all fields in all ponent this is the way we do this.
same thing using reference type will be like this :
// grand-parent
<template>
<div>
<parent :fields="fields" >
</div>
</template>
<script>
import parent from "./parent"
export default {
ponents : {parent},
data(){
return {
fields : {
first : 'first-value',
second : 'second-value',
}
}
}
}
</script>
// parent
<template>
<div>
<input v-model="fields.first" />
<child :fields="fields" >
</div>
</template>
<script>
import child from "./child"
export default {
ponents : {child},
props : {
fields : Object,
}
}
</script>
// child
<template>
<div>
<input v-model="fields.second" />
</div>
</template>
<script>
export default {
props : {
fields : Object,
}
}
</script>
as you see using reference
type is much easier. even if there was more fields.
now my question :
- should we use reference type for updating parent data or this is bad approach ?
- even if we use a ponent always in the same parent again we should not use this method ?
- what is the reason that we should not use
reference
type to update parent? - if we should not use
reference
type why vue pass same object to children and not clone them before passing ? (maybe for better performance ?)
2 Answers
Reset to default 3The "always use $emit
" rule isn't set in stone. There are pros and cons of either approach; you should do whatever makes your code easy to maintain and reason about.
For the situation you described, I think you have justified mutating the data directly.
When you have a single object with lots of properties and each property can be modified by a child ponent, then having the child ponent mutate each property itself is fine.
What would the alternative be? Emitting an event for each property update? Or emitting a single input
event containing a copy of the object with a single property changed? That approach would result in lots of memory allocations (think of typing in a text field emitting a cloned object for each keypress). Having said that, though, some libraries are designed for this exact purpose and work pretty well (like Immutable.js).
For simple ponents that manage only small data like a textbox with a single string value, you should definitely use $emit
. For more plex ponents with lots of data then sometimes it makes sense for the child ponent to share or own the data it is given. It bees a part of the child ponent's contract that it will mutate the data in certain circumstances and in some particular way.
what is the reason that we should not use reference type to update parent?
- The parent "owns" the data and it knows that nobody but itself will mutate it. No surprises.
- The parent gets to decide whether or not to accept the mutation, and can even modify it on-the-fly.
- You don't need a watcher to know when the data is changed.
- The parent knows how the data is changed and what caused the change. Imagine there are multiple ways that the data can be mutated. The parent can easily know which mutation originated from a child ponent. If external code (i.e. inside a child ponent) can mutate the data at any time and for any reason, then it bees much more difficult for the parent to know what caused the data to change (who changed it and why?).
if we should not use reference type why vue pass same object to children and not clone them before passing ? (maybe for better performance ?)
Well yes, for performance, but also many other reasons such as:
- Cloning is non-trivial (Shallow? Deep? Should the prototype be copied too? Does it even make sense to clone the object? Is it a singleton?).
- Cloning is expensive memory- and CPU-wise.
- If it were cloned then doing what you describe here would be impossible. It would be silly to impose such a restrictive rule.
@Vue Detailed usage of $refs, $emit, $on:
$refs - parent ponent calls the methods of the child ponent. You can pass data.
$emit - child ponents call methods of the parent ponent and pass data.
$on - sibling ponents pass data to each other.
本文标签: javascriptvueemit vs reference for updating parent dataStack Overflow
版权声明:本文标题:javascript - vue - $emit vs. reference for updating parent data - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745629230a2160057.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论