Tag Archives: backbone

Backbone笔记

  • listenTo的callback会接受到一个参数,就是other的当前对象。
object.listenTo(other, event, callback)
  • Model的状态属性都在model.attributes对象中,通过defaults可以来赋初值定义。之后通过get和set获得
var M = Backbone.Model.extend({</p> 
    defaults:function(){
    
    return {key: value };
    
    })
    
    new M.get('key');
    
    new M.set('key', 'hello world')

 

  • 数组的构造函数,默认接受参数(models, options),就是说,初值必须是models这个值。
  • model默认都会有id,如果你的后台不是id,可以通过指定model.idAttribute = ‘_id’来修改,于是Bakbone就会把id的值设为_id这个属性的值。
  • 数组的add方法会进行去重,粗略的说,包含有相同id的model对象都不会添加进去,实际代码用get方法判断,get如下:
return this._byId[obj.id || obj.cid || obj[this._idAttr] || obj];

也就是说,如果定义model的时候,把 id的初值设置为null,由于cid是自动产生的client id,不会重复,因此,Collection.add会把这个新的对象加入到数组中。这里,cid的产生方法是_.uniqueId(‘c’),就是说产生一个c打头的唯一id,目测不会与后台的id编号冲突。

小试backbone

收到@liuda101的强烈推荐,最终还是看了一下backbone。也由于之前shunote的代码基本上是靠jquery堆出来的,完全用knockout重写,不太现实。看完果然发现,backbone确实什么也没做,但是帮你梳理了代码的思路,让代码变的更加清晰了。

View

Backbone的View的意思是一段显示的内容,即html通过模板构造,然后对其绑定事件。这对于SPA来说,还是很重要的。之前确实觉得绑定事件这种代码没地方放,放到业务逻辑模块感觉不对,单独放又与业务逻辑分不开,因为事件是Js运转的起点。下面是从官方demo todo删减出来的一段代码。

  Var AppView = Backbone.View.extend({
      el: $('#todoapp'),
      events: {
        "click #clear-completed": "clearCompleted",
        "keypress #new-todo": "createOnEnter"
      },
      initialize: function(){
        this.listenTo(Todos, "add", this.addOne);
        this.listenTo(Todos, "all", this.render); //所有发生的事件都会触发
      },
      render: function(){
        // 重新渲染视图
        this.footer.html(this.statsTemplate({done: done, remaining: remaining}));
      },
      addOne: function(){
        var view = new TodoView({model: todo});
        this.$("#todo-list").append(view.render().el);
      },
    })

 

很清晰的一段代码。el代表这个View的最外围的元素,这里就是说页面上已经有这个元素了。如果没有需要稍稍换一种方式声明。events就是绑定元素内其他元素的事件。initialize是初始化,在View实例化的时候可以调用,在这里面Listen to 数据Model的变化,

注意,数据Model变化也是“事件”,所以是Listen to,但是不是界面事件,而是数据变化事件。View需要和数据变化保持一致,所以View要listen to models

那么,数据是怎么变化的呢?当然还是界面事件导致的(input)。因此,在View的events里定义的事件,就用来listen to 界面变化,这里的事件处理函数,会改变models。

View做了什么?

也就是说,View做了两件事,

  1. 当用操作界面时,改变model ——view是攻
  2. 当model改变时,更新界面。 ——view是受

是不是很晕?那就对了,因为MVC在这里其实不太好用。这里如果要梳理的更清楚,应该使用MVVM模型,参考Understanding MVVM – A Guide For JavaScript Developers

  • ViewModel: 界面数据模型(界面事件产生时,更新ViewModel,它对界面上展示的数据建模)
  • View 需要被model同步的界面(上面的受,knockout的data-bind),同时把界面事件events通知给ViewModel(攻ViewModel)
  • Model 真正的数据模型,ViewModel相当于封装了Model,把需要展示的部分暴露出来,Model藏在ViewModel的后面。

剩下的部分

继续Backbone,

Model和Collection了,模型和模型数组,没啥好说的,大家都差不多。

Router,这个是特色,帮你管理URL。具体的没看,不过写过SPA的应该都猜的出来,不同的url做不同的事嘛,构造和解析嘛。

Sync,帮助你将数据持久化,就是ORM的部分,搞定后台,REST接口。

Backbone带来的一系列小福利。

哦了。

knockoutjs初探——MVVM框架

Backbone, ember, knockout算是比较火的三个前端MV*框架,受到Knockout.js vs Backbone.js文章的蛊惑,我决定尝试一下knockout。文中称Backbone的优势在于,对Rest接口的后台进行了一个很好的model,也就是说是一个不错的ORM(这个比喻让写过后台的人秒懂啊有木有!),而对于DOM操作,这种属于controler范围的东西,Backbone没有一个集中编写的位置,也没有提供任何方便,你需要自己用jquery去操纵。因此,Backbone非常_“灵活”_。

继续Knockout。Knockout有个牛逼的在线教程,灰常有用。

Textarea和p

在前端实现MVC框架都有一个问题,View可能会接受大量用户输入,并进行改变。

Knockout对input类型和p类型都可以进行model的绑定,

<p data-bind="text: question"></p>
<select data-bind="options: [1,2,3,4,5], value: points"></select>

这里就是对p元素绑定text类型的变量question。question是在js中的ViewModel中定义的,具体绑定细节就请移步教程~ question是一个observable

question = ko.observable("Are you hungry?")

当需要改变question的值时,使用

question("Are you happy?") //change value
question()    //read value

让人想起来setters和getters啊。question的值一旦改变,所有data-bind相关的view都会改变。

text这个类型,很明显是一个文档值类型,我们可以相见,还会有html类型用来直接传入html。Knockout的模板当然不止提供这些,还提供例如:foreach(循环block内部的内容),visible(满足条件才可视),click等等。例如:

<h3 data-bind="visible: value() > 3 ">value居然大于3了</h3>

只有当value()的值大于3的时候才会显示h3的内容

<button href="#” data-bind="enable: value()>3, click: onclick"></button>

相当于绑定了一个回调函数。

显然,你也可以自定义,这个成为bindingHandlers。

bindingHandlers的init和update

bingingHandler的定义如下:

ko.bindingHandlers.yourhandler = {
    init: function(element, accessValue){},
    update: function(element, accessValue){}
}

update很好理解,当元素内容发生改变的时候,通过选中$(element),利用accessValue()里的值进行操作。这个accessValue就是html中跟在visible或者text或者yourhandler后面的值,需要通过accessValue()调用返回。

init是什么的?一般需要自定义handler是希望实现一些动画,但是,如果只有update,当页面第一次加载的时候,只能执行update中的例如,fadeOut()动画,于是,页面就相当于闪了一下,多不和谐。于是,你可以自定义init来改变handler第一次加载时的行为。

真贴心啊!

于是,你就可以这样写了。

<p data-bind="yourhandler: value"></p>

init在页面加载的时候只执行一次,这意味着!可以在里面再另外写一些辅助性的绑定哦~~~

//...    
$(element).hover(function(){}, function(){})
$("span", element).each(function(){ $(this).addClass('span'); })
//...