zoukankan      html  css  js  c++  java
  • backbone.js初体验--构建简单分页应用时踩到的坑

    最近突然想接触下之前没有接触过的领域,单页应用,正巧之前也是刚刚学习了requirejs的用法,所以趁热打铁选择了很多网站采用的requirejs+underscorejs+backbonejs+jquery(zepto)的方式来进行demo的编写。

    这篇文章主要不是介绍怎么去构建一个分页效果的,也不会去讲述backbone的基础知识,而是分享在我构建分页效果时候踩到的一些坑。

    1. collection不是必须的

    首先,我在开始写的时候就陷入了一个问题,事实证明我真的是多虑了,就是不该用collection的时候,就别去用它了,这个是我在分析堆糖网站源码的时候发现的,整个堆糖就没用到一个collection。

    下面来说说为什么:

    collection是model的有序集合,model是什么,model就是模型,其实我们做分页的时候,就是不断的问后台要数据,不论是更改页码还是进行排序,其实都是后台再进行操作的,我们做的只是更改路由,去问后台要相应的数据,再填充进html中,所以如果不是对model本身进行增删改查的话,collection就会显得有些冗余了。

    2. 慎用collection中的all事件

    这个问题其实是跟上面那个问题绑定在一起的,是我强行想要使用collection时遇到的一个问题(洁癖,凑齐MVC三个字母嘛),当时是看到其他的文章,别人的demo中用的就是all事件,于是自己也没动脑筋,不管适合不适合,就先照搬了过来,其实还是有性能上的隐患的,collection是一个model的合集,当一个view不停的在监听collection变化的时候,作为all事件,有一些细小的变换都会导致该事件的触发。

    initialize: function() {
          var _this = this
          this.page_view = new pageView()
          this.list = new cnCollection()
          this.pages = 1 //默认第一页
          this.listenTo(this.list, 'all', this.render) //如果使用all,可能会多次触发render
        },
        render: function() {
          console.log(1)
          this.models = this.list.models
          this.pageModels = this.list.page
          var len = this.models.length,
            html = ''
          for (var i = 0; i < len; i++) {
            html += '<li>' + this.template(this.models[i].toJSON()) + '</li>'
          }
          $('#prdList').html(html)
          this.page_view.render(this.pageModels)
        }

    先介绍下前提,再看上面的代码,这里的models里面有24个节点,可以看成是有24个商品的数据,我们的目的是把24个节点的数据渲染到html中。

    这里的1被输出了20多次,就是说render被执行了至少24次,因为对于collection来说每一次的变换都会触发回调函数,那我们有24个节点添加入了collection,那自然就有24次的变换,这样代码运行的效率就是非常低的了,当然这里还会有其他的变换,所以数字是大于24的,如果把all改成add,就能准确的看到是24次了,那么我们怎么来解决这个问题呢,我使用的是sort事件,sort事件是当该collection已被重新排序时触发的,这样当分页重新获取数据填充collection时,其实backbone就认为collection是进行了重新排序,而且这个事件只会被触发一次,所以sort事件既能完成任务,又能避免性能的浪费,给他点个赞!

    3. view中的el属性

    其实我要吐槽的不是el属性,而是events属性,大家都知道bb中定义dom事件是在view中进行的。

    events: {
          'click .prev-page': 'goToPrev',
          'click .next-page': 'goToNext'
        }

    就像上面这样定义,但是如果.prev-page不是el属性的子节点的话,就歇菜了!

    js部分代码(接口改成假的了,感受下就行):

    var cnModel = B.Model.extend({});
      /* 列表Collection */
      var cnCollection = B.Collection.extend({
        model: cnModel,
        parse: function(res) {
          this.page = res.data.page
          return (res && res.data && res.data.list) || {}
        }
      });
    
      /* 列表View */
      var cnView = B.View.extend({
        el: $('.g-warp'),
        events: {
          'click .prev-page': 'goToPrev',
          'click .next-page': 'goToNext'
        },
        template: _.template($('#list-template').html()),
        initialize: function() {
          var _this = this
          this.page_view = new pageView()
          this.list = new cnCollection()
          this.pages = 1 //默认第一页
          this.listenTo(this.list, 'sort', this.render) //如果使用all,可能会多次触发render
        },
        render: function() {
          this.models = this.list.models
          this.pageModels = this.list.page
          var len = this.models.length,
            html = ''
          for (var i = 0; i < len; i++) {
            html += '<li>' + this.template(this.models[i].toJSON()) + '</li>'
          }
          $('#prdList').html(html)
          this.page_view.render(this.pageModels)
        },
        goToPrev: function() {
          this.changeRoutes(-1)
        },
        goToNext: function() {
          this.changeRoutes(1)
        },
        changeRoutes: function(args) {
          var pageCount = this.list.page.page_count
          this.pages = this.pages + args
          if (this.pages <= 0) {
            this.pages = 1
            alert("已经是第一页")
            return false
          } else if (this.pages > pageCount) {
            this.pages = pageCount
            alert("一共就" + pageCount + "页")
            return false
          }
          mr.navigate("/pages" + this.pages, {
            trigger: true
          });
        }
      });
      /* 页码View */
      var pageView = B.View.extend({
        template: _.template($('#page-template').html()),
        render: function(args) {
          $('#pageCount').html(this.template(args))
        }
      });
      var myRouter = B.Router.extend({
        initialize: function() {
          this.view = new cnView()
        },
        routes: {
          '': 'index',
          'pages:num': 'pages'
        },
        index: function() {
          this.view.list.url = 'http://xxx.com/a.php?mod=Search&act=page&option=&p=' + 1 + '&callback=?'
          this.view.list.fetch({
            success: function() {
              $(".loading-content").hide()
            }
          })
        },
        pages: function(num) {
          $(".loading-content").show()
          this.view.list.url = 'http:/xxx.com/a.php?mod=Search&act=page&option=&p=' + num + '&callback=?'
          this.view.pages = Number(num)
          this.view.list.fetch({
            success: function() {
              $(".loading-content").hide()
            }
          })
        }
      });
      var mr = new myRouter();
      B.history.start();

    路由倒是挺好用的,点个赞!今天就写到这里了,以后再有坑就另外开一篇文章了。

  • 相关阅读:
    DC中为什么要用Uniquify?
    hdu 1596 find the safest road
    hdu2112 HDU Today
    hdu 2066 一个人的旅行
    poj 3026 Borg Maze
    poj 1979 Red and Black
    poj 1321 棋盘问题
    hdu 1010 Tempter of the Bone
    hdu 4861 Couple doubi
    codeforces584B Kolya and Tanya
  • 原文地址:https://www.cnblogs.com/junhua/p/4453431.html
Copyright © 2011-2022 走看看