vue3 reactive array push 值后 为什么还是会响应源值?

预览:https://stackblitz.com/edit/vitejs-vite-wnwsdn?embed=1&file=s...

<template>

<div class="w-full">

<ul class="list-none w-full flex flex-col gap-2 mb-4 p-0">

<li v-for="(condition, index) of conditions" :key="index">

<ul

class="

list-none

w-full

rounded

border border-solid border-gray-200

@hover:border-gray-300

flex flex-row

justify-around

items-center

p-0

gap-2

"

>

<li class="flex-1 flex-inline items-center justify-center">

{{ resolveArray(condition.field, fields) }}

</li>

<li class="flex-1 flex-inline items-center justify-center">

{{ resolveArray(condition.symbol, symbols) }}

</li>

<li class="flex-1 flex-inline items-center justify-center">

{{ condition.value }}

</li>

<li class="flex-0 flex-inline items-center justify-center">

<el-button text bg @click.prevent="onCondDel(index)"> X </el-button>

</li>

</ul>

</li>

</ul>

<el-form

ref="condRef"

:model="cond"

label-position="top"

hide-required-asterisk

:rules="rules"

>

<el-row :gutter="10">

<el-col :span="6">

<el-form-item label="字段" prop="field">

<el-select v-model="cond.field" class="w-full">

<el-option

v-for="item of fields"

:label="item.label"

:value="item.value"

></el-option>

</el-select>

</el-form-item>

</el-col>

<el-col :span="4">

<el-form-item label="运算符" prop="symbol">

<el-select v-model="cond.symbol">

<el-option

v-for="item of symbols"

:label="item.label"

:value="item.value"

></el-option>

</el-select>

</el-form-item>

</el-col>

<el-col :span="12">

<el-form-item label="值" prop="value">

<el-input v-model="cond.value" placeholder="输入值" clearable />

</el-form-item>

</el-col>

<el-col :span="2">

<el-form-item label="操作">

<el-button plain @click="onCondAdd()"> + </el-button>

</el-form-item>

</el-col>

</el-row>

</el-form>

</div>

</template>

<script setup>

import { ref, reactive, computed, onMounted, watch } from 'vue';

const props = defineProps({

modelValue: {},

});

const emit = defineEmits(['update:modelValue']);

const rules = reactive({

field: [{ required: true, message: '字段必须选择' }],

symbol: [{ required: true, message: '运算符必须选择' }],

value: [{ required: true, message: '值不能为空' }],

});

const initialCond = reactive({

field: '',

symbol: '',

value: '',

});

const cond = reactive({ ...initialCond });

const conditions = reactive([]);

const condRef = ref(null);

const symbols = reactive([

{ label: '等于', value: 'eq' },

{ label: '不等于', value: 'ne' },

{ label: '包含', value: 'in' },

{ label: '不包含', value: 'ni' },

{ label: '大于', value: 'gt' },

{ label: '小于', value: 'lt' },

{ label: '大于等于', value: 'gte' },

{ label: '小于等于', value: 'lte' },

]);

const fields = reactive([

{ label: '姓名', value: 'fullname' },

{ label: '性别', value: 'gender' },

{ label: '手机', value: 'phone' },

{ label: '生日', value: 'birthday' },

{ label: '身份证', value: 'idcard' },

{ label: '年龄', value: 'age' },

]);

const onCondAdd = () => {

if (!condRef.value) return;

condRef.value.validate((valid) => {

if (valid) {

conditions.push(cond);

} else {

return;

}

});

};

const onCondDel = (index) => {

if (index !== -1) {

return conditions.splice(index, 1);

}

};

const resolveArray = (value, array) => {

if (!value) return;

const element = array.find((element) => element.value == value);

return `${element.label} ( ${element.value} )`;

};

</script>

<style scoped lang="scss">

.el-form--inline .el-form-item {

margin-right: 0;

}

</style>


回答:

cond 是一个对象,push 进去了,两边还是同一个对象,所以会同步更新。

切断引用关系就好了


内部是非引用类型,可以浅拷贝一下

  1. 比如上面的解构 {...cond}
  2. 还有 assign

也可以深拷贝,借用一些库

  1. JSON.parse(JSON.stringify)
  2. lodash.cloneDeep
本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。


回答:

这里应改这样写

...

const onCondAdd = () => {

if (!condRef.value) return;

condRef.value.validate((valid) => {

if (valid) {

conditions.push({...cond});

} else {

return;

}

});

};

...

以上是 vue3 reactive array push 值后 为什么还是会响应源值? 的全部内容, 来源链接: utcz.com/p/933936.html

回到顶部