• RequireJS与Backbone简单整合


    前言

    昨天我们一起学习了Backbone,最后做了一个备忘录的例子,说是做了不如说是看了下官方提供的例子,所以最终我感觉我们还是没能掌握Backbone,今天还得做个其它例子先。

    然后前面也只是草草学习了RequireJS,没做demo,这个周末又在看电影打游戏睡觉瞎折腾,转眼就周日下午了,突然诗性大起,于是作诗一首先:

    古有通宵看A片,今有彻夜码代码

    好吧,我们开始今天的学习吧,我们今天先用backbone做一个通讯录的东西,然后使用requireJS组装之。

    部分参考:the5fire的技术博客

    简单例子

    做之前我们先来个简单的例子:

     1 <html xmlns="http://www.w3.org/1999/xhtml">
     2 <head>
     3     <title></title>
     4 </head>
     5 <body>
     6     <div id="contactapp">
     7         <header>
     8             <h1>
     9                 通讯录</h1>
    10         </header>
    11         <section id="main">
    12             <ul id="contact-list">
    13             </ul>
    14         </section>
    15         <div class="create">
    16             <input type="button" value="增加(弹出框)" id="addDia" />
    17         </div>
    18     </div>
    19 </body>
    20 <script src="js/jquery.js" type="text/javascript"></script>
    21 <script src="js/underscore.js" type="text/javascript"></script>
    22 <script src="js/backbone.js" type="text/javascript"></script>
    23 <script type="text/javascript">
    24     (function ($) {
    25         var Contact = Backbone.Model.extend({
    26             //创建一个contact对象,拥有name属性
    27             name: null
    28         });
    29         var ContackList = Backbone.Collection.extend({
    30             initialize: function (models, options) {
    31                 //contact集合
    32                 this.bind('add', options.view.addOne);
    33             }
    34         });
    35         var AppView = Backbone.View.extend({
    36             el: $('body'),
    37             initialize: function () {
    38                 //实例化集合,并传入AppView对象
    39                 this.contacts = new ContackList(null, { view: this });
    40             },
    41             events: {
    42                 'click #addDia': 'addDia'
    43             },
    44             addDia: function () {
    45                 var name = prompt('请输入姓名');
    46                 var c = new Contact({ name: name });
    47                 this.contacts.add(c);
    48             },
    49             addOne: function (model) {
    50                 $('#contact-list').append('<li>' + model.get('name') + '</li>');
    51             }
    52         });
    53         var app = new AppView();
    54     })(jQuery);
    55 </script>
    56 </html>

    PS:感谢the5fire给出的例子,我和我的小伙伴一下都明白了。。。。

    以上代码涉及到Backbone三个部分:View、Model、Collection,我们在addOne里面使用了jquery绑定dom以后会将之消除。

    各位请看这个代码:

    this.bind('add', options.view.addOne);

    在集合中绑定了add事件,在addDia最后执行了,然后触发集合的事件,才最后将dom添加完成。

    知识回顾(参考the5fire)

    the5fire关于backbone的文章写的很好(http://www.the5fire.com),我们一起来看看顺便回顾下我们的知识。

    model

    Man = Backbone.Model.extend({
            initialize: function(){
                alert('Hey, you create me!');
            }
        });
    var man = new Man;

    这个是一个model最简单的model,initialize中的方法一来就会执行,这里就会弹出框:

    对象赋值

    Man = Backbone.Model.extend({
        initialize: function () {
            alert('Hey, you create me!');
        },
        defaults: {
            name: '张三',
            age: '38'
        }
    });
    var man = new Man;
    alert(man.get('name'));
    //man.set({ name: 'the5fire', age: '10' });

    若是不赋值就使用默认值,若是赋值则采用给的值。

    事件与方法

    Man = Backbone.Model.extend({
        initialize: function(){
            alert('Hey, you create me!');
            //初始化时绑定监听
            this.bind("change:name",function(){
                var name = this.get("name");
                alert("你改变了name属性为:" + name);
            });
        },
        defaults: {
            name:'张三',
            age: '38'
        },
        aboutMe: function(){
            return '我叫' + this.get('name') + ',今年' + this.get('age') + '岁';
        }
    });
    var man = new Man;
    man.set({name:'the5fire'})  //触发绑定的change事件,alert。

    可以定义方法aboutMe,也可以在initialize中绑定事件以监听某个属性的变化。

    验证及错误提示

    Man = Backbone.Model.extend({
        initialize: function () {
            this.bind("error", function (model, error) {
                alert(error);
            });
        },
        validate: function (attributes) {
            if (attributes.name == '') {
                return "name不能为空!";
            }
        },
    });
    var man = new Man;
    man.set({ name: '' }); //根据验证规则,弹出错误提示。

    此处验证不通过便会触发错误提示。

    PS:经测试并没有提示,问题后面跟进

    PS:最后证明有反应,我调试页面用错了

    对象持久化

    对象持久化可以是服务器也可以是本地存储,具体就不展开了。

    collection

    集合其实就是model的有序集合,经过周末的学习,我们应该比较熟悉了:

    Book = Backbone.Model.extend({
        defaults: {    // 感谢网友蓝色动力指正改为defaults
            title: 'default'
        },
        initialize: function () {
            //alert('Hey, you create me!');
        }
    });
    BookShelf = Backbone.Collection.extend({
        model: Book
    });
    var book1 = new Book({ title: 'book1' });
    var book2 = new Book({ title: 'book2' });
    var book3 = new Book({ title: 'book3' });
    //var bookShelf = new BookShelf([book1, book2, book3]); 
    //注意这里面是数组,或者使用add
    var bookShelf = new BookShelf;
    bookShelf.add(book1);
    bookShelf.add(book2);
    bookShelf.add(book3);
    bookShelf.remove(book3);
    //基于underscore这个js库,还可以使用each的方法获取collection中的数据
    bookShelf.each(function (book) {
        alert(book.get('title'));
    });

    fetch

    我们若是要与服务器通讯获取数据,需要先为bookshelf定义url:

    bookShelf.fetch({ url: '/getbooks/', success: function (collection, response) {
        collection.each(function (book) {
            alert(book.get('title'));
        });
    }, error: function () {
        alert('error');
    }
    });
    //对应的BookShelf的返回格式如下:
    [{'title':'book1'},{'title':'book2'}.....]

    此后我们需要将页面的dom与数据同步,所以会用到reset事件;

    bookShelf.bind('reset',showAllBooks);
    showAllBooks = function(){
        bookShelf.each(function(book){
            ​//将book数据渲染到页面。
        });
    }
     1 <html>
     2 <head>
     3     <title>the5fire-backbone-collection</title>
     4 </head>
     5 <body>
     6 </body>
     7 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
     8 <script src="http://ajax.cdnjs.com/ajax/libs/underscore.js/1.1.4/underscore-min.js"></script>
     9 <script src="http://ajax.cdnjs.com/ajax/libs/backbone.js/0.3.3/backbone-min.js"></script>
    10 <script>
    11 (function ($) {
    12     //collection是一个简单的models的有序集合
    13     //1、一个简单的例子
    14 
    15     Book = Backbone.Model.extend({
    16         defaults : {    // 感谢网友蓝色动力指正改为defaults
    17             title:'default'
    18         },
    19         initialize: function(){
    20             //alert('Hey, you create me!');
    21         }
    22     });
    23     BookShelf = Backbone.Collection.extend({
    24         model : Book
    25     });
    26 
    27     var book1 = new Book({title : 'book1'});
    28     var book2 = new Book({title : 'book2'});
    29     var book3 = new Book({title : 'book3'});
    30 
    31     //var bookShelf = new BookShelf([book1, book2, book3]); //注意这里面是数组,或者使用add
    32     var bookShelf = new BookShelf;
    33     bookShelf.add(book1);
    34     bookShelf.add(book2);
    35     bookShelf.add(book3);
    36     bookShelf.remove(book3);
    37     /*
    38     for(var i=0; i<bookShelf.models.length; i++) {
    39         alert(bookShelf.models[i].get('title'));
    40     }
    41     */
    42     //基于underscore这个js库,还可以使用each的方法获取collection中的数据
    43     bookShelf.each(function(book){
    44         alert(book.get('title'));
    45     });
    46 
    47     //2、使用fetch从服务器端获取数据,使用reset渲染
    48     bookShelf.bind('reset', showAllBooks);
    49     bookShelf.fetch({url:'/getbooks/',success:function(collection,response){
    50         collection.each(function(book){
    51             alert(book.get('title'));
    52         });
    53     },error:function(){
    54         alert('error');
    55     }});
    56     showAllBooks = function(){
    57         bookShelf.each(function(book){
    58 //将book数据渲染到页面。
    59         });
    60     }
    61     //上述代码仅仅均为可正常执行的代码,不过关于服务器端的实例在后面会有。
    62 })(jQuery);
    63 </script>
    64 </html>
    完整参考代码

    Router(之前好像没看到)

    之前我们学习的时候好像错过了Router了,路由的出现是想控制URL呢,Backbone.Router会把#标签当做url路径。

     1 <html>
     2 <head>
     3     <title>the5fire-backbone-router</title>
     4 </head>
     5 <body>
     6     <a href="#/posts/120">Post 120</a>
     7 <a href="#/download/user/images/hey.gif">download gif</a>
     8 <a href="#/dashboard/graph">Load Route/Action View</a>
     9 </body>
    10 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
    11     <script src="http://ajax.cdnjs.com/ajax/libs/underscore.js/1.1.4/underscore-min.js"></script>
    12     <script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>
    13     <script>
    14     (function ($) {
    15         //Backbone中的router,见名知意,router有路由的意思,显然这里是要控制url的。
    16         //Backbone.Router会把你连接中的#标签当做是url路径
    17         /**
    18         //1、来看一个简单的例子
    19         var AppRouter = Backbone.Router.extend({
    20             routes: {
    21                 "*actions" : "defaultRoute"
    22             },
    23             defaultRoute : function(actions){
    24                 alert(actions);
    25             }
    26         });
    27 
    28         var app_router = new AppRouter;
    29 
    30         Backbone.history.start();
    31 
    32 
    33         //2、既然是对url进行匹配那么它应该不仅仅只是简单的静态匹配,应该具有传递参数的功能,所以下面再来一个动态的router的例子.
    34         var AppRouter = Backbone.Router.extend({
    35             routes: {
    36                 "/posts/:id" : "getPost",
    37                 "*actions" : "defaultRoute"
    38             },
    39             getPost: function(id) {
    40                 alert(id);
    41             },
    42             defaultRoute : function(actions){
    43                 alert(actions);
    44             }
    45         });
    46 
    47         var app_router = new AppRouter;
    48 
    49         Backbone.history.start();
    50         **/
    51         //从上面已经可以看到匹配#标签之后内容的方法,有两种:一种是用“:”来把#后面的对应的位置作为参数;还有一种是“*”,它可以匹配所有的url,下面再来演练一下。
    52         var AppRouter = Backbone.Router.extend({
    53             routes: {
    54                 "/posts/:id" : "getPost",
    55                 "/download/*path": "downloadFile",  //对应的链接为<a href="#/download/user/images/hey.gif">download gif</a>
    56                         "/:route/:action": "loadView",      //对应的链接为<a href="#/dashboard/graph">Load Route/Action View</a>
    57                 "*actions" : "defaultRoute"
    58             },
    59             getPost: function(id) {
    60                 alert(id);
    61             },
    62             defaultRoute : function(actions){
    63                 alert(actions);
    64             },
    65             downloadFile: function( path ){
    66                 alert(path); // user/images/hey.gif
    67             },
    68             loadView: function( route, action ){
    69                 alert(route + "_" + action); // dashboard_graph
    70             }
    71         });
    72 
    73         var app_router = new AppRouter;
    74 
    75         Backbone.history.start();
    76 
    77     })(jQuery);
    78     </script>
    79 
    80 </html>
    路由的例子

    我们暂时不管这个,否则任务完成不了了。

    View

    这个看完,我们就要继续今天的学习了,这里用了太多时间啦。

    backbone的view是用来显示model数据到页面的,同时监听dom事件并相应变化。

    来看看我们的页面主体:

     1 <html xmlns="http://www.w3.org/1999/xhtml">
     2 <head>
     3     <title></title>
     4 </head>
     5 <body>
     6     <div id="search_container">
     7     </div>
     8     <script type="text/template" id="search_template">
     9         <label><%= search_label %></label>
    10         <input type="text" id="search_input" />
    11         <input type="button" id="search_button" value="Search" />
    12     </script>
    13 </body>
    14 <script src="js/jquery.js" type="text/javascript"></script>
    15 <script src="js/underscore.js" type="text/javascript"></script>
    16 <script src="js/backbone.js" type="text/javascript"></script>
    17 <script type="text/javascript">
    18     (function ($) {
    19         //此处添加下面的试验代码
    20     })(jQuery);
    21 </script>
    22 </html>

    el属性

    该属性引用dom中的一些元素,每个view都会有这个属性,没有声明就默认创建空div

    (function ($) {
        SearchView = Backbone.View.extend({
            initialize: function () {
                //this.render();
            },
            render: function () {
                //使用underscore这个库,来编译模板
                var template = _.template($("#search_template").html(), {});
                //加载模板到对应的el属性中
                //this.el.html(template);   //感谢 子不语同学指正。
                $(this.el).html(template);
            }
        });
        var searchView = new SearchView({ el: $("#search_container") });
        searchView.render();  //这个reander的方法可以放到view的构造函数中
    })(jQuery);

    [这里有一个错误,因为这个例子里没有传入search_label这个变量,所以你运行的时候要把html的模板中的那个变量改掉才行。]

    事件绑定

    (function ($) {
        SearchView = Backbone.View.extend({
            initialize: function () {
                this.render();
            },
            render: function () {
                //使用underscore这个库,来编译模板
                var template = _.template($("#search_template").html(), {});
                //加载模板到对应的el属性中
                //this.el.html(template);
                $(this.el).html(template);
            },
            events: {  //就是在这里绑定的
                'click input[type=button]': 'doSearch'  //定义类型为button的input标签的点击事件,触发函数doSearch
            },
    
            doSearch: function (event) {
                alert("search for " + $("#search_input").val());
            }
        });
        var searchView = new SearchView({ el: $("#search_container") });
    })(jQuery);

    模板

    此处的模板,就是以数据替换其中的特殊标签<%= search_label %>

     1 <html xmlns="http://www.w3.org/1999/xhtml">
     2 <head>
     3     <title></title>
     4 </head>
     5 <body>
     6     <div id="search_container">
     7     </div>
     8     <script type="text/template" id="search_template">
     9         <label><%= search_label %></label>
    10         <input type="text" id="search_input" />
    11         <input type="button" id="search_button" value="Search" />
    12     </script>
    13 </body>
    14 <script src="js/jquery.js" type="text/javascript"></script>
    15 <script src="js/underscore.js" type="text/javascript"></script>
    16 <script src="js/backbone.js" type="text/javascript"></script>
    17 <script type="text/javascript">
    18     (function ($) {
    19         SearchView = Backbone.View.extend({
    20             initialize: function () {
    21                 this.render('the5fire');
    22             },
    23             render: function (search_label) {
    24                 //使用underscore这个库,来编译模板
    25                 var template = _.template($("#search_template").html(), { search_label: search_label });
    26                 //加载模板到对应的el属性中
    27                 $(this.el).html(template);
    28             },
    29             events: {  //就是在这里绑定的
    30                 'click input[type=button]': 'doChange'
    31             },
    32             doChange: function (event) {
    33                 //通过model发送数据到服务器
    34                 this.render('the5fire' + $("#search_input").val());
    35             }
    36         });
    37         var searchView = new SearchView({ el: $("#search_container") });
    38     })(jQuery);
    39 </script>
    40 </html>

    阶段总结

    好了,知识回顾暂时到这里,我们要来我们的东西了,不然搞不完了。

    HTML结构

    有点一头雾水的感觉,于是先上一张图吧:

     1 <html xmlns="http://www.w3.org/1999/xhtml">
     2 <head>
     3     <title></title>
     4 </head>
     5 <body>
     6     <div id="contactapp">
     7         <header>
     8             <h1>
     9                 通讯录</h1>
    10         </header>
    11         <section id="main">
    12             <ul id="contact-list">
    13             </ul>
    14         </section>
    15         <div class="create">
    16             <label>
    17                 姓名:<input type="text" id="name" /></label>
    18             <label>
    19                 电话:<input type="text" id="phone" /></label>
    20             <input type="button" value="保存" id="add" />
    21         </div>
    22     </div>
    23 </body>
    24 </html>

    下面的输入框用以新建通讯项目,contact-list用以显示通讯录列表。整个页面非常简单,我们先就完成这个功能即可。

    模型与集合

    完了我们应该创建Contact模型了,我们先来随便写写代码看看有神马情况发生:

    var Contact = Backbone.Model.extend({
        validate: function (attr) {
            if (!attr.name || attr.name.length > 5) {
                return '姓名格式错误';
            }
        }
    });
    var contact = new Contact();
    var s = '';

    这里根据backbone的Model的extend方法建立了Contact模型。

    其中可能会有验证机制,我这里随便写了一个,电话其实也需要验证的。

    而模型会有的方法,我们暂时不管他了,先来个集合吧:

    <script src="js/underscore.js" type="text/javascript"></script>
    <script src="js/backbone.js" type="text/javascript"></script>
    <script src="js/backbone.localStorage.js" type="text/javascript"></script>
    <script type="text/javascript">
    var Contact = Backbone.Model.extend({
        validate: function (attr) {
            if (!attr.name || attr.name.length > 5) {
                return '姓名格式错误';
            }
        }
    });
    
    var ContackList = Backbone.Collection.extend({
        model: ContackList,
        localStorage: new Store('contacts')//所有信息保存至contacts空间下,注意此次用到了本地存储的东西
    });
    var s = '';
    </script>

    这里使用了本地存储,所以我们必须设置localStorage属性。

    视图

    现在我们来设置视图后:

     1 <html xmlns="http://www.w3.org/1999/xhtml">
     2 <head>
     3     <title></title>
     4 </head>
     5 <body>
     6     <div id="contactapp">
     7         <header>
     8             <h1>
     9                 通讯录</h1>
    10         </header>
    11         <section id="main">
    12             <ul id="contact-list">
    13             </ul>
    14         </section>
    15         <div class="create">
    16             <label>
    17                 姓名:<input type="text" id="name" /></label>
    18             <label>
    19                 电话:<input type="text" id="phone" /></label>
    20             <input type="button" value="保存" id="add" />
    21         </div>
    22     </div>
    23 </body>
    24 <script src="js/jquery.js" type="text/javascript"></script>
    25 <script src="js/underscore.js" type="text/javascript"></script>
    26 <script src="js/backbone.js" type="text/javascript"></script>
    27 <script src="js/backbone.localStorage.js" type="text/javascript"></script>
    28 <script type="text/javascript">
    29     (function ($) {
    30         var Contact = Backbone.Model.extend({
    31             validate: function (attr) {
    32                 if (!attr.name || attr.name.length > 5) {
    33                     return '姓名格式错误';
    34                 }
    35             }
    36         });
    37 
    38         var ContackList = Backbone.Collection.extend({
    39             model: ContackList,
    40             localStorage: new Store('contacts'), //所有信息保存至contacts空间下,注意此次用到了本地存储的东西
    41             initialize: function (models, options) {
    42                 this.bind('add', options.view.add);
    43             }
    44         });
    45         var AppView = Backbone.View.extend({
    46             el: $('body'),
    47             tmplate: _.template('<li><%= name %>:<%= phone %></li>'),
    48 
    49             initialize: function () {
    50                 _.bindAll(this, 'save', 'add');
    51                 this.contacts = new ContackList(null, { view: this });
    52                 this.list = $('#contact-list');
    53                 this.name = $('#name');
    54                 this.phone = $('#phone');
    55             },
    56             events: {
    57                 'click #add': 'save'
    58             },
    59             save: function () {
    60                 var model = new Contact({ name: this.name.val(), phone: this.phone.val() });
    61                 this.contacts.add(model);
    62             },
    63             add: function (model) {
    64                 var obj = model.toJSON();
    65                 $(this.list).append(this.tmplate(obj));
    66             }
    67         });
    68         var app = new AppView();
    69 
    70     })(jQuery);
    71 </script>
    72 </html>

    我们的简单的界面终于出来了。。。。于是我们来优化加功能吧:

      1 <!DOCTYPE html>
      2 <html xmlns="http://www.w3.org/1999/xhtml">
      3 <head>
      4     <title></title>
      5 </head>
      6 <body>
      7     <div id="contactapp">
      8         <header>
      9             <h1>
     10                 通讯录</h1>
     11         </header>
     12         <section id="main">
     13             <ul id="contact-list">
     14             </ul>
     15         </section>
     16         <div class="create">
     17             <label>
     18                 姓名:<input type="text" id="name" /></label>
     19             <label>
     20                 电话:<input type="text" id="phone" /></label>
     21             <input type="button" value="保存" id="add" />
     22         </div>
     23     </div>
     24 </body>
     25 <script src="js/jquery.js" type="text/javascript"></script>
     26 <script src="js/underscore.js" type="text/javascript"></script>
     27 <script src="js/backbone.js" type="text/javascript"></script>
     28 <script src="js/backbone.localStorage.js" type="text/javascript"></script>
     29 <script type="text/javascript">
     30     (function ($) {
     31         var Contact = Backbone.Model.extend({
     32             initialize: function () {
     33                 this.bind("error", function (model, error) {
     34                     alert(error);
     35                 });
     36             },
     37             validate: function (attr) {
     38                 if (attr.name.length == '') {
     39                     return '姓名格式错误';
     40                 }
     41             }
     42         });
     43         var ContactList = Backbone.Collection.extend({
     44             model: Contact,
     45             localStorage: new Store('contacts') //所有信息保存至contacts空间下,注意此次用到了本地存储的东西
     46 
     47         });
     48         var list = new ContactList();
     49         var ContactView = Backbone.View.extend({
     50             tagName: 'li',
     51             template: _.template('<div><%= name %>:<%= phone %></div>'),
     52             events: {
     53                 'click li': 'test'
     54             },
     55             initialize: function () {
     56                 _.bindAll(this, 'render', 'remove');
     57                 this.model.bind('change', this.render);
     58                 this.model.bind('destroy', this.remove);
     59             },
     60             render: function () {
     61                 var html = this.template(this.model.toJSON());
     62                 //this.el是生成的空div
     63                 $(this.el).html(html);
     64                 //返回了当前视图
     65                 return this;
     66             },
     67             remove: function () {
     68                 $(this.el).remove();
     69             },
     70             test: function () {
     71                 alert(this);
     72                 var s = '';
     73             }
     74         });
     75         var AppView = Backbone.View.extend({
     76             el: $('body'),
     77             events: {
     78                 'click #add': 'save'
     79             },
     80             initialize: function () {
     81                 this.name = this.$('#name');
     82                 this.phone = this.$('#phone');
     83                 this.list = this.$('#contact-list');
     84 
     85                 _.bindAll(this, 'render', 'add', 'loadList', 'save');
     86                 //为集合绑定事件
     87                 list.bind('add', this.add);
     88                 //添加修改时触发
     89                 list.bind('refresh', this.loadList);
     90                 list.fetch();
     91             },
     92             //添加项目
     93             add: function (model) {
     94                 var view = new ContactView({ model: model });
     95                 this.list.append(view.render().el);
     96 //                view.model.save({ name: model.name, phone: model.phone });
     97                 var s = '';
     98             },
     99             loadList: function () {
    100                 list.each(this.add);
    101             },
    102             save: function () {
    103                 var name = this.name.val();
    104                 var phone = this.phone.val();
    105                 list.create({ name: name, phone: phone });
    106                 this.name.val('');
    107                 this.phone.val('');
    108             }
    109         });
    110         var app = new AppView();
    111 
    112     })(jQuery);
    113 </script>
    114 </html>

    这个代码与上述代码有些不同,我们来理一理:

    ① 模型与集合变化不大

    ② 具有2个视图:

    通讯录视图,我们后面通讯录会有编辑、删除或者其他功能,就在此上写

    全局视图,AppView用于全局,可能还会显示整体状态。

    ③流程

    因为我们只有一个通讯录列表,所以将之全局化出来了:

    var list = new ContactList();

    ContactView主要关注自身,与整体可以隔离开。

    tagName指定了形成的dom的外层结构,不指定就是div

    template会解析模板,我直接写到这里了,后面我们做点修改给个删除功能

    template: _.template('<div><%= name %>:<%= phone %><a href="javascript:;">[删除]</a></div>'),

    events就是绑定的事件

    PS:具体代码各位自己看吧......

    这里将删除事件加上就算阶段完成了:

      1 <!DOCTYPE html>
      2 <html xmlns="http://www.w3.org/1999/xhtml">
      3 <head>
      4     <title></title>
      5 </head>
      6 <body>
      7     <div id="contactapp">
      8         <header>
      9             <h1>
     10                 通讯录</h1>
     11         </header>
     12         <section id="main">
     13             <ul id="contact-list">
     14             </ul>
     15         </section>
     16         <div class="create">
     17             <label>
     18                 姓名:<input type="text" id="name" /></label>
     19             <label>
     20                 电话:<input type="text" id="phone" /></label>
     21             <input type="button" value="保存" id="add" />
     22         </div>
     23     </div>
     24 </body>
     25 <script src="js/jquery.js" type="text/javascript"></script>
     26 <script src="js/underscore.js" type="text/javascript"></script>
     27 <script src="js/backbone.js" type="text/javascript"></script>
     28 <script src="js/backbone.localStorage.js" type="text/javascript"></script>
     29 <script type="text/javascript">
     30     (function ($) {
     31         var Contact = Backbone.Model.extend({
     32             initialize: function () {
     33                 this.bind("error", function (model, error) {
     34                     alert(error);
     35                 });
     36             },
     37             validate: function (attr) {
     38                 if (attr.name.length == '') {
     39                     return '姓名格式错误';
     40                 }
     41             }
     42         });
     43         var ContactList = Backbone.Collection.extend({
     44             model: Contact,
     45             localStorage: new Store('contacts') //所有信息保存至contacts空间下,注意此次用到了本地存储的东西
     46 
     47         });
     48         var list = new ContactList();
     49         var ContactView = Backbone.View.extend({
     50             tagName: 'li',
     51             template: _.template('<div><%= name %>:<%= phone %><a href="javascript:;" class="delete">[删除]</a></div>'),
     52             events: {
     53                 'click .delete': 'destroy'
     54             },
     55             initialize: function () {
     56                 _.bindAll(this, 'render', 'remove');
     57                 this.model.bind('change', this.render);
     58                 this.model.bind('destroy', this.remove);
     59             },
     60             render: function () {
     61                 var html = this.template(this.model.toJSON());
     62                 //this.el是生成的空div
     63                 $(this.el).html(html);
     64                 //返回了当前视图
     65                 return this;
     66             },
     67             destroy: function () {
     68                 this.model.destroy();
     69             },
     70             remove: function () {
     71                 $(this.el).remove();
     72 
     73             }
     74         });
     75         var AppView = Backbone.View.extend({
     76             el: $('body'),
     77             events: {
     78                 'click #add': 'save'
     79             },
     80             initialize: function () {
     81                 this.name = this.$('#name');
     82                 this.phone = this.$('#phone');
     83                 this.list = this.$('#contact-list');
     84 
     85                 _.bindAll(this, 'render', 'add', 'loadList', 'save');
     86                 //为集合绑定事件
     87                 list.bind('add', this.add);
     88                 //添加修改时触发
     89                 list.bind('refresh', this.loadList);
     90                 list.fetch();
     91             },
     92             //添加项目
     93             add: function (model) {
     94                 var view = new ContactView({ model: model });
     95                 this.list.append(view.render().el);
     96                 //                view.model.save({ name: model.name, phone: model.phone });
     97                 var s = '';
     98             },
     99             loadList: function () {
    100                 list.each(this.add);
    101             },
    102             save: function () {
    103                 var name = this.name.val();
    104                 var phone = this.phone.val();
    105                 list.create({ name: name, phone: phone });
    106                 this.name.val('');
    107                 this.phone.val('');
    108             }
    109         });
    110         var app = new AppView();
    111 
    112     })(jQuery);
    113 </script>
    114 </html>
    带删除功能的通讯录

    阶段总结

    我们又简单的回顾了下backbone,这次学习后我和我的小伙伴表示都懂了。。。。

    整合requireJS

    先上个图:

    尼玛,一下多出了好多文件:

    模型

    define(function () {
        var Contact = Backbone.Model.extend({
            initialize: function () {
                this.bind("error", function (model, error) {
                    alert(error);
                });
            },
            validate: function (attr) {
                if (attr.name.length == '') {
                    return '姓名格式错误';
                }
            }
        });
        return Contact;
    });

    集合

    define(['model/contact'], function (Contact) {
        var ContactList = Backbone.Collection.extend({
            model: Contact,
            localStorage: new Store('contacts') //所有信息保存至contacts空间下,注意此次用到了本地存储的东西
    
        });
        return ContactList;
    });

    contact视图

    define(function () {
        var ContactView = Backbone.View.extend({
            tagName: 'li',
            template: _.template('<div><%= name %>:<%= phone %><a href="javascript:;" class="delete">[删除]</a></div>'),
            events: {
                'click .delete': 'destroy'
            },
            initialize: function () {
                _.bindAll(this, 'render', 'remove');
                this.model.bind('change', this.render);
                this.model.bind('destroy', this.remove);
            },
            render: function () {
                var html = this.template(this.model.toJSON());
                //this.el是生成的空div
                $(this.el).html(html);
                //返回了当前视图
                return this;
            },
            destroy: function () {
                this.model.destroy();
            },
            remove: function () {
                $(this.el).remove();
    
            }
        });
        return ContactView;
    });

    全局视图

    define(['collection/contact', 'view/contact'], function (contact, ContactView) {
        window.list = new contact();
        var AppView = Backbone.View.extend({
            el: $('body'),
            events: {
                'click #add': 'save'
            },
            initialize: function () {
                this.name = this.$('#name');
                this.phone = this.$('#phone');
                this.list = this.$('#contact-list');
    
                _.bindAll(this, 'render', 'add', 'loadList', 'save');
                //为集合绑定事件
                list.bind('add', this.add);
                //添加修改时触发
                list.bind('refresh', this.loadList);
                list.fetch();
            },
            //添加项目
            add: function (model) {
                var view = new ContactView({ model: model });
                this.list.append(view.render().el);
                //                view.model.save({ name: model.name, phone: model.phone });
                var s = '';
            },
            loadList: function () {
                list.each(this.add);
            },
            save: function () {
                var name = this.name.val();
                var phone = this.phone.val();
                list.create({ name: name, phone: phone });
                this.name.val('');
                this.phone.val('');
            }
        });
        return AppView;
    });

    main函数

    require.config({
        paths: {
            jquery: 'js/jquery',
            underscore: 'js/underscore',
            backbone: 'js/backbone',
            bl: 'js/backbone.localStorage'
    
        }
    });
    
    require(['jquery', 'underscore', 'backbone', 'bl', 'model/contact', 'collection/contact', 'view/contact', 'view/app'], 
    function ($, _, b, bl, model, collection, view, app) {
        var app = new app();
    });

    HTML页面

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
    </head>
    <body>
        <div id="contactapp">
            <header>
                <h1>
                    通讯录</h1>
            </header>
            <section id="main">
                <ul id="contact-list">
                </ul>
            </section>
            <div class="create">
                <label>
                    姓名:<input type="text" id="name" /></label>
                <label>
                    电话:<input type="text" id="phone" /></label>
                <input type="button" value="保存" id="add" />
            </div>
        </div>
    </body>
    <script src="js/require.js" data-main="main" type="text/javascript"></script>
    </html>

    于是,我们功能完成了:

    结语

    我和我的小伙伴说,尼玛终于搞完了。。。。。。

  • 相关阅读:
    [C++] socket
    [C++] socket
    2014-3-16 星期天 晴[改变生活规律,稳中求进]
    [C++] socket
    [C++] socket
    [ACM_水题] Yet Another Story of Rock-paper-scissors [超水 剪刀石头布]
    easyui datagrid如何获取到每行的文本框
    JS传递数组到后台
    如何将js的object对象传到后台--->JavaScript之对象序列化
    EasyUI常用控件禁用方法
  • 原文地址:https://www.cnblogs.com/yexiaochai/p/3221081.html
Copyright © 2020-2023  润新知