【问题标题】:Handlebars with Backbone template not rendering带有主干模板的车把未渲染
【发布时间】:2017-07-09 04:59:41
【问题描述】:

我有一个在服务器和客户端上同时使用 Backbone 和 Handlebars 的应用程序。

服务器

Backbone 和 Express-Handlebars 已安装

app.js

app.set('views', path.join(__dirname, '/views'));
app.engine('.hbs', expHbs({
  defaultLayout: 'index', 
  extname: '.hbs'
}));
app.set('view engine', '.hbs');

index.js

exports.init = function(req, res){
  res.render('contact/index');
};

index.hbs

<div class="row">
  <div class="col-sm-6">
    <div class="page-header">
      <h1>Send A Message</h1>
    </div>
    <div id="contact"></div>
  </div>
  ....some code

<script id="tmpl-contact" type="text/x-handlebars-template">
  <form>

      bootstrap with handlebars temlates {{....}} in here

  </form>
</script>

客户

在客户端我通过 Bower 安装了 Backbone 和 Handlebars

index.js Backbone.view

var Handlebars = require('handlebars');
  app.ContactView = Backbone.View.extend({
    el: '#contact',
    template: Handlebars.compile( $('#tmpl-contact').html() ),
    events: {
      'submit form': 'preventSubmit',
      'click .btn-contact': 'contact'
   },
    initialize: function() {
      this.model = new app.Contact();
      this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template( this.model.attributes ));
      this.$el.find('[name="name"]').focus();
   },
    preventSubmit: function(event) {
      event.preventDefault();
   },
    contact: function() {
      this.$el.find('.btn-contact').attr('disabled', true);

      this.model.save({
        name: this.$el.find('[name="name"]').val(),
        email: this.$el.find('[name="email"]').val(),
        message: this.$el.find('[name="message"]').val()
      });
    }
  });

发生的情况是 index.hbs 在服务器端正常渲染,但它没有在脚本内渲染表单;它显示为空的&lt;div id="contact"&gt;&lt;/div&gt;,并且在控制台中没有显示任何错误。

Using Handlebars with Backbone 所示,用车把替换下划线模板的一种方法是将_.template 替换为Handlebars.compile,但这些选项都不适用于我。我还为 &lt;script&gt; 尝试了不同的 type 属性,但仍然无法正常工作。

我该如何解决这个问题?任何帮助表示赞赏。谢谢。

在客户端添加了完整的 index.js

/* global app:true */

var Handlebars = require('Нandlebars');

(function() {
  'use strict';

  app = app || {};

  app.Contact = Backbone.Model.extend({
    url: '/contact/',
    defaults: {
      success: false,
      errors: [],
      errfor: {},
      name: '',
      email: '',
      message: ''
    }
  });

  app.ContactView = Backbone.View.extend({
    el: '#contact',
    template: Handlebars.compile( $('#tmpl-contact').html() ),
    events: {
      'submit form': 'preventSubmit',
      'click .btn-contact': 'contact'
    },
    initialize: function() {
      this.model = new app.Contact();
      this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template( this.model.attributes ));
      this.$el.find('[name="name"]').focus();
    },
    preventSubmit: function(event) {
      event.preventDefault();
    },
    contact: function() {
      this.$el.find('.btn-contact').attr('disabled', true);

      this.model.save({
        name: this.$el.find('[name="name"]').val(),
        email: this.$el.find('[name="email"]').val(),
        message: this.$el.find('[name="message"]').val()
          });
        }
     });

  $(document).ready(function() {
    app.contactView = new app.ContactView();
  });
}());

【问题讨论】:

  • 你在哪里初始化index.js...中的视图?声明一个视图是不够的。您需要在加载所需的内容后对其进行初始化。
  • @T J 如果你的意思是使用 Backbone.Model.Extend,我把它放在同一个文件中
  • (function() { 'use strict'; app = app || {}; app.Contact = Backbone.Model.extend({ url: '/contact/', 默认值: { 成功: false, errors: [], errfor: {}, name: '', email: '', message: '' } }); 这是带有 Jade 和 Underscore 模板的 github.com/jedireza/drywall。我正在尝试将其更改为车把。
  • 不,您应该在某处拥有new app.ContactView()。顺便说一句,如果您要共享代码块,请edit 并添加它。它们在 cmets 中是不可读的
  • $(document).ready(function() { app.contactView = new app.ContactView(); }); 将初始化视图然后您的应用程序加载。那时index.hbs 的内容是否可用?还是稍后加载?

标签: backbone.js handlebars.js express-handlebars


【解决方案1】:

所以这里提到Handlebars.compile 必须在&lt;script&gt;&lt;/script&gt; 中的车把模板加载到DOM 之后加载。在这种情况下,使用 express-hanldebars 时,必须在主布局中的 {{{ body }}} 元素之后放置指向 js 文件的链接。这是正确的答案。

这里还有一个问题,app 不能像 index.js

中出现的那样在全局范围内定义

为了在全局范围内定义app,您必须将app = app || {}; 移出IIFE 范围并将其放在文件的开头并将其声明为全局变量:var app = app || {};。如果有多个主干文件,它们都应该实现类似的结构,以便app 是全局的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-17
    • 2013-01-15
    • 1970-01-01
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多