>웹 프론트엔드 >JS 튜토리얼 >Model 모델의 소스코드와 Backbone.js_Basic 지식에 대한 간략한 이해

Model 모델의 소스코드와 Backbone.js_Basic 지식에 대한 간략한 이해

WBOY
WBOY원래의
2016-05-16 15:15:481052검색

백본.모델

오늘은 먼저 Backbone.js MVC에 대해 이야기하겠습니다. 모델은 페이지 표시 콘텐츠에 대한 데이터와 데이터 작업을 둘러싼 다양한 변환, 검증, 계산 및 권한 제어를 포함하는 백본의 핵심 부분입니다. , 서버 측 상호 작용 및 기타 작업을 수행하려면 Backbone.Model.extend()를 통해 모델을 생성할 수 있습니다. 물론 생성된 모델을 기본 클래스로 사용하여 더 많은 모델을 확장할 수도 있습니다

 var People = Backbone.Model.extend({
     
 });

 var Man = People.extend({

 });

Backbone.Model API

Backbone.Model은 모델의 기본 작업을 구현하기 위한 다양한 방법을 제공합니다. 물론 가장 기본적인 방법은 Backbone.Events를 기반으로 하는 이벤트 메커니즘입니다. attr 이벤트는 Trigger가 되며, 제공되는 API는 다음과 같습니다.

2016214171632823.png (207×574)

데이터에 대해 서버측 작업을 수행하는 방법은 다음과 같습니다.

  • sync: xhr의 기본 클래스인 Backbone.sync를 래핑합니다
  • 가져오기: 서버에서 데이터를 가져오는 데 사용됩니다
  • 저장: 데이터를 서버에 유지
  • destroy: 서버에서 데이터를 삭제합니다

모델의 데이터 조작 방법:

  • get: 속성에서 데이터 가져오기
  • set: 데이터를 속성으로 설정
  • escape: 밑줄의 _.escape를 사용하여 데이터를 인코딩합니다
  • has: 속성에 해당 데이터가 있는지 여부
  • 설정 해제: 속성에서 데이터 삭제
  • clear: 속성 데이터 지우기
  • changed: 이전 상태(set, unset이 실행됨) 대비 변경된 값
  • toJSON: 속성을 객체로 직렬화
  • parse: 설정 항목 구문 분석이 true인 경우 초기화/설정/설정 해제/가져오기 및 기타 데이터 작업 중에 대상 데이터를 구문 분석하여 구문 분석된 개체를 반환합니다. 이 메서드는 빈 메서드이므로 재정의해야 합니다.
  • hasChanged: 이전 상태와 비교하여 변화가 있는지 여부(set, unset이 실행됨)
  • changeAttributes: 이전 상태(set, unset이 실행됨)와 비교하여 발생한 모든 값
  • previous: 이전 상태(set, unset이 실행됨), 이 속성에 해당하는 값
  • previousAttributes: 이전 상태(set, unset이 실행됨)에서 변경된 객체의 이전 상태의 모든 값

모델 내 데이터 검증 방법:

  • validate: 모델의 데이터를 확인하는 데 사용되며 기본 방법을 재정의하려면 재정의해야 합니다.
  • validationError: 최근 잘못된 오류가 발생했을 때 반환된 값을 반환합니다
  • isValid: _validate 메소드 호출

일부 주요 API는 아래에 설명되어 있습니다.

건축자

  var Model = Backbone.Model = function(attributes, options) {
     var attrs = attributes || {};
     options || (options = {});
     this.cid = _.uniqueId('c');
     this.attributes = {};
     if (options.collection) this.collection = options.collection;
     if (options.parse) attrs = this.parse(attrs, options) || {};
     attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
     this.set(attrs, options);
     this.changed = {};
     this.initialize.apply(this, arguments);
   };

생성자는 주로 초기화된 데이터와 옵션을 설정한 다음 모델을 표시하기 위해 고유한 cid를 생성합니다. 옵션의 구문 분석이 true인 경우 초기화된 값은 구문 분석 메서드와 호출 집합 메서드를 통해 구문 분석되며 모든 초기 값은 ​​속성에 저장되고 초기화 초기화 메서드가 호출됩니다. 모델 초기화가 완료되었습니다.

설정

model.set(attributes, [options])

set 메소드는 속성에 값을 설정합니다. 설정 중에 클라이언트가 true로 설정되면 해당 변경:attr 이벤트가 트리거됩니다. 마지막으로 변경 이벤트가 세트 코드의 일부로 트리거됩니다. 방법은 다음과 같습니다.

  set: function(key, val, options) {
     //......

      // key值可以是键值对,也可以是一个字符串,将赋值传入attrs属性中  
    if (typeof key === 'object') {
     attrs = key;
     options = val;
    } else {
     (attrs = {})[key] = val;
    }

   // ....

    //对设置的值进行校验 
      if (!this._validate(attrs, options)) return false;
    unset = options.unset; // unset为true时会删除设置的值,unset方法就是通过 set(key,val,{unset:true})去实现的
   
    //当对象正在被被设置的时候,不给 previousAttributes 赋值
    if (!changing) {
     this._previousAttributes = _.clone(this.attributes);
     this.changed = {};
    }
 
    current = this.attributes, prev = this._previousAttributes;
 
    //如果对Id进行了设置,则对对象的id属性也进行改变
    if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
 

    //进行 设置或者是删除操作
    for (attr in attrs) {
     val = attrs[attr];
     if (!_.isEqual(current[attr], val)) changes.push(attr);
     if (!_.isEqual(prev[attr], val)) {
      this.changed[attr] = val;//为model的changed进行设置
     } else {
      delete this.changed[attr];
     }
     unset ? delete current[attr] : current[attr] = val;//如果unset被设置成true了,则进行删除操作
    }
 
    //在silent不为false 的情况下,进行change:attr事件发送
    if (!silent) {
     if (changes.length) this._pending = options;
     for (var i = 0, l = changes.length; i < l; i++) {
      this.trigger('change:' + changes[i], this, current[changes[i]], options);
     }
    }
 

    //触发change事件
    if (changing) return this;
    if (!silent) {
     while (this._pending) {
      options = this._pending;
      this._pending = false;
      this.trigger('change', this, options);
     }
    }
    this._pending = false;
    this._changing = false;
    return this;
   
  }

설정의 전체 과정은 들어오는 값을 처리하여 키-값 쌍으로 변환한 다음 값을 확인하고 정확성을 확인한 다음 설정 작업을 시작하는 것입니다. 설정 시 확인 시 값이 변경됩니다. 있는 경우 변경된 객체에 추가한 후 unset 값을 확인하고 해당 추가, 업데이트, 삭제 작업을 수행합니다. 그런 다음 Change:attr 및 변경 이벤트가 순서대로 트리거됩니다.

저장

model.save([attributes], [options])

save 메소드는 데이터를 클라이언트에 유지하는 데 사용되며 다양한 데이터 및 구성에 따라 생성, 업데이트 또는 패치를 사용하고 동기화 이벤트를 트리거합니다.

  save: function(key, val, options) {     
    // ......
 

 
    //当设置了wait属性true的时候 , save方法先不执行set方法(不触发change事件),只执行validate
    if (attrs && !options.wait) {
     if (!this.set(attrs, options)) return false;
    } else {
     if (!this._validate(attrs, options)) return false;
    }

    //如果wait为true,设置this.attributes
    if (attrs && options.wait) {
     this.attributes = _.extend({}, attributes, attrs);
    }
 

    // .....
   
    var model = this;
    var success = options.success;
    options.success = function(resp) {
     // Ensure attributes are restored during synchronous saves.
     model.attributes = attributes;
     var serverAttrs = model.parse(resp, options);
     //如果wait为true , 那么会在请求返回之后才进行set操作
     if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
     if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {
      return false;
     }
     if (success) success(model, resp, options);
     //触发 sync 事件
     model.trigger('sync', model, resp, options);
    };

    //生成XHR onerror 回调函数
    wrapError(this, options);
    //选择方法
    method = this.isNew() &#63; 'create' : (options.patch &#63; 'patch' : 'update');
    if (method === 'patch') options.attrs = attrs;
    xhr = this.sync(method, this, options);
 
    // Restore attributes.
    if (attrs && options.wait) this.attributes = attributes;
    //返回xhr对象
    return xhr;
  }

 
save 中最需要注意的就是 wait 的设置,当wait为真的时候,save返回会在xhr返回之后再执行set操作,而不是在xhr之前就进行set操作,因此change事件的触发时机也就不同了。

之前说过整个Backbone都是通过事件串联起来的,所以对于事件触发时机的了解和把握是非常重要的,不然会在开发过程中导致一些奇怪的问题出现。

Backbone.View
前面已经对backbone中的Event、Model、Collection代码进行了分析,现在我们来看下MVC中的V部分,也就是Backbone.View,View在Backbone中主要用于沟通页面中的DOM和Backbone.Model/Collection,页面的逻辑操作,DOM事件的绑定等,View部分的代码非常简答,加上注释只有110左右。 View部分有一下API:

2016214171843674.png (197×245)

方法不多,下面对部分API进行介绍:

构造方法

  var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
 var View = Backbone.View = function(options) {
   this.cid = _.uniqueId('view');
   options || (options = {});
   _.extend(this, _.pick(options, viewOptions));
   this._ensureElement();
   this.initialize.apply(this, arguments);
   this.delegateEvents();
 };

构造方法中为View生成了一个唯一的cid,以'view'开头,然后进行对目标属性viewOptions进行合并,接着调用_ensureElement判断el的情况,接着调用delegateEvents进行方法绑定,初始化完成 。

delegateEvents

view.setElement(element)

   setElement: function(element, delegate) {
    if (this.$el) this.undelegateEvents();//如果已经存在this.$el,进行事件解绑

    //对$el进行赋值,本质是一个jquery或者是 Lo-Dash and Zepto 对象
    this.$el = element instanceof Backbone.$ &#63; element : Backbone.$(element);
    //把dom element 赋值给el
    this.el = this.$el[0];

     //如果没有显式传值,则进行事件绑定
    if (delegate !== false) this.delegateEvents();
    return this;
   }

setElement方法用于设置View对应的element , 这个方法在new的时候会被调用, 如果想要在使用过程中改变View的dom元素指向,可调用这个方法进行重新设置

_ensureElement

  _ensureElement: function() {
     //如果已经对el进行设置,直接调用setElement方法
    if (!this.el) {//如果没有设置,生成一个元素对象,再调用setElement方法
     var attrs = _.extend({}, _.result(this, 'attributes'));
     if (this.id) attrs.id = _.result(this, 'id');
     if (this.className) attrs['class'] = _.result(this, 'className');
     var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs);
     this.setElement($el, false);
    } else {
     this.setElement(_.result(this, 'el'), false);
    }
  }

_ensureElement这个方法是内部方法,在构造函数中使用,用于判断指定的el在页面中存不存在,如果存在则对$el进行赋值,如果不存在,则生成一个$el,但是要注意这个对象是没有落地到dom树中的 。

delegateEvents

delegateEvents([events])

    // *{"event selector": "callback"}*
   //
   //   {
   //    'mousedown .title': 'edit',
   //    'click .button':   'save',
   //    'click .open':    function(e) { ... }
   //   }

   delegateEvents: function(events) {
      //如果不存在events,则直接返回
      if (!(events || (events = _.result(this, 'events')))) return this;
   
      //先解除所有的事件绑定
      this.undelegateEvents();
   
      //处理每个事件
      for (var key in events) {
       var method = events[key];
       //解析回调函数
       if (!_.isFunction(method)) method = this[events[key]];
       if (!method) continue;
   
       //对选择器进行分析
       var match = key.match(delegateEventSplitter);
       var eventName = match[1], selector = match[2];
       method = _.bind(method, this);
   
       //绑定的事件名都是以 eventName + '.delegateEvents' + cid 组成,
       //这么做能够在undelegateEvents的时候选择到这个View的所有事件
       eventName += '.delegateEvents' + this.cid;
       if (selector === '') {
        this.$el.on(eventName, method);
       } else {
        this.$el.on(eventName, selector, method);
       }
      }
      return this;
   }

在View中你可以使用一个 key:value 集合指定对应的事件,在初始化的时候构造函数会调用delegateEvents进行绑定,需要注意的是所有在key中指定的元素的父元素都必须是$el,也就是说元素必须是$el的子节点,否则绑定失败。

View和其他backbone模块一个区别就是没有自己的内建自定义事件,当然他也组合了Events模块,但是所有的事件都需要自己进行建立。View主要是一个MVC模型的承载,其实真正的功能不多,其实从模型层面上看V在前端开发中是最接近业务逻辑的,所以在View中大部分的逻辑都是开发者自己去扩展的。

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.