8

私は数か月間 nunjucks を使用しており、優れたテンプレート エンジンであることがわかりました。しかし、今朝、単純に見える問題に遭遇しましたが、それを理解することはできません。別の目が解決策を示すのに役立つことを願っています.

問題: テンプレートに関数を渡すと、その関数に渡された引数は関数本体内で定義されていません。

値とオブジェクトは問題なくテンプレートに渡すことができます。関数を渡すと、関数内からコンソールにログを記録できます (関数自体がそこにあることがわかります) が、引数はすべて未定義です。

これは最初はクロージャーで解決できるもののように思えましたが、1) 私が見つけたどの例にもクロージャーが見られず、2) クロージャーを試したところ、それらも未定義の引数を受け取ることがわかりました。

一日を通して、コードを可能な限り単純なケースに戻しましたが、まだこれを理解できません。

テンプレート:

<div>

<p>{{ value }}</p>

<p>{{ object|pretty }}</p>

<p>{{ func(4) }}</p>

<p>{{ args(4)|pretty }}</p>

<p>{{ local(4) }}</p>

</div>

テンプレートをレンダリングするコード (これは、requirejs 定義内にありますが、表示されていません):

    var nunjucks = require('lib/nunjucks-slim.min'), // v1.3.4
        env = new nunjucks.Environment(null), // global templates
        $tgt = $('#test'),
        local;

    env.addGlobal('value', 3);

    env.addGlobal('object', {
        a: 2
    });

    env.addFilter('pretty', function (obj) {
        return JSON.stringify(obj, null, 2);
    });

    env.addGlobal('func', function (val) {
        return 'func: ' + val;
    });

    env.addGlobal('args', function () {
        return arguments;
    });

    local = function (val) {
        return 'local: ' + val;
    };

    $tgt.html(env.render('test.nj', {
        'local': local
    }));

レンダリングされた HTML は次のようになります。

3                  // value

{ "a": 2 }         // object|pretty

func: undefined    // func

{}                 // args

local: undefined   // local

したがって、値は問題ありません。オブジェクトも同様に機能し、「きれいな」フィルターを通過した後も見栄えがします。

ただし、「func」に渡される値は関数本体で未定義になり、関数内で引数変数を使用しても役に立ちません。さらに、関数をテンプレート コンテキスト (ローカル) に直接渡すこともできません。

フィルター (基本的には単なる関数) は正常に機能しますが、通常の関数は、テンプレート コンテキストの一部として渡されるか、グローバルとして渡されるかに関係なく機能しません。

役立つかもしれないいくつかのメモ:

  • 私はrequirejsを使用していますが(nunjucks自体のインポートを除く)、方程式から排除しようとしました。

  • この例では、nunjucks v1.3.4 を使用しています。デバッグの過程で、v2.1 でこの動作を確認しようとしましたが、v2.x では requirejs の互換性が壊れている可能性があり、2 つの問題に並行して取り組みたくありませんでした。

  • grunt-nunjucks を使用してテンプレートをプリコンパイルし、結果を醜くしています。私の Gruntfile の関連部分は次のとおりです。

    module.exports = function (grunt) {
    'use strict';
    
    grunt.initConfig({
    
    pkg: grunt.file.readJSON('package.json'),
    
    nunjucks: {
        common: {
            baseDir: 'site/',
            src: [
                'site/core/**/*.nj'
            ],
            dest: 'application/static/js/common.js'
        },
    },
    
    uglify: {
        templates: {
            options: {
                preserveComments: false,
                mangle: true,
                compress: {
                    dead_code: true,
                    loops: true,
                    conditionals: true,
                    booleans: true,
                    unused: true,
                    if_return: true,
                    join_vars: true,
                    drop_console: true
                }
            },
            files: {
                'application/static/js/common.min.js': ['application/static/js/common.js'],
            }
        }
    },
    });
    
    grunt.loadNpmTasks('grunt-nunjucks');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    };
    

テスト テンプレート (上に表示) は、common.js にコンパイルされ、上記の設定を使用して common.min.js に醜化されたいくつかのテンプレートの 1 つです。醜くすることなくテンプレートをコンパイルしようとしましたが、同じ結果が得られたことに注意してください。

これは非常に基本的な機能であるため、これがバグであるとすれば、SE やイシュー ログで多くの参照が見られると思いますが、ほとんど見つかりませんでした。本当に明白なものが欠けていると思いますが、それを見つけることができないようです。

何かご意見は?

4

1 に答える 1

2

デバッグを続けた後、最終的に次のテスト セットアップを使用して、醜化と requirejs を方程式から外しました。

index.html:

<html>
<head>
    <script src="nunjucks-slim.js"></script>
    <script src="common.js"></script>
</head>

<body>

    <script src="test.js"></script>
</body>

</html>

common.js にプリコンパイルされている私のテンプレート:

<div>

<p>{{ value }}</p>

<p>{{ object|pretty }}</p>

<p>{{ func(4) }}</p>

<p>{{ func(x) }}</p>

<p>{{ args(4)|pretty }}</p>

<p>{{ local(4) }}</p>

<p>{{ local(x) }}</p>

</div>

test.js は、テンプレートを実行するコードです。

var env = new nunjucks.Environment(null),
    local;

env.addGlobal('value', 3);

env.addGlobal('object', {
    a: 2
});

env.addFilter('pretty', function (obj) {
    return JSON.stringify(obj, null, 2);
});

env.addGlobal('func', function (val) {
    return 'func: ' + val;
});

env.addGlobal('args', function () {
    return arguments;
});

local = function (val) {
    return 'local: ' + val;
};

console.log(env.render('core/root/test.nj', {
    'local': local,
    'x': 4
}));

最後に、問題を示す出力 (コメントを追加):

<div>

<p>3</p>    // value

<p>{
  "a": 2    // object|pretty
}</p>

<p>func: undefined</p>    // func(4)

<p>func: undefined</p>    // func(x)

<p>{}</p>    // args(4)|pretty

<p>local: undefined</p>    // local(4)

<p>local: undefined</p>    // local(x)

</div>

requirejsコンパイルされたテンプレート コードをステップ実行して問題を見つけようとするのに数時間費やしました (ちなみに、これは非常に有益でした) nunjucks v2.1.0

数回クリックすると、テストコードが動作しました。

<div>

<p>3</p>

<p>{
  a: 2
}</p>

<p>func: 4</p>

<p>func: 4</p>

<p>{
  0: 4
}</p>

<p>local: 4</p>

<p>local: 4</p>

</div>

したがって、(v1.3.4 で) 問題を把握して解決できればよかったのですが、答えは「nunjucks v2.1.0 にアップグレードする」ようです。

于 2015-10-03T17:18:38.717 に答える