Node.js with Handlebars.js on server and client

前端 未结 7 2411
抹茶落季
抹茶落季 2020-12-02 08:21

I have an app in Node.js using Expressjs and Handlebars as the template engine.

Expressjs uses layouts and then renders views. The layout (layout.hbs) looks like th

相关标签:
7条回答
  • 2020-12-02 08:26

    An easy way to do this is to just append a \ before the {{ in a Handlebars file. For example:

    <script type="text/x-template" id="todo-item-template">
    <div class="todo-view">
        <input type="checkbox" class="todo-checkbox" \{{checked}}>
        <span class="todo-content" tabindex="0">\{{text}}</span>
    </div>
    
    <div class="todo-edit">
        <input type="text" class="todo-input" value="\{{text}}">
    </div>
    
    <a href="#" class="todo-remove" title="Remove this task">
        <span class="todo-remove-icon"></span>
    </a>
    

    The above code will be rendered on the client with the {{..}} tags preserved.

    0 讨论(0)
  • 2020-12-02 08:26

    You have 2 options. The second is THE best way to go:

    1) Escape the mustaches

    <script type="text/x-handlebars" data-hbs="example">
      <p>\{{name}}</p>
    </script>
    

    2) Precompile

    This will compile the template on the server before it goes to the client. This will make the template ready to use and reduces the burden on the browser.

    0 讨论(0)
  • 2020-12-02 08:30

    I didn't like the precompilation solution (because I want to define templates in the same file where I will use them) nor the naive \{{ escape solution (because it needs the full Handlebars compiler and more javascript code) so I came up with an hybrid solution that uses Handlebars' helpers:

    1) Register a new helper called "template" on server configuration

    var hbs = require('hbs');
    hbs.registerHelper("template", function(key, options){
        var source = options.fn().replace("\\{{", "{{");
        var ret =
        '<script>\n' + 
            key + ' = function(opt){\n' +
                'return Handlebars.template(' + hbs.handlebars.precompile(source) + ')(opt);\n' +
            '}\n' + 
        '</script>';
        return ret;
    });
    


    2) Use it anywhere in your client-side webpage (with \{{ escape for client-side parameters)

    {{#template "myTemplate"}}
        <div>
            <p>Hello \{{this.name}}!</p>
        </div>
    {{/template}}
    

    (the server will precompile it in something like this)

    <script>
        myTemplate = function(opt){
            return Handlebars.template(/* HBS PRECOMPILATED FUNCTION */)(opt);
        }
    </script>
    


    3) Simply call the function where you need it in client-side javascript

    var generatedHtml = myTemplate("world");   // = <div><p>Hello world!</p></div>
    $("#myDiv").html(generatedHtml);           // or whatever
    
    0 讨论(0)
  • 2020-12-02 08:31

    I have worked around this by passing client-side templates through server-side templates.

    So on the server-side read all your client-side templates to an array and pass it to your render function on the server-side

    In your route handler do something like:

    readTemplates(function(err, clientTemplates) {
      res.render("page", {
        clientTemplates: clientTemplates;   
      });
    });
    

    And then in layout.hbs:

    {{#each clientTemplates}}
    <script type="text/handlebars id="{{this.filename}}" >
    {{{this.template}}}
    </script>
    {{/each}}
    

    Here I'm using file names without extensions as the template id so that they can be referenced from Backbone views. Oh, and remember to implement caching for production mode.

    Yeah, this sucks.

    I think we should write a Handlebars/Express/Connect helper for this.

    0 讨论(0)
  • 2020-12-02 08:32

    You should use pre-compiled client templates. They are faster executing and allow you to use the same template language on the server and client.

    1. Install handlebars globally npm install handlebars -g
    2. Precompile your templates handlebars client-template1.handlebars -f templates.js
    3. Include templates.js <script src="templates.js"></script>
    4. Execute the template var html = Handlebars.templates["client-template1"](context);

    https://stackoverflow.com/a/13884587/8360

    0 讨论(0)
  • 2020-12-02 08:36

    Shameless self-promotion!

    I wanted to do this same client/server sharing thing, so I wrote a little npm package to assist:

    node-handlebars-precompiler

    I whipped it up in a couple hours based on the command-line compiler in wycats' handlebars repo. It's not the greatest code in the world, but it's been getting the job done for me very well.

    EDIT: I am no longer maintaining this package. If you would like to take over, please contact me via Github. I mainly use Jade templates now, so it doesn't make sense for me to continue as the maintainer.

    0 讨论(0)
提交回复
热议问题