英文:
Using Vue3 to implement an efficient way to reset specific value in array?
问题
如何使用Vue3来实现对数组中特定值进行高效重置?我尝试复制原始数据进行临时存储,然后使其不可变并重置值,或者使用其他方法来实现这个目标?
<script setup>
import { ref, computed, toRaw, watch } from 'vue';
const selected = ref(null);
const data = ref([{
id: 1,
label: 'A',
value: 'A',
name: 'Student A'
}, {
id: 2,
label: 'B',
value: 'B',
name: 'Student B'
}, {
id: 3,
label: 'C',
value: 'C',
name: 'Student C'
}]);
const initData = structuredClone(toRaw(data.value.reduce((acc, item) => {
acc[item.id] = item.value;
return acc;
}, {})));
watch(selected, (v) => {
if (v === null) {
data.value.forEach(item => item.value = initData[item.id]);
} else {
data.value.forEach(item => item.value = v);
}
});
</script>
<template>
<div>
<select v-model="selected">
<option :value="null">初始值</option>
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
<template v-for="(item, idx) in data" :key="idx">
<div style="display:flex ; align-items: center;margin-bottom: 16px;">
<div style="margin-right:16px;"> Name:{{ item.name }}</div>
<select :value="item.value" @change="updateValue(item.id, $event.target.value)">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
</div>
</template>
</div>
</template>
英文:
How to Using Vue3 to implement an efficient way to reset specific value in array? I am trying to copy origin data for temporary storage, then make it immutable and reset value, or other methods to implement this?
<script setup>
import { ref, computed, toRaw, watch } from 'vue';
const selected = ref(null)
const data = ref([{
id: 1,
label: 'A',
value: 'A',
name: 'Student A'
}, {
id: 2,
label: 'B',
value: 'B',
name: 'Student B'
}, {
id: 3,
label: 'C',
value: 'C',
name: 'Student C'
}])
const initData = structuredClone(toRaw(data.value.reduce((acc, item) => {
acc[item.id] = item.value;
return acc;
}, {})))
watch(selected, (v) => {
if (v === null) {
data.value.forEach(item => item.value = initData[item.id])
} else {
data.value.forEach(item => item.value = v)
}
})
</script>
<template>
<div>
<select v-model="selected">
<option :value="null">Init Value</option>
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
<template v-for="(item, idx) in data" :key="idx">
<div style="display:flex ; align-items: center;margin-bottom: 16px;">
<div style="margin-right:16px;"> Name:{{ item.name }}</div>
<select :value="item.value" @change="updateValue(item.id, $event.target.value)">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
</div>
</template>
</div>
</template>
答案1
得分: 0
你的措辞不太清晰,但我认为你在问你的工作代码是否可以改进?
如果是这样,我的第一个建议是用map
替换reduce
。map
用于转换数组的每个元素,而reduce
通常用于将数组的所有值合并为单个值。你正在进行映射操作,但错误地使用了reduce
函数来实现它。toRaw
和structuredClone
也是完全不必要的。
第二个建议是用函数替换watch
。对事件的响应,尤其是用户交互,适合使用函数。这不是watch
的用例,watch
通常用于对属性变化或异步操作结果的响应(一般规则是,只有在不能用函数或计算属性实现所需功能时,才使用watch
)。
const initData = data.value.map(item => item.value)
const valueSelected = () => {
if (selected.value === null) {
data.value.forEach((item, i) => item.value = initData[i])
} else {
data.value.forEach(item => item.value = selected.value)
}
}
<select v-model="selected" @change="valueSelected">
英文:
Your wording is not clear, but I think you're asking if your working code could be made better?
If so, my first advice would be to replace the reduce
with map
. Map is for transforming each element of an array, while reduce is usually meant to merge all values of an array into a single value. What you are doing is mapping but incorrectly using the reduce function to do it. toRaw
and structuredClone
are also completely unnecessary.
Second would be to replace watch
with a function. Reacting to an events, especially user interactions, is what functions are good for. It is not the use case for watch
, which is usually meant for reacting to prop changes or reacting to the result of asynchronous operations (a general rule is, only if you can't do what you want with a function or computed property, then use watch).
const initData = data.value.map(item => item.value)
const valueSelected = () => {
if (selected.value === null) {
data.value.forEach((item, i) => item.value = initData[i])
} else {
data.value.forEach(item => item.value = selected.value)
}
}
<select v-model="selected" @change="valueSelected">
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论