【问题标题】:text/x-handlebars never showing uptext/x-handlebars 永远不会出现
【发布时间】:2013-03-07 17:49:10
【问题描述】:

我正在尝试开发我的第一个应用程序,但无法让浏览器显示我的车把脚本

这是我的html:

<!doctype html>
<html>
<head>
        <title>Random Presents</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="style.css">
        <script src="lib/jquery.min.js"></script>
        <script src="lib/handlebars.js"> </script>
        <script src="lib/ember.js"></script>
        <script src ="js/app.js"></script>
</head>

<body>
    <script type="text/x-handlebars">
    {{#view App.AView}}{{firstName}}{{/view}}
</script>
<script type="text/x-handlebars">
    {{#view App.AView}}{{surname}}{{/view}}
</script>
</body>
</html>

还有我的 app.js 文件:

App = Ember.Application.create();

App.AView = Ember.View.extend({
    tagName: 'span',
    firstName: 'Joe',
    surname: 'Bloggs'
});

当我加载文件时;该页面是空的,即使源对应于我的 html 文件。 我在 chrome javascript 控制台中没有看到任何错误。

有什么我想念的很明显的东西吗? 我测试了这些库,它们直接来自网站并且是最新版本。

更糟糕的是,我什至尝试使用仅包含 html 的脚本,但他也不会加载。

【问题讨论】:

    标签: javascript html ember.js handlebars.js


    【解决方案1】:

    因为您在View 类中创建了属性,所以您应该使用view 属性,它在某些情况下有点像this 关键字的指针。

    将您的模板更改为:

    <script type="text/x-handlebars">
        {{#view App.AView}}
            {{view.firstName}}
            {{view.surname}}
        {{/view}}
    </script>
    

    由于 Ember 约定,您代码中的两个车把模板代表相同的东西。当没有名称时,Ember 假定模板名称为“应用程序”。这意味着即使您将两个模板上的属性都修复为{{view.propertyName}},后一个模板也会覆盖第一个(或所有同名的前辈),因为 Ember 会将模板(带有 Handlebars)编译为模板函数和name 将用作模板集合的键(路径Ember.TEMPLATES),因此您需要将这些表达式移动到单个模板中,就像上面的代码一样。

    但是你应该避免使用这样的视图。

    视图应该显示数据,但不应该保留数据。您的数据应该存在于模型中(在商店中),并且视图应该向控制器询问数据,并且应该从疼痛中获取数据。控制器应该通过路由器从存储中填充数据(它知道做什么以及什么时候做)。

    我说这话一点也不坏。从 Ember 开始,只是想避免你在街道的错误一侧开车。

    众所周知,有很多过时的教程,这有时会引起很多混乱(repo 包含过时的教程/文章,应该会收到更新或添加免责声明的通知)。但总的来说,我建议你在网上关注guides,观看一些videos about Ember,查看other resources available

    这是一个非常基本的sample application 的注释代码,只是为了展示您可以并且应该使用的一些功能:

    车把

    <!-- 
        when a template doesn't have a data-template-name, Ember assumes this is the 
        application main template. This is usually where you'd render the layout structure
        and also where you'd put the main outlet
    -->
    <script type="text/x-handlebars">
        <h1>Example</h1>
        {{outlet}}
    </script>
    
    <!-- 
        As per convention, a named template should match with its route name
        There are ways around using "partial", "render", or even defining 
        a View class and setting the templateName property to a different name, or
        using the route's renderTemplate hook
    
        Another thing. You can have nested views when using nested routes
        This view template has another outlet to display a person from the collection
    -->
    <script type="text/x-handlebars" data-template-name="people">
        {{#each person in controller}}
            {{#linkTo people.person person}}
                {{person.fullName}}
            {{/linkTo}}<br />
        {{/each}}
        <hr />
        {{outlet}}
    </script>
    
    <!-- 
        Unlike the very first code piece in this answer, when you have a view or 
        template connected to a controller, you can access the data from the controller
        using handlebars expressions.
    -->
    <script type="text/x-handlebars" data-template-name="people/person">
        First name: {{view Ember.TextField valueBinding="firstName"}}<br />
        Last name: {{view Ember.TextField valueBinding="lastName"}}<br />
        Full Name: {{fullName}}    
    </script>
    

    JavaScript

    window.App = Ember.Application.create();
    
    // defining routes which are somewhat like states (think of a state machine)
    // they also provide the ability to have hash urls
    // the router is a very important piece of ember due to conventions
    App.Router.map(function() {
        // sample url ~/#/people
        this.resource('people', function() {
            // sample url ~/#/people/1
            this.route('person', { path: ':person_id' });
        });    
    });
    
    // In this route we provide the data to the list view in "people" template
    // the data will actually go to the controller 'content' property which can 
    // be a type of array for arraycontroller or a single object for object controller
    // this should allow the view to call data from the controller 
    App.PeopleRoute = Em.Route.extend({
        model: function() {
            return App.Person.find()
        }
    });
    
    // in this route we provide data for the "people/person" template
    // In this case we are using the person id from the parameters to query our
    // application store.
    App.PeoplePersonRoute = Em.Route.extend({
        model: function(params) {
            return App.Person.find(params.person_id)
        }
    });
    
    // This is the very first route of the application
    // Most of the time, you'll simply redirect from your index to a resource
    // in this example, from ~/#/ to ~/#/people
    App.IndexRoute = Em.Route.extend({
        redirect: function() {
            this.transitionTo('people');
        }
    });
    
    // The store manages your application data. Normally you only have to define
    // the revision since it's not 1.0 yet (https://github.com/emberjs/data/blob/master/BREAKING_CHANGES.md)
    // for this sample, I'm using the Fixture Adapter so I can add mock up data to the 
    // app while testing/coding front end
    App.Store = DS.Store.extend({
        revision: 11,
        adapter: 'DS.FixtureAdapter'
    });
    
    // Using Ember-Data, you can define a Model object which uses application
    // semantics to describe your data, and does many operations which you'd 
    // normally expect to see in a ORM. Ember-Data is no ORM, but it gets pretty close
    // and in certain scenarios it goes beyond
    App.Person = DS.Model.extend({
        firstName: DS.attr('string'),
        lastName: DS.attr('string'),
        fullName: function() {
            return '%@ %@'.fmt(
                this.get('firstName'),
                this.get('lastName')
            );
        }.property('firstName', 'lastName')
    });
    
    // Using the FixtureAdapter you can add mockup data to your data store
    App.Person.FIXTURES = [
        {id: 1, firstName: 'Joe', lastName: 'Bloggs'},
        {id: 2, firstName: 'Other', lastName: 'Dude'}
    ];
    
    // when your controller wants to handle a collection, use ArrayController
    App.PeopleController = Em.ArrayController.extend();
    // when it handles a single object, use ObjectController
    App.PeoplePersonController = Em.ObjectController.extend();
    

    【讨论】:

    • 非常感谢!我会深入研究的。我实际上有一个带有模型和控制器的应用程序,但到目前为止我的任何车把脚本都无法显示任何内容,这就是我以这种方式剥离它的原因。我一定会根据你的建议给它一个新的镜头!再次感谢
    【解决方案2】:

    在模板中,默认上下文是控制器,因此您需要显式引用视图以访问其属性:{{view.property}}

    在你的例子中:

    {{#view App.AView}}{{view.surname}}{{/view}}
    

    Working example JSBin

    【讨论】:

      猜你喜欢
      • 2012-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-01
      相关资源
      最近更新 更多