Vue中date类型输入框触发时computed property未调用的问题
问题原因与解决方案
嘿,我来帮你拆解下为什么你的computed属性没触发,以及怎么修复这个问题:
原代码的核心问题
你的computed属性没被调用主要有三个原因:
- computed没有被模板引用:Vue的computed属性是惰性求值的,只有当它在模板中被使用时,Vue才会追踪它的依赖并在依赖变化时重新计算。你的模板里完全没用到
result这个computed属性,所以即使dateOfBirth变化,它也不会触发。 - computed没有返回值:Vue的computed要求必须返回一个计算后的结果,你的
result函数只是修改了this.age,没有任何返回,这不符合computed的设计规范,也会导致依赖追踪异常。 - 在computed中修改data是反模式:computed应该是纯函数——只根据依赖计算值,不应该产生修改data这类副作用,这会让数据流向变得混乱,也可能引发意想不到的问题。
正确的实现方式
这里给你两种符合Vue规范的实现方案:
方案1:用computed直接返回年龄(推荐)
既然年龄是基于出生日期计算出来的,完全可以用computed直接返回结果,不需要单独维护age这个data属性:
<div id="app"> <input type="date" v-model="dateOfBirth"> <!-- 直接使用computed属性 --> <input type="number" :value="calculatedAge" readonly> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <script> var myObject = new Vue({ el: '#app', data: { dateOfBirth: '2020-01-01' }, computed: { calculatedAge: function () { if (!this.dateOfBirth) return 0; const systemDateYear = moment().year(); const myDOB = new Date(this.dateOfBirth); return systemDateYear - myDOB.getFullYear(); } } }) </script>
方案2:用watch监听出生日期变化来更新年龄
如果你确实需要维护age这个data属性,可以用watch来监听dateOfBirth的变化,然后更新年龄:
<div id="app"> <input type="date" v-model="dateOfBirth"> <input type="number" v-model="age"> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <script> var myObject = new Vue({ el: '#app', data: { dateOfBirth: '2020-01-01', age: 0 }, watch: { dateOfBirth: function(newDate) { const systemDateYear = moment().year(); const myDOB = new Date(newDate); this.age = systemDateYear - myDOB.getFullYear(); } }, // 初始化时计算一次年龄 mounted() { this.$watch('dateOfBirth', this.dateOfBirth)(); } }) </script>
为什么移出到外部能运行?
你把代码移出到外部后,应该是手动触发了这段代码(比如在某个事件里),此时myObject.dateOfBirth已经更新,所以能正确计算年龄,但这不是Vue的响应式写法,维护起来会很麻烦。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

