多级ul li backbone.js

时间:2013-05-07 11:23:02

标签: javascript jquery backbone.js

我尝试使用backbone.js进行嵌套导航。下面是我的代码。

Json数据:

[
{"id":1,"name":"one","parent_id":0},
{"id":2,"name":"two","parent_id":0},
{"id":3,"name":"three","parent_id":0},
{"id":4,"name":"four","parent_id":0},
{"id":5,"name":"five","parent_id":0},
{"id":6,"name":"one","parent_id":2},
{"id":7,"name":"two","parent_id":2},
{"id":8,"name":"three","parent_id":2},
{"id":9,"name":"four","parent_id":2},
{"id":10,"name":"five","parent_id":2},
]

Html:

<ul>
    <li><a href="#">one</a></li>
    <li><a href="#">two</a>
        <ul>
            <li><a href="#">one</a></li>
            <li><a href="#">two</a></li>
            <li><a href="#">three</a></li>
            <li><a href="#">four</a></li>
            <li><a href="#">five</a></li>
        </ul>
    </li>
    <li><a href="#">three</a></li>
    <li><a href="#">four</a></li>
    <li><a href="#">five</a></li>
</ul>

和Backbonejs代码在这里:

var MenuList = Backbone.View.extend({
    tagName: 'ul',
    id: 'menu-trial-task',
    initialize: function() {
            this.collection = new ItemCollection();
            this.collection.on('sync', this.render, this);
            this.collection.fetch();       
    },
    render: function() {
        _.each( this.collection.models, function( item ) {
            this.$el.append( new MenuItem({model:item}).render().el );
        }, this);
    $('nav').html(this.$el);    
        return this;
    }
});

var MenuItem = Backbone.View.extend({
    tagName: 'li',
    initialize: function() {
        this.template = _.template($('#munu_itemt_view').html());
    },
    render: function() {
        this.$el.html( this.template( this.model.toJSON()));
        return this;
        }
});     
var menuList = new MenuList();

结果是:

<ul>
    <li><a href="#">one</a></li>
    <li><a href="#">two</a></li>
    <li><a href="#">three</a></li>
    <li><a href="#">four</a></li>
    <li><a href="#">five</a></li>
    <li><a href="#">one</a></li>
    <li><a href="#">two</a></li>
    <li><a href="#">three</a></li>
    <li><a href="#">four</a></li>
    <li><a href="#">five</a></li>    
</ul>

你可以看到这不是必需的结果。

我也试过使用underscore.js但是失败了。有没有好的和简单的方法来做到这一点?

3 个答案:

答案 0 :(得分:1)

尝试使用嵌套视图,我建议使用模板

var data = [
    {"id":1,"name":"one","parent_id":0},
    {"id":2,"name":"two","parent_id":0},
    {"id":3,"name":"three","parent_id":0},
    {"id":4,"name":"four","parent_id":0},
    {"id":5,"name":"five","parent_id":0},
    {"id":6,"name":"one","parent_id":2},
    {"id":7,"name":"two","parent_id":2},
    {"id":8,"name":"three","parent_id":2},
    {"id":9,"name":"four","parent_id":2},
    {"id":10,"name":"five","parent_id":2},
]

var NestedView = Backbone.View.extend({
  render: function(){
    this.$el.html( "<ul id='ul-0'></ul>" )
    this.collection.each( function( model ){ this.renderElement( model ) }, this )
  },

  renderElement: function( model ){
    var ul = this.getParentUl( model );
    this.appendElement( ul, model );
  },

  getParentUl: function( model ) {
    var ul = this.$el.find( "#ul-" + model.get( "parent_id" ) );
    if( ul.length == 0 ) {
      this.appendListInElement( model );
      ul = this.$el.find( "#ul-" + model.get( "parent_id" ) );
    }

    return ul;
  },

  appendListInElement: function( model ){
    var li = this.$el.find( "#li-" + model.get( "parent_id" ) );
    li.after( "<ul id='ul-" + model.get( "parent_id" ) + "'></ul>" );
  },

  appendElement: function( ul, model ){
    ul.append( "<li id='li-" + model.get( "id" ) + "'>" + model.get( "name" ) + "</li>" );
  }
});

var elements = new Backbone.Collection( data );
var nestedView = new NestedView({ el: "#wrapper", collection: elements });
nestedView.render();


<div id="wrapper"></div>

这是完整的代码,带有下划线模板

<!DOCTYPE html>
<html>
<head>
    <title>Backbone</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script type="text/javascript" src="http://underscorejs.org/underscore.js"></script>
    <script type="text/javascript" src="http://backbonejs.org/backbone.js"></script>

    <script type="text/template" id="parent-template">
        <ul id='ul-<%= parent_id %>'></ul>
    </script>
    <script type="text/template" id="child-template">
        <li id="li-<%= id %>"><%= name %></li>
    </script>

    <script type="text/javascript">

    var compiledParent = _.template( $('#parent-template').html() );
    var compiledChild = _.template( $('#child-template').html() );

    var data = [
        {"id":1,"name":"one","parent_id":0},
        {"id":2,"name":"two","parent_id":0},
        {"id":3,"name":"three","parent_id":0},
        {"id":4,"name":"four","parent_id":0},
        {"id":5,"name":"five","parent_id":0},
        {"id":6,"name":"one","parent_id":2},
        {"id":7,"name":"two","parent_id":2},
        {"id":8,"name":"three","parent_id":2},
        {"id":9,"name":"four","parent_id":2},
        {"id":10,"name":"five","parent_id":2},
    ];

    var NestedView = Backbone.View.extend({
      render: function(){
        this.$el.html( compiledParent({parent_id : '0'}) );
        this.collection.each( function( model ){ this.renderElement( model ) }, this )
      },

      renderElement: function( model ){
        var ul = this.getParentUl( model );
        this.appendElement( ul, model );
      },

      getParentUl: function( model ) {
        var ul = this.$el.find( "#ul-" + model.get( "parent_id" ) );
        if( ul.length == 0 ) {
          this.appendListInElement( model );
          ul = this.$el.find( "#ul-" + model.get( "parent_id" ) );
        }

        return ul;
      },

      appendListInElement: function( model ){
        var li = this.$el.find( "#li-" + model.get( "parent_id" ) );
        li.after( compiledParent({parent_id : model.get( "parent_id" )}) );
      },

      appendElement: function( ul, model ){
        ul.append( compiledChild({id:model.get( "id" ) , name:model.get( "name" )}) );
      }
    });

    $(document).ready(function()
    {
        var elements = new Backbone.Collection( data );
        var nestedView = new NestedView({ el: "#wrapper", collection: elements });
        nestedView.render();
    });
    </script>
</head>
<body>
    <div id="wrapper">
    </div>
</body>
</html>

答案 1 :(得分:1)

这个怎么样,我认为按照你想要的菜单来构建你的json会更好。

您也不应忘记将嵌套的ul置于li内,否则无效。

它没有像我说的那样使用模板,但我认为它能够很好地完成工作。 它只需要jquery就可以工作。

var menu = [
    {name:"one"},
    {
        name:"two",
        nodes: [
            {name:"one"},
            {name:"two"},
            {name:"three"},
            {name:"four"},
            {name:"five"}
        ]
    },
    {name:"three"},
    {name:"four"},
    {name:"five"}
];

function createMenu(menuItem)
{
    var list = $("<ul>");
    $.each (menuItem, function(indexInArray, currentItem){
        var li = $("<li>").html(currentItem.name);
        if (currentItem.nodes)
            li.append(createMenu(currentItem.nodes));
        list.append(li);
    });
    return list;
}

$("body").append(createMenu(menu));

小提琴: http://jsfiddle.net/3gjkZ/2/

答案 2 :(得分:1)

像这样改变渲染:

render: function() {
   this.$el.html( this.template( items : this.model.toJSON()));
   return this;
}

和这样的模板:

<ul>
   <li><a href="#">${name}</a>
      <ul> {each items}
          <li><a href="#">${name}</a></li>
      </ul>
   </li>
</ul>

我使用jquery模板,您可以将其更改为下划线