今在开发一个循环增加select 的时候,出现了v-model绑定到相同对象,当一个select改变其他也会随之改变的问题
页面操作,1、选择其中一个select
2、当选择后发现上下两个select 也随之选中为了同样的值
Think think why … ,修改某一个select 其他两个也会同着更改!
来过过代码找找问题—//
html是这样的
<el-form-item
label="推送消息类型"
>
<div v-for="(hItem,index) in pushSecondTypeOfHour" :key="index" class="items-second-type">
<el-select v-model="hItem.hModelVal">
<el-option
v-for="item in hItem.houseList"
:key="item.value+'-h'"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-select v-model="hItem.tModelVal">
<el-option
v-for="item in hItem.temperList"
:key="item.value+'-t'"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-select v-model="hItem.maxModelVal">
<el-option
v-for="item in hItem.maxList"
:key="item.value+'-m'"
:label="item.label"
:value="item.value"
/>
</el-select>
<i v-show="pushSecondTypeOfHour.length>1&&index!==pushSecondTypeOfHour.length-1" class="el-icon-minus rec-second-msg" @click="redcSecondBtn" />
<i v-show="index===pushSecondTypeOfHour.length-1" class="el-icon-plus add-second-msg" @click="addSecondType" />
<span v-show="index===pushSecondTypeOfHour.length-1" class="add-second-msg-txt">添加类型1/3</span>
</div>
</el-form-item>
js是这样的
<script>
export default {
data(){
return{
pushSecondTypeOfHourOption: {
houseList: [
{ label: '1小时', value: 1 },
{ label: '3小时', value: 3 },
{ label: '6小时', value: 6 },
{ label: '12小时', value: 12 },
{ label: '24小时', value: 24 }
],
temperList: [
{ label: '降温', value: 1 },
{ label: '降水', value: 3 },
{ label: '风', value: 4 }
],
maxList: [
{ label: '最大值', value: 1 },
{ label: '最小值', value: 3 },
{ label: '平均值', value: 4 },
{ label: '累计值', value: 5 }
],
hModelVal: 1,
tModelVal: 1,
maxModelVal: 1
},
pushSecondTypeOfHour: []
}
},
created() {
this.pushSecondTypeOfHour.push(this.pushSecondTypeOfHourOption)
},
methods: {
// 增加消息类型
addSecondType() {
this.pushSecondTypeOfHour.push(this.pushSecondTypeOfHourOption)
console.log(this.pushSecondTypeOfHour)
},
// 删除
redcSecondBtn() {
this.pushSecondTypeOfHour.pop()
}
}
}
后来才发现原来是这里addSecondType()
方法直接用pushSecondTypeOfHour
push 了这个this.pushSecondTypeOfHourOption
对象
这就意味着,数组里所有元素的内存地址都指向了同一个pushSecondTypeOfHourOption
对象, 而后来的v-model
绑定自然也就在同一个对象上了,当改变时几个select 所选中的值都相同自然就不奇怪了
最后修改代码
1、修改pushSecondTypeOfHourOption 定义
将data中的pushSecondTypeOfHourOption 移动到 最外层,定义为一个常量
const TYPE_OPTIONS = {
houseList: [
{ label: '1小时', value: 1 },
{ label: '3小时', value: 3 },
{ label: '6小时', value: 6 },
{ label: '12小时', value: 12 },
{ label: '24小时', value: 24 }
],
temperList: [
{ label: '降温', value: 1 },
{ label: '降水', value: 3 },
{ label: '风', value: 4 }
],
maxList: [
{ label: '最大值', value: 1 },
{ label: '最小值', value: 3 },
{ label: '平均值', value: 4 },
{ label: '累计值', value: 5 }
],
hModelVal: 1,
tModelVal: 1,
maxModelVal: 1
}
export default {
// ........
2、再修改methods
created() {
// this.handlerFilter()
this.pushSecondTypeOfHour.push(TYPE_OPTIONS)
},
methods: {
// 增加消息类型
addSecondType() {
// 拷贝一份值
const typeOptions = Object.assign({}, TYPE_OPTIONS)
this.pushSecondTypeOfHour.push(typeOptions)
console.log(this.pushSecondTypeOfHour)
}
}
在addSecondType()
使用Object.assign()
进行对象拷贝,再将其添加到pushSecondTypeOfHour
数组中,确保数组元素不是同一个对象
ok 问题解决,没想还踩了个基础知识的坑
这里借用相关文章补补基础知识
JS中的基本类型和引用类型
基本类型:undefined、null、string、number、boolean、symbo(ES6)
普通基本类型:undefined、null、symbol(ES6)
特殊基本包装类型:string、number、boolean
引用类型:Object、Array、RegExp、Date、Function
区别:引用类型值可添加属性和方法,而基本类型则不可以。
1、基本类型
- 基本类型的变量是存放在栈内存(Stack)里的
- 基本数据类型的值是按值访问的
- 基本类型的值是不可变的
- 基本类型的比较是它们的值的比较
2、引用类型
- 引用类型的值是保存在堆内存(Heap)中的对象(Object)
- 引用类型的值是按引用访问的
- 引用类型的值是可变的
- 引用类型的比较是引用(对象本身)的比较
基本类型的赋值其实就是将变量的值复制一份给另一个变量,当一个变量值做操作时并不会影响到其他变量
引用类型的赋值其实是将对象保存在栈区地址的指针(内存地址)赋值给另一个变量,赋值后等同于这两个变量都指向了同一块内存地址,因此当一个变量赋值给另一个时,两个变量指向的是同一个对象(及内存地址),任何的操作都会相互影响。