Meteor 模板未在 HTML 元素内呈现内容

Meteor Template Not Rendering Content Inside HTML Elements

我想做什么

这看起来很简单,但我正在尝试使用 Meteor 的帐户系统和 Iron:Router 来为网络应用程序设置管理系统。管理部分是应用程序中唯一带有帐户的部分。管理部分位于 /admin 并有一个登录模板和一个应在管理员登录后显示的数据模板。

密码

基本路由器

Router.route('/', {
    template: 'user' // Not shown; works fine
});
Router.route('/admin', {
    template: 'adminDataPage'
});

模板

<template name="adminLoginPage">
    <div class="cover-wrapper-outer page-admin login">
        <div class="cover-wrapper-inner">
            <div class="cover-container">
                <div class="cover">
                    <form class="admin-login-form">
                        <div class="alert alert-danger login-failure">
                            The username or password is incorrect.
                        </div>
                        <input class="form-control username" name="username" type="text" placeholder="Username">
                        <input class="form-control password" name="password" type="password" placeholder="Password">
                        <input class="form-control submit" name="submit" type="submit" value="Log in">
                    </form>
                </div>
            </div>
        </div>
    </div>
</template>
<template name="adminDataPage">
    <div class="container-fluid page-admin admin-content">
        <div class="row">
            <div class="col-xs-12">
                <div class="scrolling-table">
                    <table class="table table-striped">
                        <thead>
                            <tr>
                                <th>Year</th>
                                <th>Make</th>
                                <th>Model</th>
                                <th>Engine</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                            <td>Year</td>
                            <td>Make</td>
                            <td>Model</td>
                            <td>Engine</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</template>
<template name="adminLoggingIn">
    Logging in...
</template>

(目前还不完整,但与问题无关。)

问题

无论我做什么,adminDataPage 模板中的内容都不会呈现。但是,在 元素 的任何内容都会呈现 。例如,此 呈现:

<template name="adminDataPage">
    Hello world!
</template>

下面中的world不会渲染:

<template name="adminDataPage">
    Hello <span>world</span>!
</template>

adminLoggingIn 模板也是如此。但是,adminLoginPage 模板中的任何内容都可以正常工作。

本质上,显示登录框,客户端Javascript(未显示)负责用户登录,用户看到Logging in...,然后用户什么也看不到,浏览器的检查器中没有显示任何内容(除非 adminDataPage 模板中有未嵌套的纯文本)。

我试过的

如果当前用户

<template name="adminDataPage">
    {{#if currentUser}}
        <div class="container-fluid page-admin admin-content">
            <div class="row">
                <div class="col-xs-12">
                    <div class="scrolling-table">
                        <table class="table table-striped">
                            <thead>
                                <tr>
                                    <th>Year</th>
                                    <th>Make</th>
                                    <th>Model</th>
                                    <th>Engine</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                <td>Year</td>
                                <td>Make</td>
                                <td>Model</td>
                                <td>Engine</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    {{else}}
        <div class="cover-wrapper-outer page-admin login">
            <div class="cover-wrapper-inner">
                <div class="cover-container">
                    <div class="cover">
                        <form class="admin-login-form">
                            <div class="alert alert-danger login-failure">
                                The username or password is incorrect.
                            </div>
                            <input class="form-control username" name="username" type="text" placeholder="Username">
                            <input class="form-control password" name="password" type="password" placeholder="Password">
                            <input class="form-control submit" name="submit" type="submit" value="Log in">
                        </form>
                    </div>
                </div>
            </div>
        </div>
    {{/if}}
</template>

如预期的那样,这将在未登录时呈现登录页面。但是,一旦登录,就不会呈现任何内容。我也试过整合 {{#if loggingIn}} 但无济于事。

Iron:Router 挂钩

Router.route('/', {
    template: 'user'
});
Router.route('/admin', {
    template: 'adminDataPage'
});
var requireLogin = function() {
    if (! Meteor.user()) {
        if (Meteor.loggingIn()) {
            this.render('adminLoggingIn');
        } else {
            this.render('adminLoginPage');
        }
    } else {
        this.next();
    }
};
Router.onBeforeAction(requireLogin, {only: 'admin'});

如果未登录,这将按预期呈现登录页面,但不会呈现 adminLoggingInadminLoginPage 模板中 HTML 元素内的任何内容。

规格

流星 v1.1.0.3

Iron:Router v1.0.9

结论

我很困惑为什么 Meteor(或 Iron:Router)拒绝在某些上下文中呈现某些内容。当然,如果有人有什么想法可以帮助解决这个问题,请拍;非常感谢。

Blaze.render() 似乎是这里的错误。在控制台中使用 Blaze.render(Template.adminDataPage, document.body) 不会呈现任何内容,但就像在我的问题中一样 - 纯文本直接嵌套在 body 元素中。它不会在正文下方嵌套任何 DOM 元素。

为了测试,我创建了一个 DOM 元素 <div class="test"></div>,将其嵌套在页面正文中,并调用了 Blaze.render(Template.adminDataPage, $('.test')[0]) 并且成功了。格式不正确,但有效。

添加供 Iron:Router 使用的布局模板可解决此问题,如下所示:

<template name="adminPage">
    <div class="test">
        {{> yield}}
    </div>
</template>
Router.route('/admin', {
    name: 'admin',
    template: 'adminDataPage',
    layoutTemplate: 'adminPage'
});
var requireLogin = function() {
    login_dep.depend();
    if (! Meteor.user()) {
        if (Meteor.loggingIn()) {
            this.render('adminLoggingIn');
            console.log('Logging in page');
        } else {
            this.render('adminLoginPage');
            console.log('Login page');
        }
    } else {
        this.next();
        console.log('Data page');
    }
};
Router.onBeforeAction(requireLogin, {only: 'admin'});

此外,将 {{#if currentUser}} 嵌套在另一个元素中也有效:

<template name="adminPage">
    <div class="test">
        {{#if currentUser}}
            <div class="container-fluid page-admin admin-content">
                <div class="row">
                    <div class="col-xs-12">
                        <div class="scrolling-table">
                            <table class="table table-striped">
                                <thead>
                                    <tr>
                                        <th>Year</th>
                                        <th>Make</th>
                                        <th>Model</th>
                                        <th>Engine</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                    <td>Year</td>
                                    <td>Make</td>
                                    <td>Model</td>
                                    <td>Engine</td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        {{else}}
            <div class="cover-wrapper-outer page-admin login">
                <div class="cover-wrapper-inner">
                    <div class="cover-container">
                        <div class="cover">
                            <form class="admin-login-form">
                                <div class="alert alert-danger login-failure">
                                    The username or password is incorrect.
                                </div>
                                <input class="form-control username" name="username" type="text" placeholder="Username">
                                <input class="form-control password" name="password" type="password" placeholder="Password">
                                <input class="form-control submit" name="submit" type="submit" value="Log in">
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        {{/if}}
    </div>
</template>
Router.route('/admin', {
    name: 'admin',
    template: 'adminPage'
});

我不确定为什么 Blaze 拒绝将某些元素附加到 body 元素,但这些是一些解决方法。

编辑

我发现一个更好的解决方法是添加一个元素,Blaze 可以在其中添加模板 DOM。 Blaze.render(Template.adminDataPage, document.body, $('.render-fix')[0]) 其中 class 为 render-fix 的隐藏元素在初始渲染时放置在 DOM 中将起作用。本质上:

<template name="adminPage">
    {{#if currentUser}}
        <div>User logged in stuff</div>
    {{else}}
        <div>User not logged in stuff</div>
    {{/if}}
    <div class="render-fix" style="display: none"></div>
</template>

在我看来,Blaze 在初始渲染后不会将任何模板附加到 body。