• Backbone模型


    Backbone模型

    现在进入最关键的组件 - 模型。模型用来存储应用的所有数据,以及直接和数据操作相关的逻辑。Backbone中的模型类是Backbone.Model,它包含了数据存储,数据验证,以及数据发生变动时触发相关动作。

    一般可以把模型与后端绑定(ORM),模型改变的同时向后端发起请求(Ajax)更新数据(数据库)。也有把模型和DOM元素绑定,模型改变时更新HTML界面。

    模型

    可以直接new一个Backbone.Model,它返回一个Model实例

    1
    2
    var model = new Backbone.Model()
    model.set({name: 'Backus', age: 35})

    也可扩展Backbone.Model,定义自己的模型类(构造器)

    1
    2
    3
    4
    5
    var Person = Backbone.Model.extend({
        initialize: function(name, age) {
            this.set({name: name, age: age})
        }
    })

    extend的第一个参数为一个对象,它将成为模型实例的属性。第二个参数将成为类属性(类静态属性、方法)。这在 Backbone的写类方式 有所提及。

    模型与属性 - set/get

    使用set和get方法来设置或获取模型的属性。属性在模型实例上有一个专门的属性来存储:this.attributes,set/get都围绕this.attributes操作。

    设置模型Person的属性

    1
    2
    var p1 = new Person()
    p1.set({name: 'Backus', age: 87})

    Firefox控制台使用get方法获取属性

    set方法除了可以接受对象形式参数,也可以接受前两个key,value方式。

    set方法内部对此做了兼容,第一个参数key如果是对象类型,直接将该对象拷贝到this.attributes上,如果key是字符串,那么将在内部把key,value转成一个临时对象attrs再拷贝到this.attributes上。

    set还有第三个可选参数options,如果设置了options.validate=true,且模型如果定义了validate方法,那么每次设置时将调用该方法进行校验,校验未通过将不进行后续设置,而直接返回。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var Person = Backbone.Model.extend({
        validate: function(attrs) {
            if ( !_.isString(attrs.name) ) return 'name 必须是字符串类型'
            if ( !_.isNumber(attrs.age) ) return 'age 必须是数字类型'
        }
    })
    var p1 = new Person()
    p1.on('invalid', function(model, error, agr) {
        console.log(error)
    })
    p1.set({name: 'Backus', age: 87})

    从控制台输入如下

    可以看到输出了提示信息“name 必须是字符串类型”,再打印出p1的JSON格式

    可以看到name仍然是“Backus”,并未修改。

    在set方法内部会调用私有的this._validate方法,该方法如下

    1
    2
    3
    4
    5
    6
    7
    8
    _validate: function(attrs, options) {
      if (!options.validate || !this.validate) return true;
      attrs = _.extend({}, this.attributes, attrs);
      var error = this.validationError = this.validate(attrs, options) || null;
      if (!error) return true;
      this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
      return false;
    }

    1.0与之前版本实现不同,必须显示的设置options.validate=true,且模型必须实现this.validate方法,才会进行验证,否则直接返回true。1.0之前默认就进行验证,无需设置options.validate为true。验证无效(失败)后会派发“invalid”事件,因此可以监听该事件做后续处理,比如显示一些必要的提示信息。

    默认情况下,set调用都会触发“change”事件,如下

    1
    2
    3
    4
    p1.on('change', function(model, error) {
        console.log('attributes has changed')
    })
    p1.set({name: 'Backus', age: 87})

    你可以在回调函数中去更新视图或处理特定的业务逻辑。如果你显示设置第三个参数中silent为true,将不会触发“change”事件。

    1
    p1.set({name: 'Backus', age: 87}, {silent: true})

    从set源码可以看到,this._validate执行在前,this.trigger在后。也就是说如果验证失败,那么就不会执行change事件。

    附set方法执行流程图

    把模型保存到服务器 - save

    save方法会把模型保存到服务器端,它的参数和set完全一致。内部调用set和sync方法。

    以下几点需要注意

    1. 默认会进行属性校验,即options.validate为true,校验失败将不会请求后台程序,也不会设置模型的this.attributes,直接返回,见源码

    1
    2
    3
    4
    5
    if (attrs && !options.wait) {
      if (!this.set(attrs, options)) return false;
    } else {
      if (!this._validate(attrs, options)) return false;
    }

    2. 首次保存时(isNew),会采用create方式(HTTP post),已存在的model则只需要update方式(HTTP put)

    如下

    1
    2
    3
    var p1 = new Person()
    p1.save({name: 'Backus', age: 87}) // create
    p1.save({name: 'John'}) // update

    3. 可以传success和error两个回调函数以处理保存成功与失败场景

    1
    2
    3
    4
    5
    var p1 = new Person()
    p1.save({name: 'Backus', age: 87}, {
        success: function() {},
        error: function() {}
    })

    4. 事件,save成功后会依次触发模型的“change”、“request”、“sync”事件。如果监听了这些事件,那么回调将得到执行

    从服务器获取模型 - fetch

    从服务器端获取使用fetch方法,fetch方法很短

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    fetch: function(options) {
      options = options ? _.clone(options) : {};
      if (options.parse === void 0) options.parse = true;
      var model = this;
      var success = options.success;
      options.success = function(resp) {
        if (!model.set(model.parse(resp, options), options)) return false;
        if (success) success(model, resp, options);
        model.trigger('sync', model, resp, options);
      };
      wrapError(this, options);
      return this.sync('read', this, options);
    },

    1. 它使用read方式(HTTP get)

    2. 请求成功后调用set方法设置模型属性(this.attributes),设置失败则直接返回不调用success,设置成功接着调用success,最后派发“sync”事件

    模型的事件 - change/invalid/sync

    上面已经提到的事件 change、 invalid、sync。change事件还可以只监听指定的属性,格式:"change:" + attributeName。如下

    1
    2
    3
    4
    var p1 = new Person()
    p1.on('change:name', function(model, error) {
        console.log('name has changed')
    })

    控制台中分别设置下name和age

    可以看到,只有设置name时才触发事件。

    除了Backbone.Model自身提供的事件,你还可以给自己的Model添加自定义的事件以满足需求。

    鸟瞰图

    1. 内部状态,各属性影响的方法

    2. 构造器执行流程

     
     
    分类: MVC
  • 相关阅读:
    UEBA——通过用户画像识别安全威胁
    《国富论》西方经济学的“圣经”——自利的人性是资本主义市场经济的基本假设,财富的源泉是劳动,钱变成可再生的钱“资产”而不是负债
    python berkeley 操作——尤其提示 需版本匹配
    druid.io 海量实时OLAP数据仓库 (翻译+总结) (1)——分析框架如hive或者redshift(MPPDB)、ES等
    万亿级日志与行为数据存储查询技术剖析(续)——Tindex是改造的lucene和druid
    编译原理Tiny语言的定义
    ubuntu 安装python,easy_install和pip
    ubuntu 安装eclipse
    ubuntu rpm 包安装使用
    linux chmod权限
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3259170.html
Copyright © 2020-2023  润新知