JavaScript/jQuery/AAJAX中的嵌套模板

Nested Templates in JavaScript/jQuery/AJAX

本文关键字:嵌套 jQuery AAJAX JavaScript      更新时间:2023-09-26

我正在尝试完成一个需要使用嵌套模板的模块,但我一直在思考如何做到这一点。

在我的UI中基本上有三个级别,例如级别1、级别2、级别3。所以当页面显示时,我只需要渲染级别1。但是,当用户单击级别1的任何元素的"展开"按钮时,我需要在级别1的选定元素下方呈现级别2的相应元素(不是全部)。

现在,当用户单击级别2的任何元素的"展开"时,应呈现相应的级别3。。

总之,它应该和左边的Windows资源管理器的导航栏一样。!

通常,您应该为每个级别定义单独的组件,为每个组件分配模板,并实现类似expand()/collapse()的方法。如果一个组件最初是折叠的(您的情况),那么它不应该在初始化时渲染子项,它只会在您展开它们时渲染它们(将使用子组件的适当模板)。

请提供一个你正在努力工作的基本代码,这样会更容易帮助你。

这里有一个Widget系统的快速原型,它有一个使用模板的简单渲染流。我想你的申请中应该有类似的内容。它是未优化的,它只是你的框架可能看起来的一个想法。

/**
 * Widget constructor
 */
var Widget = function(config) {
    // apply config
    $.extend(this, config);
    // attempt to render
    this.render();
};
/**
 * Widget prototype
 */
$.extend(Widget.prototype, {
    // render target
    renderTo: null,
    // template
    tpl: '<div class="container-panel">' +
            '<p>${txt}</p>' +
            '<div class="items-container"></div>' +
        '</div>',
    // template data
    tplData: null,
    // child items array
    children: null,
    // initial collapsed state
    collapsed: false,
    // widget's root element
    el: null,
    // default render target selector for child items
    renderTarget: '.items-container',
    render: function() {
        var me = this,
            renderDom
        // render the widget
        if(!this.rendered && this.renderTo && this.tpl) {
            renderDom = $.tmpl(this.tpl, this.tplData);
            // assume that first element is widget's root element
            this.el = renderDom[0];
            $(this.renderTo).append(renderDom);
             // clear the reference
            renderDom = undefined;
            // THIS IS JUST EXAMPLE CODE! Bind click handler...
            $(this.el).find('p').first().click(function() {
                me.collapsed ? me.expand() : me.collapse();
            });    
            // find render target for children
            this.renderTarget = $(this.el).find(this.renderTarget).first();
            // render children if not collapsed
            this.renderChildren();
            // set rendered flag
            this.rendered = true;
        }
    },
    renderChildren: function() {
        var children = this.children;
        if(!this.collapsed && children && children.length) {
            for(var i = 0, len = children.length; i < len; i++) {
                // render children inside 
                children[i].renderTo = this.renderTarget;
                children[i].render();
            }
        }
    },
    /**
     * Expand template method. Override it.
     */   
    expand: function() {
        this.collapsed = false;
        this.renderChildren();
        this.renderTarget.show();
    },
    /**
     * Collapse template method. Override it.
     */    
    collapse: function() {
        this.collapsed = true;
        this.renderTarget.hide();
    }
});

​在这里,我预定义了模板,并硬编码了在小部件的第一个段落元素中单击时发生的扩展/折叠逻辑。

这就是您使用小部件的方式:

// Using our widgets
var containerPanel = new Widget({
    tplData: {txt: 'Hello world!'},
    renderTo: $('body'),
    collapsed: true,
    children: [
        new Widget({
            tplData: {txt: '&nbsp;&nbsp;Child 1'},
            collapsed: true,
            children: [
                new Widget({
                    tplData: {txt: '&nbsp;&nbsp;&nbsp;&nbsp;Child 1.1'}
                }),
                new Widget({
                    tplData: {txt: '&nbsp;&nbsp;&nbsp;&nbsp;Child 1.2'}
                }),
                new Widget({
                    tplData: {txt: '&nbsp;&nbsp;&nbsp;&nbsp;Child 1.3'}
                })
            ]
        }),
        new Widget({
            tplData: {txt: '&nbsp;&nbsp;Child 2'}
        })
    ]
});

您可以在jsFiddle上看到一个实际示例:http://jsfiddle.net/dipish/XDmWq/只需单击项目并查看动态生成的标记。

我认为代码是不言自明的,但可以随意提出任何问题。注意,代码使用jQuery模板插件,但这只是为了方便。

如果您的web应用程序中有许多复杂的组件,您可能希望使用比纯jQuery更严肃的组件,如ExtJS或DojoToolkit。这样的框架通常为您提供了一个方便的类系统和基本的小部件/组件逻辑来构建,此外还有很多其他功能。

祝你好运!

您需要更具体地了解标记的外观。然而,这里有一个粗略的例子:

//run this puppy when we need to append stuff
var dynamicAppend = function( data, container )
{
  var ul = container.children().slice(1,2);
  var len = data.length;
  for( var i = 0; i < len; i++ )
  {
    var markup = [
     "<li class='" + data[i].thing + "'>",
       "<span class='second_toggle' data-stuff='" + data[i].other_thing + "'></span>",
       "<ul>",
       "</ul>",
     "</li>"
    ];
    ul.append( markup.join() );
  }
}
//do ajax stuff
var handleAjax = function( data, container )
{
  var json = { unique: data }
  $.ajax({
    url: '',
    data: json,
    success: function( data )
    {
      if( data.success === 'your_flag' && data.newStuff )
      {
        dynamicAppend( data.newStuff, container );
      }
    }
  });
}
//first, you'll click the toggle
var expand_toggle = $( '.toggle' );
expand_toggle.click(function(e){
  var that = $(this);
  //grab some data that identifies the unique container you want to append to
  var unique_id = that.data( 'some_identifier' );
  var container = that.parents('.parent_container_class:first');
  handleAjax( unique_id, container );
});

我个人会把它放进一个构造函数中,并以OOP风格进行,但你可以理解这个想法。

这里有一些标记:

<div class='parent_container_class'>
  <span class='toggle' data-some_identifier='special_identifier_here'></span>
  <ul></ul>
</div>