引言
这个问题是我刚入门前端时遇到的一个问题,最近在复盘Vue,如果有大佬一眼能看出问题关键点,希望在评论区中指点一下,或者探讨一下其他问题。如果有其他问题也可以私信我,积极解决并复盘哦。
废话少说,直接看代码
问题代码示例
代码1
<template>
<el-input v-model="skuCode" placeholder="SKU" />
</template>
<script>
export default {
data() {
return { raw: { skuCode: '' } };
},
computed: {
// 没有 setter,v-model 无法写回
skuCode() {
return this.raw.skuCode;
},
},
};
</script>
代码2
<template>
<div>
<div v-for="(item, index) in list" :key="index">
<el-input :value="item['skuCode']" @input="item.skuCode = $event" placeholder="请输入 SKU"></el-input>
</div>
<pre>{{ list.length }}</pre>
</div>
</template>
<script>
export default {
data() {
return {
list: [{},{}],
};
},
};
</script>
问题定位
上述示例代码中着重讲解一下代码2
简单明了,甚至控制台还报错了,原因就是使用了计算属性使用了getter数据只能被读取,无法被修改,给计算属性加上setter就可以解决了。
为什么出现了这个问题:
- Vue2 的底层响应式使用的是
Object.defineProperties的setter、getter触发响应式更新的,在已有的属性上定义setter、getter,上述代码声明时没有skuCode属性,导致没有被监听到。
那么问题又来了,为什么使用input组件能看到视图变化,而el-input就看不到呢:
- 它是一个“受控组件”:优先以父组件传入的 value 为准,内部状态会被 value 同步覆盖。
- 原生 input 在很多写法下是“非受控”的,用户输入会直接落在 DOM 上,即使数据没更新,视觉上也能看到输入。
问题又又来了,使用v-model视图咋又能更新了呢:
注意:还是未监听到响应变化,只是el-input做了处理。
- 你在 el-input 上看到“能变化”,主要是因为 el-input 内部有一个 currentValue,会在用户输入时立刻更新这个内部状态并展示出来;同时 v-model 把值赋回了对象(即便是新增属性,赋值本身是成功的,只是不会触发响应式更新)。
问题如何解决
- 使用 v-model 绑定 skuCode
- 初始化时声明 skuCode