VUE中,动态添加的文本框如何实现数据实时双向绑定?

CooCls
  • 77

在线调试地址

http://jsrun.net/Cp3Kp/edit

问题描述

项目中有个功能,通过选择器为商品列表添加商品,为每个新增的商品设置价格,但是以上实现方式造成新增的商品后面的文本框内容输入无法实时更新,在新增商品价格文本框处编辑无效,在原有商品价格文本框处编辑才会生效。为何会出现该现象,如何解决?

主要代码内容

html:

<div id="app">
<template>
  <el-select v-model="value" placeholder="请选择" @change="selectChange">
    <el-option
      v-for="item in goods"
      :key="item.value"
      :label="item.label"
      :value="item">
    </el-option>
  </el-select>
  <div>
    <div v-for="item in goodsPrice" :key="item.value">
        <span>{{item.label}}</span>
        <el-input style="width: 120px" v-model="item.price"/>
    </div>
  </div>
</template>
</div>

js:

data() {
      return {
        // 商品
        goods: [
            {value: '选项1',label: '黄金糕'},
            {value: '选项2',label: '双皮奶'},
            {value: '选项3',label: '蚵仔煎'},
            {value: '选项4',label: '龙须面'},
            {value: '选项5',label: '北京烤'}
        ],
        value: null,
        // 带价商品列表
        goodsPrice: [{value: '选项1',label: '黄金糕',price: 0}]
      }
    },
    methods: {
        // 选中商品,为商品添加价格属性,将带价格属性的商品加入到带价商品列表中
        selectChange(item){
            item.price = 0;
            this.goodsPrice.push(item);
        }
    }
回复
阅读 5.2k
4 个回答

vue能够侦测到数组响应式更新的只有七种方法:
(1)push
(2)pop
(3)shift
(4)unshift
(5)splice
(6)sort
(7)reverse
而对于object,能够侦测到object响应式更新则只有两种方法:
(1) vue.$set 设置属性值
(2) vue.$delete 删除属性

楼主的错误在于使用item.price = 0;对对象进行了一个赋值,而这个赋值vue是侦测不到它的变化的,即使用赋值操作不是响应式更新。

所以正确的代码应该是:

selectChange(item){
  this.$set(item,'price',0);
  this.goodsPrice.push(item);
}

<el-input style="width: 120px" v-model="item.price"/>

这里绑定的是 price, 你 this.goodsPrice.push(item); 的看上去是 {value: '选项1',label: '黄金糕'}

这样的 price 是无法被监测到的,而且因为你是直接push的原对象,所以导致goodsPrice 里面的也被改变了。

所以你应该把原对象拷贝一下,然后把price字段也加上11111111111

selectChange(item){
    this.goodsPrice.push({...item,price:0});
}
selectChange(item){
            const data = {
              value: item.value,
              label: item.label,
              price: 0
            }
            this.goodsPrice.push(data);
        }

这样试下

改成这样

this.goodsPrice.push(JSON.parse(JSON.stringify(item)))

或者其他方式复制或生成一个新的对象

原因就是实际上item指向的是goods内的对象,你添加修改数据时都是用的这个对象
相当于指针操作

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏