Vue.js:改变对象作为道具传递是一种糟糕的技术吗?
Vue.js: Is changing objects passed as props a bad technique?
我注意到在 Vue 中你可以更改作为 Props 传递的对象字段,它会更改父级中的这些字段。
这是一种糟糕的技术吗?应该避免,还是可以使用?这种方法有什么注意事项?
示例:
Parent.vue:
<script setup>
import { reactive } from 'vue';
import ChildInput from "./Child.vue";
</script>
<script>
const myObj = reactive({'val':'Default text'});
</script>
<template>
<ChildInput :passedObj="myObj" />
<div>
It's a parent input:
<input v-model="myObj.val">
</div>
</template>
Child.vue:
<script setup>
const props = defineProps({
passedObj: {
type: Object,
required: true,
},
})
const dropValue = function() {
props.passedObj.val = "Changed text";
}
</script>
<template>
<div>
<label>
It's a child input:
<input v-model="passedObj.val">
<button @click="dropValue">Change text</button>
</label>
</div>
</template>
禁止浅 prop 突变,因为 props 对象是 read-only。
深层道具突变是 a bad practice that should be avoided。一个原因是这使数据流变得更加复杂且难以遵循,在这种情况下这是无意识地发生的,这解释了为什么这是一个问题。另一个可能的原因是性能可能会受到影响,因为这种情况不在常用范围内,尽管我目前还没有意识到这样的优化问题。
官方推荐在需要对props进行变异时使用v-model
two-way binding,这样变异发生在父组件中,需要调试时可以通过Vue事件追踪。当一个 prop 发生深度变异时,它会被克隆到一个子节点中并发送给父节点。
所以它 似乎是 一种不好的做法。如果有人需要用 Composition API.
编写的,我会留下一个我自己使用的替代方案
如果你只想修改 prop 的某些字段,你可以使用 setter 和 getter 的计算变量。像这样。
在parent中:
<script setup>
import { reactive } from "vue";
import InteractiveTable from "./Child.vue";
// Reactive object, which contains our data
const myObj = reactive({
data: [{name: "Sasha", address: "Middle of nowhere"}]
});
</script>
<InteractiveTable v-model="myObj" />
请记住,您可以传递多个 v-model 自定义标题:v-model:title
。您也可以自己监听事件。像那样:
<InteractiveTable :passedObj="myObj" @update:passedObj="(data) => <something>" />
在child中:
import { computed } from "vue";
// Defining our props
// For v-model default prop is 'modelValue'
// Don't forget to assign it to a variable
const props = defineProps({
modelValue: {
type: Object,
required: true,
},
});
// Emits must be assigned to a variable too
const emit = defineEmits([
"update:modelValue",
]);
// our computed variable, which we will use in JS instead of prop
const localData = computed({
get() {
// note that we can use object itself or any of its properties, 'data' in this case
return props.modelValue.data;
},
set(val) {
emit("update:modelValue.data", val);
},
});
现在你可以做:
const addRow = function (name, address) {
// You have to call this localData with .value
// In all other regards you can treat it as a normal variable
localData.value.push({
'name': name,
'address': address,
});
};
您可以阅读有关 computed
个变量的更多信息 here and about emit
here。
我是 Vue.js 的新手,所以如果您发现我的代码有问题,请在评论中通知我。
我注意到在 Vue 中你可以更改作为 Props 传递的对象字段,它会更改父级中的这些字段。
这是一种糟糕的技术吗?应该避免,还是可以使用?这种方法有什么注意事项?
示例:
Parent.vue:
<script setup>
import { reactive } from 'vue';
import ChildInput from "./Child.vue";
</script>
<script>
const myObj = reactive({'val':'Default text'});
</script>
<template>
<ChildInput :passedObj="myObj" />
<div>
It's a parent input:
<input v-model="myObj.val">
</div>
</template>
Child.vue:
<script setup>
const props = defineProps({
passedObj: {
type: Object,
required: true,
},
})
const dropValue = function() {
props.passedObj.val = "Changed text";
}
</script>
<template>
<div>
<label>
It's a child input:
<input v-model="passedObj.val">
<button @click="dropValue">Change text</button>
</label>
</div>
</template>
禁止浅 prop 突变,因为 props 对象是 read-only。
深层道具突变是 a bad practice that should be avoided。一个原因是这使数据流变得更加复杂且难以遵循,在这种情况下这是无意识地发生的,这解释了为什么这是一个问题。另一个可能的原因是性能可能会受到影响,因为这种情况不在常用范围内,尽管我目前还没有意识到这样的优化问题。
官方推荐在需要对props进行变异时使用v-model
two-way binding,这样变异发生在父组件中,需要调试时可以通过Vue事件追踪。当一个 prop 发生深度变异时,它会被克隆到一个子节点中并发送给父节点。
所以它 似乎是 一种不好的做法。如果有人需要用 Composition API.
编写的,我会留下一个我自己使用的替代方案如果你只想修改 prop 的某些字段,你可以使用 setter 和 getter 的计算变量。像这样。
在parent中:
<script setup>
import { reactive } from "vue";
import InteractiveTable from "./Child.vue";
// Reactive object, which contains our data
const myObj = reactive({
data: [{name: "Sasha", address: "Middle of nowhere"}]
});
</script>
<InteractiveTable v-model="myObj" />
请记住,您可以传递多个 v-model 自定义标题:v-model:title
。您也可以自己监听事件。像那样:
<InteractiveTable :passedObj="myObj" @update:passedObj="(data) => <something>" />
在child中:
import { computed } from "vue";
// Defining our props
// For v-model default prop is 'modelValue'
// Don't forget to assign it to a variable
const props = defineProps({
modelValue: {
type: Object,
required: true,
},
});
// Emits must be assigned to a variable too
const emit = defineEmits([
"update:modelValue",
]);
// our computed variable, which we will use in JS instead of prop
const localData = computed({
get() {
// note that we can use object itself or any of its properties, 'data' in this case
return props.modelValue.data;
},
set(val) {
emit("update:modelValue.data", val);
},
});
现在你可以做:
const addRow = function (name, address) {
// You have to call this localData with .value
// In all other regards you can treat it as a normal variable
localData.value.push({
'name': name,
'address': address,
});
};
您可以阅读有关 computed
个变量的更多信息 here and about emit
here。
我是 Vue.js 的新手,所以如果您发现我的代码有问题,请在评论中通知我。