【问题标题】:Not able to set and access a dynamic variable in a JSRender loop无法在 JSRender 循环中设置和访问动态变量
【发布时间】:2021-03-04 20:09:34
【问题描述】:

我有一个循环,我只想在项目名称更改时显示标题。

所以我想设置一个变量 previousProject 并在 IF 语句中进行比较。

我尝试如下,设置它: {{* window.previousProject=:project}} 如下,阅读它: {{* if window.previousProject==:project}}

但我无法让它工作。

更新:

我想要完成的是:

HEADER 1 (This only prints on the first occurrence of HEADER 1)
ITEM 1.1
ITEM 1.2
ITEM 1.3
...
HEADER 2 (This only prints on the first occurrence of HEADER 2)
ITEM 2.1
ITEM 2.2
ITEM 2.3
...

所以 HEADER 实际上就是 data.project。

第一次,当 header 未定义时,我需要打印一个开头的 div + header

每次检测到新标题时,我都需要打印一个关闭 div 和一个打开 div + header

最后一次(迭代中的最后一行)我需要打印一个结束 div

【问题讨论】:

    标签: variables jsrender


    【解决方案1】:

    我不确定我是否正确理解了您的预期行为(例如,project 是您传递给 render(data) 的数据上的变量 data.project, 或者它是在模板之外全局定义的 JavaScript var。但无论如何,你上面有一些语法错误,包括:project

    这是一个您可以尝试的工作示例,它可能会对您有所帮助。

    <script id="myTemplate" type="text/x-jsrender">
    {{* window.previousProject=data.project;}}
    
    {{* if (window.previousProject==data.project) { }}
        A {{*:data.project}} {{:project}}
    {{* } else { }}
        B {{*:window.previousProject}}
    {{* } }}
    
    {{* window.previousProject="Other project"; }}
    
    {{* if (window.previousProject==data.project) { }}
        A {{*:data.project}} {{:project}}
    {{* } else { }}
        B {{*:window.previousProject}}
    {{* } }}
    </script>
    
    <div id="result"></div>
    
    <script>
    var data = {project: "My project"};
    
    $.views.settings.allowCode(true);
    
    var html = $("#myTemplate").render(data);
    
    $("#result").html(html);
    </script>
    

    更新

    也就是说,我不确定您是否真的需要使用allowCode(true)。根据您对场景的额外解释,这里有几个备选方案:

    如果你有这些数据

    data = {projects: [
    {project: "Header1", item: "Item 1.1"},
    {project: "Header1", item: "Item 1.2"},
    {project: "Header1", item: "Item 1.3"},
    {project: "Header2", item: "Item 2.1"},
    {project: "Header2", item: "Item 2.2"},
    {project: "Header2", item: "Item 2.3"},
    {project: "Header3", item: "Item 3.1"},
    {project: "Header3", item: "Item 3.2"},
    {project: "Header3", item: "Item 3.3"}
    ]};
    

    您可以使用在模板渲染期间更改状态的方法,但无需使用 allowCode(true) 公开完整的 javascript。而是通过 get/set 模式传入 ~previousProject() 助手:

    var _prevProject = ""; //initial state
    
    var html = $("#myTemplate").render(data, {
        prevProject: function(val) {
            if (val===undefined) {
                return _prevProject;
            } else {
                _prevProject=val;
                return "";
            }
        }
    });
    

    使用以下模板:

    <script id="myTemplate" type="text/x-jsrender">
    {{for projects}}
      {{if !~prevProject()}}
        <div>{{:project}} {{:item}}
      {{else ~prevProject()===project}}
        {{:item}}
      {{else}}
        </div><div>{{:project}} {{:item}}
      {{/if}}
      {{:~prevProject(project)}}
    {{/for}}
    </div>
    </script>
    

    但实际上你根本不需要动态设置状态,而是可以直接访问数组项来测试project,如下面的模板。 (不需要辅助函数):

    <script id="myTemplate" type="text/x-jsrender">
    {{for projects ~projects=projects}}
      {{if #getIndex()===0}}
        <div>{{:project}} {{:item}}
      {{else}}
        {{if ~projects[#getIndex()-1].project===project}}
          {{:item}}
        {{else}}
          </div><div>{{:project}} {{:item}}
        {{/if}}
      {{/if}}
    {{/for}}
    </div>
    </script>
    

    如果可能,最好使用 JsRender 标准标签,而不是将 allowCode 设置为 true 并将 javascript 代码插入模板...

    添加:

    上述解决方案工作正常,但模板不是很容易维护或理解,并且不遵循或揭示输出的自然层次结构。所以另一种选择是使用filter property:{{for filter=...}},如下所示:

    帮手

    var html = $("#myTemplate").render(data, {
        header: function(item, index, items) {
            if (index===0 || item.project!==items[index-1].project) {
                _prevProject=item.project;
                return true;
            }
        },
        items: function(item, index, items) {
            return item.project===_prevProject;
        }
    });
    

    模板:

    <script id="myTemplate" type="text/x-jsrender">
    {{for projects filter=~header ~projects=projects}}
      <div>
        {{:project}}
        {{for ~projects filter=~items}}
          {{:item}}
        {{/for}}
      </div>
    {{/for}}
    </script>
    

    【讨论】:

    • 这确实是我的意思;项目是data.project。除了您的模板在开头设置{{* window.previousProject=data.project;}} 使(window.previousProject==data.project) 始终为真,因此需要在末尾设置。
    • 不幸的是,这不起作用。我将更新原始帖子以解释我要完成的工作。
    • 这正是我正在寻找的解决方案。我昨天想出的解决方法是在项目对象中添加打开/关闭的布尔道具。非常感谢您清晰而详细的解释。
    • 在上面添加了另一个替代方法,在 {{for}} 上使用过滤器
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-17
    相关资源
    最近更新 更多