我正在尝试在Ember.JS中运行一个小原型,以便完全重写Web应用程序的UI作为针对WebAPI运行的Ember应用程序,但是我已经设法让Ember运行正常,我无法让jqueryui正确初始化标签。
如果在视图中我放置了要创建的选项卡的静态数据,似乎工作正常,但是如果我使用动态数据则它不起作用。
我有一个Ember视图模板
<script type="text/x-handlebars" id="index">
<div id="tabs" class="ui-tabs">
<ul>
{{#each model}}
<li>
<span class="ui-icon ui-icon-person"></span>
<a {{bindAttr href="route"}} {{bindAttr title="tabTitle"}}><span>{{title}}</span></a>
</li>
{{/each}}
</ul>
{{#each model}}
<div {{bindAttr id="tabTitle"}}>
<p>
Retrieving Data - {{title}}
</p>
</div>
{{/each}}
</div>
</script>
和视图
App.IndexView = Ember.View.extend({
templateName: 'index',
didInsertElement: function () {
var tabs = $("#tabs").tabs();
}
});
和模型
App.Section = DS.Model.extend({
name: DS.attr('string'),
title: DS.attr('string'),
tabTitle: function () {
return 'tab-' + this.get('name');
}.property("name"),
route: function () {
return '#' + this.get('tabTitle');
}.property("tabTitle")
});
App.Section.FIXTURES = [
{
id: 1,
name: 'home',
title: 'Home'
},
{
id: 2,
name: 'users',
title: 'Users'
}
];
它似乎正确生成HTML(从检查Firebug),但这不起作用,就好像我用
替换模板<script type="text/x-handlebars" id="index">
<div id="tabs" class="ui-tabs">
<ul>
<li>
<span class="ui-icon ui-icon-person"></span>
<a href="#tab-home" title="tab-home"><span>Home</span></a>
</li>
<li>
<span class="ui-icon ui-icon-person"></span>
<a href="#tab-users" title="tab-users"><span>Users</span></a>
</li>
</ul>
<div id="tab-home">
<p>
Retrieving Data - Home
</p>
</div>
<div id="tab-users">
<p>
Retrieving Data - Users
</p>
</div>
</div>
</script>
效果很好。
我假设在初始化选项卡时没有完全呈现DOM,但是我能找到的所有东西都说didInsertElement就是这样做的地方,我有时间深入挖掘爱好。
我很感激任何想法。
编辑:我通过以下方式成功地完成了这项工作:
App.IndexView = Ember.View.extend({
templateName: 'index',
didInsertElement: function () {
Ember.run.next(this, function () {
if (this.$('#tab-users').length > 0) {
var tabs = $('#tabs').tabs();
} else {
Ember.run.next(this.didInsertElement);
}
});
},
});
这个问题是1)它需要我知道将要写入视图的最后一个元素被调用(显然动态数据我不一定知道),所以我可以继续检查它,2)这种技术的低效率让我想要尖叫!
此外,在渲染完成后,我们会得到一个很好的旧的FoUC(Flash of Unstyled Content),但在我们获得JQueryUI之前,它们才能正确地设置样式。
感激地收到任何建议。
答案 0 :(得分:0)
它仍然不好......但这至少可行,并且效率相当高......
从Ember.js - Using a Handlebars helper to detect that a subview has rendered我发现了如何编写触发器,并且由于运行循环似乎工作的方式,在页面的最后一个循环中插入触发器会导致它被调用n次,但仅循环完成后,快速状态检查“hasBeenTriggered”确保您只执行一次delgate函数。
我的代码现在看起来像这样:
<script type="text/x-handlebars" id="index">
<div id="tabs" class="ui-tabs">
<ul>
{{#each model}}
<li>
<span class="ui-icon ui-icon-person"></span>
<a {{bindAttr href="route"}} {{bindAttr title="tabTitle"}}><span>{{title}}</span></a>
</li>
{{/each}}
</ul>
{{#each model}}
<div {{bindAttr id="tabTitle"}}>
<p>
Retrieving Data - {{title}}
</p>
</div>
{{trigger "triggered"}}
{{/each}}
</div>
</script>
带触发器
Ember.Handlebars.registerHelper('trigger', function (evtName, options) {
options = arguments[arguments.length - 1];
var hash = options.hash,
view = options.data.view,
target;
view = view.get('concreteView');
if (hash.target) {
target = Ember.Handlebars.get(this, hash.target, options);
} else {
target = view;
}
Ember.run.next(function () {
target.trigger(evtName);
});
});
并查看
App.IndexView = Ember.View.extend({
templateName: 'index',
hasBeenTriggered: false,
triggered: function () {
if (!this.get("hasBeenTriggered")) {
var tabs = $('#tabs').tabs();
this.set("hasBeenTriggered", true);
}
}
});
我很想知道是否有更好的方法可以做到这一点,因为这仍然无法解决FOUC问题(再次可以通过更多JS黑客攻击)...... :(