1

我目前正在尝试在 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),但在我们让 JQueryUI 正确设置它们的样式之前。

任何建议都非常感激。

4

1 回答 1

0

它仍然不是很好......但这至少确实有效,并且相当有效......

来自Ember.js - 使用 Handlebars 助手检测子视图已呈现我发现了如何编写触发器,并且由于运行循环似乎工作的方式,将触发器插入页面的最后一个循环会导致它被调用 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 hacks 来完成)...... :(

于 2013-06-17T23:02:30.240 回答