我尝试构建一个受google's timer启发的时间输入组件。
这是我的版本:
我知道有很多方法可以做到这一点,但这个方法最让我困惑。
我选择使用数组shift()/push()
到位的最后一位/新数字并保留数组length <= 4
{{input value=inputValue type="text"}}
<span {{bind-attr class="digits.3::placeholder"}}>{{digits.[3]}}</span>
<span {{bind-attr class="digits.2::placeholder"}}>{{digits.[2]}}</span>
<span {{bind-attr class="digits.2::grey"}}>h</span>
<span {{bind-attr class="digits.1::placeholder"}}>{{digits.[1]}}</span>
<span {{bind-attr class="digits.0::placeholder :last"}}>{{digits.[0]}}</span>
<span {{bind-attr class="digits.0::grey"}}>m</span>
App.TimeInputComponent = Ember.Component.extend(
MAX_TIME: 99 * 60 + 59
didInsertElement: () ->
if @get('value')
@set('inputValue', @formatValue(@get('value')))
classNames: ['time-input-component']
classNameBindings: ['focused:focused']
digits: []
keyUp: (e) ->
code = e.which
char = String.fromCharCode(code)
return unless 48 <= code <= 57 or code == 8 or code == 9
digits = @get('digits')
if code == 8
digits.shift()
else if char.match(/[0-9]/)
digits.pop() if digits.length >= 4
digits.unshift(char)
# Initial idea: NOT working
@notifyPropertyChange('digits')
做了一些冗长的调试,发现了这个:
由于MANDATORY_SETTER
,对get()
的调用仅在对象的meta.values
内,而不在属性本身(obj[keyName]
)内。
所以只是为了测试它,我这样做是为了让组件的this.digits[Ember.META_KEY].values
中的值更新:
@set('digits.0', digits[0])
@set('digits.1', digits[1])
@set('digits.2', digits[2])
@set('digits.3', digits[3])
有没有办法围绕4个set()调用并仍然使用普通数组? 我应该使用ArrayProxy吗?我希望在这个特定的用例中我可以使用普通数组。
答案 0 :(得分:0)
根据我的经验,如果你发现自己需要深入了解Ember的内部情况以了解正在发生的事情,那么你已经偏离了难以捉摸的“Ember方式”,而Ember将继续与你战斗。正如您所发现的那样,在模板中引用数组中的特定元素并不是Ember真正希望您做的事情。
为什么不给出像hoursTensDigit
这样的个别数字名称,而不是继续将数字视为模板中的数组。然后你可以用以下代码替换你的套件:
@set 'hoursTensDigit', digits.objectAt(3)
...
或向组件添加一些计算属性
hoursTensDigit: ( ->
return digits.objectAt(3)
).property 'digits.@each'
...
您可以继续引用除模板之外的其他任何位置的个别数字(尽管您可能希望使用.objectAt(..)
而不是'。[x]'),并且所有内容都应该在游泳中运行。计算出的属性,或者将所有集合放在观察者的“数字。@ each”中,一旦你开始倒计时等,就会给你最大的里程数。