Vue.js 3 - 如果 props 带有父组件中的数组成员,则在子组件中观看 props 不起作用
Vue.js 3 - watching props in child component does not work if props comes with a member of array in parent component
我正在使用Vue.js 3.我遇到了问题,让我们先看看代码。
代码
ChildComponent.vue
<template>
<div>
{{ modelValue }}
<input v-model="resultString"/>
<button @click="showModelValue">show model value</button>
</div>
</template>
<script lang="ts">
import {defineComponent, PropType, ref, watch} from "vue";
export default defineComponent({
props: {
modelValue: {
type: Object as PropType<number>,
required: true,
}
},
emits:['update:modelValue'],
setup(props) {
const resultString = ref<string>("");
watch(() => props.modelValue, (newVal:number, oldVal:number) => {
if (newVal % 2 == 0) {
resultString.value = 'even';
} else {
resultString.value = 'odd';
}
}, {deep: true});
const showModelValue = () => {
console.log(props.modelValue);
}
return { resultString, showModelValue }
}
})
</script>
<style scoped>
</style>
ParentComponent.vue
<template>
<div class="main-container">
<child-component v-model="test1" />
<button @click="increaseTest1">increase test1</button>
<hr/>
Cannot use v-model within v-for!
<!--
<div v-for="(testNum, index) in test2">
<child-component v-model="testNum" /> <button @click="increaseTest2(index)">increase test2</button>
</div>
-->
<hr/>
<div v-for="(testNumWrapper, index) in test3">
<child-component v-model="testNumWrapper.val" /> <button @click="increaseTest3(index)">increase test3</button>
</div>
</div>
</template>
<script lang="ts">
import {defineComponent, onMounted, ref} from "vue";
import ChildComponent from "@/main/components/pc/ChildComponent.vue";
export default defineComponent({
components: {ChildComponent},
setup() {
const test1 = ref<number>(1);
const increaseTest1 = () => test1.value++;
/*
const test2 = ref<number[]>([3,1,4,1,5,9]);
const increaseTest2 = (index:number) => test2.value[index]++;
const updateTest2 = (e:any) => {
console.log(e);
};
*/
const test3 = ref<{val:number}[]>([]);
const increaseTest3 = (index:number) => test3.value[index].val++;
onMounted(() => {
// This triggers watch() in childComponent.
test1.value = 4;
// But these do NOT trigger watch() in childComponent.
test3.value = [{val: 3},{val: 1},{val: 4},{val: 1},{val: 5},{val: 9}];
});
return {
test1, increaseTest1,
//test2, increaseTest2, updateTest2,
test3, increaseTest3,
}
}
});
</script>
<style scoped>
</style>
以上代码是为分享我的问题而修改的,让我解释一下。
ChildComponent 自动决定 modelValue 的值是奇数还是偶数。
父组件...
- 绑定一个 ref 变量,
test1
到 ChildComponent,
- 尝试将 ref 数组变量
test2
的每个原始类型成员绑定到 ChildComponents 但这没有被编译,因为 v-model 不能在 v-for 中使用,所以我注释掉了代码行和尝试下一个测试,
- 将 ref 数组变量的每个非原始类型成员
test3
绑定到 ChildComponent。
并启动onMounted()
中的变量。
但是,我发现 ChildCompoent 中的 watch()
适用于 test1
但不适用于 test3
。当我将值推入 test3
或从 test3
中删除值时,watch()
也不适用于 test3
。 (当我点击增加按钮时它起作用了。)
请告诉我如何触发 test3
的 watch()
函数。
谢谢。
当然,子组件中的 watch
不是通过从数组中推入或删除元素来触发的。子组件不是在监视整个数组,而是在监视单个元素(它是 val
属性)。
如果将新元素推入数组,则该元素的子组件尚不存在。如果删除一个元素,为该元素呈现的子组件将立即被销毁。唯一可以触发 watch
的确实是 val
属性...
的突变
test2
的问题在于 testNum
是局部临时变量 - 而不是 v-model="testNum"
,请使用 v-model="test2[index]"
无论如何,你的 ChildComponent.vue
根本不需要 watch
。只需使用 computed
:
const resultString = computed(() => props.modelValue % 2 === 0 ? 'even' : 'odd')
...顺便说一句,您应该将 key
与 v-for
- docs
一起使用
我正在使用Vue.js 3.我遇到了问题,让我们先看看代码。
代码
ChildComponent.vue
<template>
<div>
{{ modelValue }}
<input v-model="resultString"/>
<button @click="showModelValue">show model value</button>
</div>
</template>
<script lang="ts">
import {defineComponent, PropType, ref, watch} from "vue";
export default defineComponent({
props: {
modelValue: {
type: Object as PropType<number>,
required: true,
}
},
emits:['update:modelValue'],
setup(props) {
const resultString = ref<string>("");
watch(() => props.modelValue, (newVal:number, oldVal:number) => {
if (newVal % 2 == 0) {
resultString.value = 'even';
} else {
resultString.value = 'odd';
}
}, {deep: true});
const showModelValue = () => {
console.log(props.modelValue);
}
return { resultString, showModelValue }
}
})
</script>
<style scoped>
</style>
ParentComponent.vue
<template>
<div class="main-container">
<child-component v-model="test1" />
<button @click="increaseTest1">increase test1</button>
<hr/>
Cannot use v-model within v-for!
<!--
<div v-for="(testNum, index) in test2">
<child-component v-model="testNum" /> <button @click="increaseTest2(index)">increase test2</button>
</div>
-->
<hr/>
<div v-for="(testNumWrapper, index) in test3">
<child-component v-model="testNumWrapper.val" /> <button @click="increaseTest3(index)">increase test3</button>
</div>
</div>
</template>
<script lang="ts">
import {defineComponent, onMounted, ref} from "vue";
import ChildComponent from "@/main/components/pc/ChildComponent.vue";
export default defineComponent({
components: {ChildComponent},
setup() {
const test1 = ref<number>(1);
const increaseTest1 = () => test1.value++;
/*
const test2 = ref<number[]>([3,1,4,1,5,9]);
const increaseTest2 = (index:number) => test2.value[index]++;
const updateTest2 = (e:any) => {
console.log(e);
};
*/
const test3 = ref<{val:number}[]>([]);
const increaseTest3 = (index:number) => test3.value[index].val++;
onMounted(() => {
// This triggers watch() in childComponent.
test1.value = 4;
// But these do NOT trigger watch() in childComponent.
test3.value = [{val: 3},{val: 1},{val: 4},{val: 1},{val: 5},{val: 9}];
});
return {
test1, increaseTest1,
//test2, increaseTest2, updateTest2,
test3, increaseTest3,
}
}
});
</script>
<style scoped>
</style>
以上代码是为分享我的问题而修改的,让我解释一下。
ChildComponent 自动决定 modelValue 的值是奇数还是偶数。
父组件...
- 绑定一个 ref 变量,
test1
到 ChildComponent, - 尝试将 ref 数组变量
test2
的每个原始类型成员绑定到 ChildComponents 但这没有被编译,因为 v-model 不能在 v-for 中使用,所以我注释掉了代码行和尝试下一个测试, - 将 ref 数组变量的每个非原始类型成员
test3
绑定到 ChildComponent。
并启动onMounted()
中的变量。
但是,我发现 ChildCompoent 中的 watch()
适用于 test1
但不适用于 test3
。当我将值推入 test3
或从 test3
中删除值时,watch()
也不适用于 test3
。 (当我点击增加按钮时它起作用了。)
请告诉我如何触发 test3
的 watch()
函数。
谢谢。
当然,子组件中的 watch
不是通过从数组中推入或删除元素来触发的。子组件不是在监视整个数组,而是在监视单个元素(它是 val
属性)。
如果将新元素推入数组,则该元素的子组件尚不存在。如果删除一个元素,为该元素呈现的子组件将立即被销毁。唯一可以触发 watch
的确实是 val
属性...
test2
的问题在于 testNum
是局部临时变量 - 而不是 v-model="testNum"
,请使用 v-model="test2[index]"
无论如何,你的 ChildComponent.vue
根本不需要 watch
。只需使用 computed
:
const resultString = computed(() => props.modelValue % 2 === 0 ? 'even' : 'odd')
...顺便说一句,您应该将 key
与 v-for
- docs