带骨干模板的把手不能渲染 [英] Handlebars with Backbone template not rendering

查看:79
本文介绍了带骨干模板的把手不能渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

服务器



安装了Backbone和Express-Handlebars
$ b $ p 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>发送讯息< / h1>
< / div>
< div id =contact>< / div>
< / div>
....一些代码

< script id =tmpl-contacttype =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()) ,
事件:{
'提交表单':'preventSubmit',
'点击.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();
},
联系方式:function(){
this。$ el.find('。btn-contact')。attr('disabled',true);

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

会发生什么情况是index.hbs在服务器端正常渲染,但它不会渲染形式内部脚本;它显示为空< div id =contact>< / div> 并且不会在控制台中显示任何错误。



如此处所示使用带骨架的把手,一种替换下划线模板的方法与handlebars只是用 Handlebars.compile 替换 _。template ,但这些选项都不适用于我。我也为< script> 尝试了不同的 type 属性,并且它仍然不起作用。

<我怎样才能解决这个问题?任何帮助表示赞赏。

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



  / *全球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 :{
'提交表单':'preventSubmit',
'点击.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();
},
prevent tSubmit:function(event){
event.preventDefault();
},
contact:function(){
this。$ el.find('。btn-contact')。attr('disabled',true);
$ b $ this.model.save({
name:this。$ el.find('[name =name]')。val(),
email:this 。$ el.find('[name =email]')。val(),
message:this。$ el.find('[name =message]')。val()
});
}
});
$ b $(document).ready(function(){
app.contactView = new app.ContactView();
});
}());


解决方案

如上所述 Handlebars .compile 必须在< script>< / script> 中的句柄模板加载到DOM后加载。在这种情况下,当使用express-hanldebars时,必须在主布局中的 {{{body}}} 元素之后放置js文件的链接。这是正确的答案。



还有一个问题是, app 无法全局定义为它出现在 index.js



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

I have an app which uses both Backbone and Handlebars on a server and a client.

Server

Backbone and Express-Handlebars installed

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>

Client

On the client I have Backbone and Handlebars installed via Bower

In 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()
      });
    }
  });

What happens is that index.hbs renders on the server-side normally, but it is not rendering a form inside script; it shows empty <div id="contact"></div> and doesn't shows any errors in console.

As shown here Using Handlebars with Backbone, a way to replace underscore templating with handlebars is simply to replace _.template with Handlebars.compile, but neither of these options works for me. I also tried different type attributes for <script> and it's still not working.

How can I fix this? Any help is appreciated. Thanks.

Added full index.js on client

/* 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();
  });
}());

解决方案

So as mentioned here Handlebars.compile must load after handlebars template in <script></script> is loaded into the DOM. In this case when using express-hanldebars, a link to js file must be placed after {{{ body }}} element in the main layout. That is the right answer.

There is one more problem here that app can't be defined globally as it appears in index.js

In order to define app globally you have to move app = app || {}; outside the IIFE scope and put it at the beginning of a file and declare it as a global variable: var app = app || {};. If there are multiple backbone files they should all implement a similar structure in order to app be global.

这篇关于带骨干模板的把手不能渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆