Vue watch 观察自己,修改自己

自己在做 Vue 项目中,有个需求是输入数字,我用的 <input type="number" v-model="text" /> 来实现自动展示数字键盘。

此时有个问题,maxlength 属性是不生效的。所以我对它进行了 watch,超过一定长度,就进行截断。

我突然发现一个问题,使用 watch 来观察数值,此时还可以修改数值吗?

看下面一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
<div id="app">
<p>{{ num }}</p>
</div>
</template>

<script>
export default {
data () {
return {
num: 0
}
},
watch: {
num (val, oldVal) {
console.log("num-changed: %i->%i", oldVal, val)
if (val < 3) {
console.log("in-if: val=%i", val)
this.num++
}
},
},
created () {
setTimeout(() => {
this.num = 1
}, 3000)
},
}
</script>

逻辑很简单:

  • 默认 num 初始化 0,3 秒后变成 1
  • 观察 num,如果变化就打印日志。
  • 此外,如果不大于 3,那么进行自增。

观察日志,得到:

1
2
3
4
5
num-changed: 0->1
in-if: val=1
num-changed: 1->2
in-if: val=2
num-changed: 2->3

是符合逻辑预期的。

也就是说,在观察中修改当前数值,是完全可行的。不过必须做好中断逻辑,否则会死循环。

这类问题本质在于 Vue 的 v-model 并不是严格双向绑定。虽然可以理解为以下写法,用户输入的内容同步到数据上,修改的数据反映到输入元素上:

1
<input :value="text" @input="onInput">

比如下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<input :value="text"/>
</template>

<script>
export default {
data () {
return {
text: 'abc'
}
}
}
</script>

很明显的,输入框绑定了 text 的值,但是实际输入框是可以输入的,之后,会发生输入框显示内容和实际绑定的 text 不符的情况。

至于输入框绑定问题,得好好花时间研究下,之前的文章感觉质量还是不够。

–END–