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();

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

时间: 2024-10-26 16:47:39

backbone.js初体验--构建简单分页应用时踩到的坑的相关文章

vue.js 初体验

Vue.js是什么? 一个构建数据驱动的web界面的库.他不是一个全能框架,技术上重点集中在MVVM中的ViewModel层. Vue.js特点? 轻巧.高性能.可组件化 官网地址:http://cn.vuejs.org/ Vue.js初体验 引入Vue.js独立版本, 至官网下载独立版本.根据提示,开发时选择开发版本. 直接引入Vue.js到静态页面中,从数据绑定开始编写DOM部分和js部分 <div id="app"> {{message}} </div>

Knockout.js初体验

前不久在网上看到一个轻量级MVVM js类库叫Knockout.js,觉得很好奇,搜了一下Knockout.js相关资料,也初体验了一下,顿时感觉这个框架的设计很有意思.接下来就搞清楚什么是Knockout.js Knockout.js有4个重要的概念:(一定要牢记) 1.声明绑定:使用简明易读的语法很容易地将模型(model)数据关联到DOM元素上. 2.UI界面自动刷新:当您的模型状态(model state)改变时,您的UI界面将自动更新. 3.依赖跟踪:为转变和联合数据,在你的模型数据之

node.js 初体验

到新公司的这段时间学到了很多新东西,有好多东西需要去总结去探索,不过事情得一件一件来,今天咱们先从Node开始.注:以后出现的Node即node.js. 先搞点前戏热热场 - 为什么写这篇文章: 1.前段时间单位有新项目启动,服务端要做的工作不多也不算麻烦,就是处理一些中间层的服务,而且我们团队里面个个都会JavaScript,领导就决定试试服务器端的JavaScript,结果本人有幸被派去研究了几天Node,怀着鸡冻的心情开始了node.js的篇章,这篇文章也就是为这几天研究的总结. 2.一个

Node.js初体验

1.Node.js是什么 [1]Node是一个服务器端 JavaScript 解释器,可是真的以为JavaScript不错的同学学习Node就能轻松拿下,那么你就错了,总结:水深不深我还不知道,不过确实不浅. [2]Node的目标是帮助程序员构建高度可伸缩的应用程序,编写能够处理数万条同时连接到一个物理机的连接代码.处理高并发和异步I/O是Node受到开发人员的关注的原因之一. [3]Node本身运行Google V8 JavaScript引擎,所以速度和性能非常好,看chrome就知道,而且N

MVC + Vue.js 初体验(实现表单操作)

Vuejs http://cn.vuejs.org/ Vue.js(读音 /vju?/, 类似于 view) 是一套构建用户界面的 渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计.Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合.另一方面,Vue 完全有能力驱动采用单文件组件和Vue生态系统支持的库开发的复杂单页应用. Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件. DEMO效果 前端源码 @{ Lay

vue.js 初体验— Chrome 插件开发实录

欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:陈纬杰 背景 对于经常和动画开发打交道的开发者对于Animate.css这个动画库不会陌生,它把一些常见的动画效果都封装起来了,非常实用.但是有时候在开发中,仅仅只是需要某一两个动画效果,把整个CSS文件都引入,这样不是太好. 需求就出现了,能不能有一个工具可以直接预览Animate.css对应的动画效果,并且生成对应的动画代码呢? 作为一个UI开发,平时跟Chrome浏览器打交道最多,于是就整了一个

impress.js初体验

概述 如果你已经厌烦了使用PowerPoint制作PPT,那么impress.js是一个非常好的选择,用它做的PPT更加直观,效果也非常的不错.装X是需要一定代价的,不过如果你是个前端爱好者那么一切就没问题了.当然如果你能勉强明白HTML和CSS也没问题,看看这篇文章 + 一点点实践(把官网上的例子拿来改改)即可... impress.js 是国外一位开发者受 Prezi 启发,采用 CSS3 与 JavaScript 语言完成的一个可供开发者使用的表现层框架(演示工具).现在普通开发者可以利用

backbone.js之Model篇 简单总结和深入(2)

一.模型属性的一些操作方法 1.mmodel.get()  获取属性的值 2.mmodel.set('age',5) 更新单个属性的值  mmodel.set({name:'aaa',age:6})  更新多个属性的值  在设置属性值时,如果该属性不存在,会自动创建该属性:同时会以true的形式返回一个模型的引用. 3.mmodel.unset('age')  从模型中删除一个属性 4.mmodel.clear()  从模型中删除所有的属性 5.mmodel.has('age') 检查是否存在某

impress.js初体验——前端装X利器

impress.js 是国外一位开发者受 Prezi 启发,采用 CSS3 与 JavaScript 语言完成的一个可供开发者使用的表现层框架(演示工具).其功能包括画布的无限旋转与缩放,任意角度放置任意大小的文字,CSS3 3D 效果支持等.同时,也支持传统 PowerPoint 形式的幻灯演示.目前 impress.js 是基于 webkit 浏览器(Chrome.Safari)开发,而在其它基于非 webkit 引擎,但支持 CSS3 3D 的浏览器也能正常运行.       impree