前言: 我们继续使用上一次写的图书案例,在基础上面进行改进!

事件绑定

在我们浏览网页的时候,获取数据并不是一下只就全部获取到的,为了创建一个更好的用户体验,就来模拟一个加载(Spinner)的图片来告诉用户正在获取数据中!

当用户在浏览详细视图(books/:BookName),只需要调用加载数据的方法。然后,因为设置了正确的监听器,当接受到新的数据的时候,视图就会自动更新。数据更新的时候,Backbone支持多事件和自定义事件。

改变路由程序里面的代码:

// 渲染Books页面
loadBook: function (bookName){
    this.bookView.loadBook(bookName);
}

除了bookView类,其他都不会改变。添加构造函数或者initialize方法,initialize方法是Backbone里面的一个特殊的字符属性。每个实例初始化的时候都会调用这个属性对应的方法。

然后使用两个事件——changespinner的自定义事件。我们将使用on()(别名bind)函数。

initialize: function (){
    this.model = new (Backbone.Model.extend({}));
    this.model.bind('change', this.render, this);
    this.bind('spinner', this.showSpinner, this);
}

上面的代码做了两件简单的事情:

  1. 当模型改变时候调用render()函数
  2. 当事件spinner触发时调用showSpinner()函数

然后spinner怎么办呢?,那就用一个简单的gif图片把!在bookView里创建一个新的属性:

templateSpinner: '<img src="img/loding.gif">'

spinner图片(上网找一大堆):
此处输入图片的描述

接着回到一开始那个loadBook函数里面,继续写代码:

loadBook: function (bookName){
    this.trigger('spinner');
    // 出现加载图片
    var me = this;
    // 需要在闭包访问this
    setTimeout(function (){
        // 模拟从服务器获取数据要的时间
        me.model.set(me.collection.where({
            name: bookName
        })[0].attributes);
    }, 1000);
}

里面触发了spinner事件,还有为了解决作用域的问题,需要在闭包里面访问this

setTimerout是为了模拟从服务器获取响应的时间。在它内部里面,使用model.set()model.attributes(返回模型属性)把选中的模型赋值给当前视图的模型。

最后把render函数里面多余的代码去掉,实现showSpinner函数:

render: function (bookName){
    var bookHtml = this.template(this.model);
    $('body').html(bookHtml);
},
showSpinner: function (){
    $('body').html(this.templateSpinner);
}

让后打开浏览器访问index.html#books/book1,如果可以看到加载的图片的话,就证明成功啦!

最后附上完整的代码

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>backbone日常练习</title>
</head>

<body>
<p><a href="#books/book1">bg</a></p>

<script src="js/jquery.min.js"></script>
<script src="js/Underscore.min.js"></script>
<script src="js/backbone-min.js"></script>

<script>
    var app;
    // 图书数据库
    var booksData = [
        {
            name: 'book1',
            url: 'img/1.jpg'
        },
        {
            name: 'book2',
            url: 'img/2.jpg'
        }
    ];
    var router = Backbone.Router.extend({
        routes: {
            '': 'home',
            'books/:bookName': 'loadBook'
        },
        initialize: function (){
            // 一些在对象初始化的时候执行的代码
            var books = new Books();
            books.reset(booksData);
            this.homeView = new homeView({collection: books});
            this.bookView = new bookView({collection: books});
        },
        home: function (){
            this.homeView.render();
        },
        // 渲染Books页面
        loadBook: function (bookName){
            this.bookView.loadBook(bookName);
        }
    });

    var homeView = Backbone.View.extend({
        el: 'body',
        template: _.template('books data: <%= data %>'),
        render: function (){
            this.$el.append(this.template({
                data: JSON.stringify(this.collection.models)
            }));
        }
        // TODO 子视图
    });

    var Books = Backbone.Collection.extend({});

    // books 视图
    var bookView = Backbone.View.extend({
        initialize: function (){
            this.model = new (Backbone.Model.extend({}));
            this.model.bind('change', this.render, this);
            this.bind('spinner', this.showSpinner, this);
        },
        template: _.template(
            '<h2><%= attributes.name %></h2><img src="<%= attributes.url %>">'
        ),
        templateSpinner: '<img src="img/loding.gif">',
        loadBook: function (bookName){
            this.trigger('spinner');
            // 出现加载图片
            var me = this;
            // 需要在闭包访问this
            setTimeout(function (){
                // 模拟从服务器获取数据要的时间
                me.model.set(me.collection.where({
                    name: bookName
                })[0].attributes);
            }, 1000);
        },
        // TODO 用加载图书过程和事件绑定来重写
        render: function (bookName){
            var bookHtml = this.template(this.model);
            $('body').html(bookHtml);
        },
        showSpinner: function (){
            $('body').html(this.templateSpinner);
        }
    });

    $(function (){
        app = new router;
        Backbone.history.start();
    });

</script>
</body>
</html>

_我已经从中二毕业了
7.9k 声望235 粉丝

不搞前端会死星人。