对于el-input组件,正常情况下,给组件设置v-model之后,例如:
v-model="inputCouponValue"
我们就可以通过在父组件中修改inputCouponValue,然后这个更改就回传给子组件,子组件内部通过
this.$emit('input', newInputCouponValue)
来通知父组件,然后父组件会再更改inputCouponValue实现子组件的更新
但是当我们需要将父组件的值做一些处理再传入子组件后,就不能用这种写法了,例如以下写法:
// alignInputValue想要保留2位小数
v-model="alignInputValue(inputCouponValue)"
就是非法的 这时,我们需要将v-model换成value
:value="alignInputValue(inputCouponValue)"
对于这个输入框,还有一个需求,就是输入的最大值有限制,例如是10,最开始时,默认会给this.inputCouponValue赋值10(希望用户尽可能少用现金)
由于用户可能输入大于10的数字,所以很自然有个逻辑就是失去焦点时将用户输入的值再重置成10,所以组件现在是这样:
:value="alignInputValue(inputCouponValue)"
@blur="setInputCouponValue"
在setInputCouponValue中,可以通过事件对象获取输入的值,进行判断,于是有:
setInputCouponValue (e) {
if (e.target.value > this.maxDicCouponCost) {
this.inputCouponValue = this.maxDicCouponCost
}
}
此处的maxDicCouponCost就是10 期望的效果是,如果用户输入1000,失去焦点后input框中的值自动变成10 但是发现这样做没法更改input中的值,也就是说,input框中的值还是1000
经过后来的测试发现,如果手动给this.inputCouponValue赋一个常量,例如:
setInputCouponValue (e) {
if (e.target.value > 10) {
this.inputCouponValue = 5
}
}
是可以的,但如果把这里的5改为和maxDicCouponCost一样的值10,就不行了
目前观察到的现象总结: inputCouponValue初始值是10,再输入1000,失去焦点,再将inputCouponValue的值改为10,这个过程并没有触发组件内部dom的更新 inputCouponValue初始值是10,再输入1000,失去焦点,再将inputCouponValue的值改为5,这个过程触发了组件内部dom的更新 猜测: 父组件给input传的value值(在此处就是inputCouponValue)的改变会导致dom的更新(input.value = xxx),所以组件里面可能会有对value的watch监听
失去焦点时,el-input组件并没有把用户输入的值更新到对应的变量中,因为如果更新了,那inputCouponValue的值也应该随之改为1000(dom上的值改变时,一定需要通知给Vue对象去改变),我们再将1000改为10时,inputCouponValue是有变化的,也就是传给el-input组件的value是有变化的,应该是会更新dom的,但实际没更新 也就是说,我们期待input组件失去焦点时帮我们做这样一件事: 先将inputCouponValue改为1000,然后再从1000改为10,但它实际上没这么做
通过查看el-input组件的源码,发现: 在el-input组件内部,input的value绑定的是currentValue变量:
<input
:value="currentValue"
>
因此,只有改变currentValue的值,才会触发currentValue的get钩子里收集的Dependency,也就是触发当前组件的刷新,所以我们重点关注一下currentValue什么时候被更新,后来发现源码中currentValue都是通过setCurrentValue这个方法来更新的,setCurrentValue更新的时机有两个: 1、value的变化 2、input事件触发
证明之前的猜想正确,修改的方案就是必须添加@input,通过它来触发触发inputCouponValue的修改,这样el-input组件就可以监听到value的改动,进而触发dom的更改了
changeInputCouponValue (value) {
this.inputCouponValue = value
},
在实际实施的过程中,并非给inputCouponValue赋值来实现的,而是直接在@blur回调中拿到事件对象,进而从事件对象中拿到dom对象,然后直接通过event.target.value = xxx修改也可以实现
但是,把这个代码移植到微信小程序后,发现跑不起来,后来又发现,小程序中没法通过event.target拿到dom对象,所以不能通过这种方式直接操作dom改它的值