【问题标题】:Using Jurassic to precompile a JsRender template server-side使用 Jurassic 预编译一个 JsRender 模板服务器端
【发布时间】:2014-05-29 19:13:05
【问题描述】:

我正在尝试从用 C# 编写的类库中预编译 JsRender 模板,使用侏罗纪脚本引擎来执行 JsRender。

这是我的代码:

var engine = new Jurassic.ScriptEngine();
engine.Execute(JsRenderContents);    
var precompiledTemplate = engine.CallGlobalFunction<string>(String.Concat("$.templates(\"", template, "\");"));

我从 this page 获取了 JavaScript 函数调用 $.templates(),它声明

$.templates(markupOrSelector) 返回:已编译的模板对象

我的示例 HTML 模板很简单

<li>{{:Name}}</li>

但是,我的代码产生了异常:

'$.templates("<li>{{:Name}}</li>");' is not a function.

现在,我不是 100% 清楚是否可以在没有 jQuery 的情况下使用 $ 运算符。作者在他的几个示例中包含了 jQuery,但也声明 jQuery 不是必需的。

所以出了什么问题?在我发布此问题的同一天,从 GitHub 获取的 JsRender 版本的文档是否已过期? (我知道 JsRender 仍处于测试阶段。)或者我在滥用侏罗纪?

编辑:

我相信这实际上是一个侏罗纪问题而不是 JsRender 问题。具体来说,我认为这与侏罗纪的全局对象有关,因为 JsRender 被包装在一个通过 this 的立即调用函数中,我不确定侏罗纪是否提供了 this

看来我不是第一个面对这个问题的人。我已从 this page 上的最后一篇文章中获得建议,并将我的代码更改为以下内容:

var engine = new Jurassic.ScriptEngine();
engine.Execute(JsRenderContents);
engine.Global["window"] = engine.Global;
var precompiledTemplate = engine.CallGlobalFunction<string>(String.Concat("window.jsviews.templates(\"", template, "\");"));

这不起作用 - 可能是因为 JsRender 的 IIF 仍然通过 this 而不是 window,我不想修改脚本。

任何人都可以帮助推动这一进程吗?鉴于侏罗纪……我不知道……也许侏罗纪实现全局对象的方式存在一些概念上的差异。

【问题讨论】:

    标签: javascript templates jsrender jurassic precompiled-templates


    【解决方案1】:

    我正在使用 jsRender + Jurassic 来预编译我的模板并在 T4 中生成 js 文件。 我花了很多时间解决这个问题并没有找到答案,但是阅读了一些文章,这很有帮助。

    查看我的代码。它在我的情况下工作。如果这没有帮助,我相信我可以帮助您解决问题:

    var engine = new Jurassic.ScriptEngine();
    
    var jsRenderPath = "/pathToDir/jsrender.js";
    var jsUnevalPath = "/pathToDir/jsRenderUtils.js";
    engine.ExecuteFile(jsRenderPath);
    engine.ExecuteFile(jsUnevalPath);
    
    engine.Evaluate("function renderTemplate(name, markup) { var tmpl = this.jsviews.templates(name, markup); return uneval(tmpl); }");
    
    var compiledTemplateString = engine.CallGlobalFunction<string>("renderTemplate", templateName, templateString);
    
    var result = "$.templates['" + templateName + "'] = " + compiledTemplateString + ";";
    

    jsRenderUtils.js 内容(uneval 函数)

    function uneval(obj, known) {
        var root = (known === undefined), result;
        known = known || [];
    
        // some values fail eval() if not wrapped in a ( ) parenthesises
        var wrapRoot = function (result) {
            return root ? ("(" + result + ")") : result;
        };
    
        // special objects
        if (obj === null)
            return "null";
        if (obj === undefined)
            return "undefined";
        if (obj !== obj) // isNaN does type coercion, so can't use that.
            return "NaN";
        if (obj === Infinity)
            return "Infinity";
        if (obj === -Infinity)
            return "-Infinity";
    
        // atoms
        switch (typeof obj) {
            case 'function':
                return wrapRoot(obj.toString());
            case 'number':
            case 'boolean':
                return obj.toString();
            case 'string':
                return "\"" + obj.toString() + "\"";
        }
    
        // circular reference check for non-atoms
        if (known.indexOf(obj) !== -1)
            return "null";//throw new Error("Circular references detected while unevaling.");
    
        known.push(obj);
    
        // specialized types
        if (obj instanceof Array)
            return "[" + obj.map(function (o) { return uneval(o, known); }).join(",") + "]";
    
        if (obj instanceof Date)
            return wrapRoot("new Date('" + obj.toString() + "')");
    
        // hashes
        var key, pairs = [];
        for (key in obj) {
            var val;
            switch (key) {
                case "render":
                    val = "$.fn.render";
                    break;
                case "markup":
                    val = "null";
                    break;
                default:
                    val = uneval(obj[key], known);
            }
            pairs.push("\r\n" + key + " : " + val);
        }
    
        return wrapRoot("{" + pairs.join(",") + "}");
    
    };
    

    更新:如果你将在没有 jquery 的情况下呈现模板,你应该添加这个:

    $ = window.jsviews;
    $.fn = {
        render: function (data, view, j, u) {
            return this.fn(data, view, j, u);
        }
    };
    

    【讨论】:

    • 我有一个由&lt;li&gt;{{:Name}}&lt;/li&gt; 组成的非常简单的模板,它会输出(由于 SO 格式,您必须将其复制粘贴到文本编辑器中并自行格式化以进行检查): testJSTemplate: ({ markup : null, tmpls : [], links : {}, tags : {}, bnds : [], _is : "template", render : $.fn.render, tmplName : "testJSTemplate", htmlTag : "li", fn : function anonymous(data, view, j, u) { // testJSTemplate var j=j||jsviews,v,ret=""; try{ ret+="&lt;li&gt;"; ret+=(v=data.Name)!=u?v:""; ret+="&lt;/li&gt;"; return ret; }catch(e){ return j._err(e); } } })
    • 你觉得这样对吗?我无法完全自行检查,因为我在使用模板时遇到了其他问题,但不想在回复您的答案之前离开太久。
    • @awj 是的,它是正确的。重要的提醒。您应该使用$.templates['" + templateName + "'] 才能使用嵌套模板(includefor)我创建了jsfiddle 并发现,如果没有jquery,您必须定义$$.fn.render。请检查一下:http://jsfiddle.net/krPnp/2/
    • 非常感谢您的帮助,@Marat。在你回答之前,我已经放弃了这个想法。
    • 不客气!)我很高兴我在这方面的研究帮助了除我之外的其他人。
    【解决方案2】:

    JsRender 可以在没有 jQuery 的情况下使用。

    它的工作方式是对于像var compiledTemplate = $.templates(...); 这样的调用,如果没有加载jQuery,那么你应该设置$ = window.jsviews(或等效的,例如this.jsviews,在服务器上时)。

    所以你真的在打电话:

    compiledTemplate = this.jsviews.templates(...);
    

    这里有一个例子:http://borismoore.github.io/jsrender/demos/step-by-step/20_without-jquery.html(这里是代码https://github.com/BorisMoore/jsrender/blob/master/demos/step-by-step/20_without-jquery.html)。

    这里还有很多单元测试:http://borismoore.github.io/jsrender/test/unit-tests-jsrender-no-jquery.html(代码:https://github.com/BorisMoore/jsrender/blob/master/test/unit-tests-jsrender-no-jquery.html)。

    稍后将在http://www.jsviews.com 上添加更多有关此场景的文档/示例。

    【讨论】:

    • 感谢您的帮助,鲍里斯 - 从马的嘴里听到它总是很高兴(可以这么说)。不幸的是,错误几乎是一样的。我已将precompiledTemplate 声明中的String.Concat 更改为现在"this.jsviews.templates(\"", template, "\");",但现在抛出的异常是'this.jsviews.templates("&lt;li&gt;{{:Name}}&lt;/li&gt;");' is not a function. 我认为这更像是侏罗纪问题而不是JsRender 问题,并将编辑我的问题以反映这个。
    猜你喜欢
    • 1970-01-01
    • 2013-12-30
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    • 2015-04-04
    • 2016-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多