Ember.js表单:无需失焦即可实时更新提交按钮禁用状态
嘿,这个场景我太熟悉了!你遇到的问题本质是属性依赖追踪的范围不对,加上默认输入框的绑定时机导致的。咱们一步步来解决:
核心问题分析
你当前的disableSubmit计算属性只监听了field1和field2这两个对象的引用变化,但用户输入时改变的是对象内部的amount属性,对象本身的引用没动——所以Ember不会触发计算属性的重新计算,直到输入框失焦(此时Ember才会把输入值同步到绑定的属性上,甚至可能只是此时才触发对象的变化检测)。
解决方案1:修正计算属性的依赖路径
直接把依赖改成监听嵌套的amount属性,这样只要field1.amount或field2.amount变化,就会立即重新计算disableSubmit:
disableSubmit: (function() { return (this.get('field1.amount') == null) || (this.get('field2.amount') == null); }).property('field1.amount', 'field2.amount'),
这样修改后,Ember会深度追踪这两个嵌套属性的变化,不管是输入框更新还是其他方式修改amount,都会实时触发按钮状态的更新。
解决方案2:用现代Ember的@tracked装饰器(推荐)
如果你的项目用的是Ember 3.1及以上版本,更推荐使用@tracked响应式系统,它不需要手动维护依赖列表,代码更简洁且响应更及时:
import { tracked } from '@glimmer/tracking'; import Mixin from '@ember/object/mixin'; export default Mixin.create({ @tracked field1; @tracked field2; get disableSubmit() { // 使用可选链操作符避免null/undefined报错 return (this.field1?.amount == null) || (this.field2?.amount == null); } });
@tracked会自动追踪所有被访问的属性变化,包括嵌套的amount,只要field1.amount或field2.amount有变动,disableSubmit就会自动更新。
关键补充:让输入框实时同步值
光改计算属性还不够!Ember的{{input}}组件默认是失焦时才同步输入值到绑定属性,所以你需要给输入框加上valueUpdate='keyup',让它每按一次键盘就同步值:
{{!-- 模板中的输入框 --}} {{input value=field1.amount valueUpdate='keyup' placeholder="输入字段1"}} {{input value=field2.amount valueUpdate='keyup' placeholder="输入字段2"}} <button {{action 'submitForm'}} disabled={{disableSubmit}}>提交</button>
这样用户输入时,值会实时同步到field1.amount和field2.amount,再配合前面的计算属性,按钮就能立刻做出状态响应,不需要等失焦啦!
内容的提问来源于stack exchange,提问作者Topher Brennan

