RequireJS与Backbone简单整合

前言

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

好吧,我们开始今天的学习吧,我们今天先用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数据渲染到页面。
    });
}
复制代码
  完整参考代码

Router(之前好像没看到)

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

  路由的例子

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

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:具体代码各位自己看吧......

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

  带删除功能的通讯录

阶段总结

我们又简单的回顾了下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>
复制代码

于是,我们功能完成了:

结语

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

原文链接:http://www.cnblogs.com/yexiaochai/p/3221081.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值