说起来也挺奇怪的,按照书上的写法再次报错,这书就不能靠谱一点……
书上的例子就不放了,直接上解决方案吧。我在x-select的issue里发现了这么一条:
Hey @newton3, if you’re using x-select 3.0 you should be using contextual components. If you update your HBS to this does it still throw the same error?
{{#x-select action='selectAppType' id="app-type-select" value=model.AppType class="form-control" as |xs|}} {{#each model.AppTypes as |appType|}} {{log appType}} {{#xs.option value=appType}} {{appType}} {{/xs.option}} {{/each}} {{/x-select}}
目前最新版的x-select是3.1.1,正好适用于这个方案。简单概括下来,这个解决方案就是将x-select重新包装一遍,以此让ember能够获得其中的get方法(注意到后面的|xs|
声明),其实和别的包装对象的意义是大致相同的。从某个意义上说,和TypeScript中某些特殊的类型转换必须先转换成any再转换成目标类型有一点相似,不过这就扯远了。
事实上,作者也给出了解释:
Absolutely! Think of it as a component “wrapping” a component.
x-option
will always be used as a child ofx-select
. Since that will always be true we can do things like automatically pass the instance ofx-select
down tox-option
. We also registerx-option
with x-select.
而且官方文档也改成这种写法了……书上那种写法不知道是哪一年的老黄历了。所以书上那个例子按照上面的改造一下,就能解决:
{{#x-select value=model.sighting.cryptid
class="form-control" as |xs|}}
{{#xs.option}}Select Cryptid{{/xs.option}}
{{#each model.cryptids as |cryptid|}}
{{#xs.option value=cryptid}}{{cryptid.name}}{{/xs.option}}
{{/each}}
{{/x-select}}
而且看文档上面说,还有更新的写法(要求ember版本>=3.4)。至于这个语法模仿了谁……大家都清楚,就不多说了(笑):
<XSelect @value={{bob}} @onChange={{action "selectPerson"}} as |xs|>
<xs.option @value={{fred}}>Fred Flintstone</xs.option>
<xs.option @value={{bob}}>Bob Newhart</xs.option>
</XSelect>
当然,改完之后虽然不报错了,但是会有deprecate的提示。这个就无能为力了,x-select的作者采用了即将废弃的写法,我们也没有办法,不是吗。而且这项目我感觉也快凉了,最近一次提交都是年初的事了……