backbone 모형층 분석

14707 단어 backbone
Model 레이어에는 두 가지 클래스가 있습니다: Model, Collection

1.Model


문서를 뒤지지 않고 우리는 코드로 이야기한다.

우선 하류를 분석하다.

var myM = Backbone.Model.extend({})//    Model ,myM


이 종류는 뜻밖에도 비어 있다. 정부에서 말한 것처럼 그렇게 많은 속성이 없는데, 설마 underscore가 고장났단 말인가?
>_.keys(myM)

["extend", "__super__"]

>_.keys(Backbone.Model)

["extend"]


기본적으로 하위 클래스가 상위 클래스보다 많음super__이게 도대체 뭐야?
>_.isObject(myM.__super__)

true

대상.관찰:
>_.keys(myM.__super__)

["on", "once", "off", "trigger", "stopListening", "listenTo", "listenToOnce", "bind", "unbind", "changed", "validationError", "idAttribute", "initialize", "toJSON", "sync", "get", "escape", "has", "set", "unset", "clear", "hasChanged", "changedAttributes", "previous", "previousAttributes", "fetch", "save", "destroy", "url", "parse", "clone", "isNew", "isValid", "_validate", "keys", "values", "pairs", "invert", "pick", "omit"]


결론: 부류의 지침?공식 문서에 열거된 인터페이스 (함수/이벤트/속성) 가 위와 같습니다.
데이터의 동기화에 관심이 많으므로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);

    } 


  
보시다시피 success 리셋, myM.fetch({success:function(model,response,options){}); 즉 성공적인 리셋 함수는 세 개의 매개 변수를 받아들인다.
그 다음은fetch가 자체의sync 함수 (마지막 줄) 를 호출합니다.
function () {

      return Backbone.sync.apply(this, arguments);

    } 


  
안개 자욱하다.지내다
분할선 -------------------------------------

분석 클래스의 인스턴스입니다.


myM 클래스의 인스턴스를 구성하고 분석하려면 다음과 같이 하십시오.
>m_obj= new myM;

s {cid: "c6", attributes: Object, _changing: false, _previousAttributes: Object, changed: Object…}

>_.isObject(m_obj)

true

>_.keys(m_obj)

["cid", "attributes", "_changing", "_previousAttributes", "changed", "_pending"]


먼저 실례의 속성은 클래스의 속성과 매우 다르고 부류의 속성과는 아무런 관계가 없는 것 같다(상속이 없다?).
정말 그런가요?
>_.functions(m_obj)

["_validate", "bind", "changedAttributes", "clear", "clone", "constructor", "destroy", "escape", "fetch", "get", "has", "hasChanged", "initialize", "invert", "isNew", "isValid", "keys", "listenTo", "listenToOnce", "off", "omit", "on", "once", "pairs", "parse", "pick", "previous", "previousAttributes", "save", "set", "stopListening", "sync", "toJSON", "trigger", "unbind", "unset", "url", "values"]


그래, 이거랑 myM.super__일정한 교집합이 있다.교차:
>m_obj_funcs = _.functions(m_obj)

base_funcs = _.functions(myM.__super__)

_.filter(base_funcs, function(f){return _.contains(m_obj_funcs,f)})



["_validate", "bind", "changedAttributes", "clear", "clone", "destroy", "escape", "fetch", "get", "has", "hasChanged", "initialize", "invert", "isNew", "isValid", "keys", "listenTo", "listenToOnce", "off", "omit", "on", "once", "pairs", "parse", "pick", "previous", "previousAttributes", "save", "set", "stopListening", "sync", "toJSON", "trigger", "unbind", "unset", "url", "values"]


 m_obj는 또 어떤 함수가 많이 나오나요?
>_.filter(m_obj_funcs, function(f){return !_.contains(base_funcs,f);})

["constructor"]


구조기인 것 같아요.
>m_obj.constructor

function (){ return parent.apply(this, arguments); } 


 

등록 정보


["cid", "attributes", "_changing", "_previousAttributes", "changed", "_pending"]
(팁: 이전 구조 m obj의 부분으로 돌아갑니다.)
먼저 스포일러를 하자면 attributes는 속성 키 값 대 집합(JSON 대상)으로 쓸 수 있다(읽기만 하는attributes라면 대상의 실례를 사용하는 toJSON() 방법).예를 들어,
>m_obj.set({'name':'tommy','blog':'http://www.cnblogs.com/Tommy-Yu'})

>m_obj.attributes

Object {name: "tommy", blog: "http://www.cnblogs.com/Tommy-Yu"}


그 다음으로 changed도 JSON 대상이다. 이 실례에서 어떤 속성이 바뀌었는지 기록한다. - 수정된 부분만 기록하고 백bone에 의해 분석된 다음에 change 이벤트 처리 방법에 전달된다.다음과 같습니다.
>m_obj.set({'name':'joe'})

>m_obj.changed

Object {name: "joe"}


_previous Attributes는 변경 전의 대상을 기록하여 데이터를 비교하고 복원하는 데 유리하다(예를 들어 취소 작업).
>m_obj._previousAttributes

Object {name: "tommy", blog: "http://www.cnblogs.com/Tommy-Yu"}


cid 이 동쪽, 임시 id에 대해서.특정 클래스(예: myM)의 객체에 자동으로 숫자순으로 번호를 매깁니다.
마지막으로 체인지입니다.

함수.


["_validate", "bind", "changedAttributes", "clear", "clone", "destroy", "escape", "fetch", "get", "has", "hasChanged", "initialize", "invert", "isNew", "isValid", "keys", "listenTo", "listenToOnce", "off", "omit", "on", "once", "pairs", "parse", "pick", "previous", "previousAttributes", "save", "set", "stopListening", "sync", "toJSON", "trigger", "unbind", "unset", "url", "values"]
제한된 분량을 고려하여 다음과 같은 주요 내용을 소개합니다.
initialize () - 대상이 new에 나올 때 호출되며, 여기에서 초기화할 수 있습니다.
소분할 ------------------
set () - 위에서 설명한 바와 같이 대상의attributes 속성을 설정합니다.set 전에 호출됩니다.validate(attributes) 방법 - 정의가 있는 경우 - 통과 여부를 확인하는 값(true/false)으로 되돌아옵니다.
has -- 객체의 attributes에 attr 속성이 있는지 여부를 판단합니다.
>m_obj.has('name')

true

>m_obj.has('age')

false

get -- 객체의 attributes 속성에서 키 값을 가져옵니다.
>m_obj.get('name')

"tommy"

-----------소분할 -------------
 
previousAttributes() ---  _previous Attributes 속성의 get 봉인
>m_obj.previousAttributes()

Object {name: "tommy", blog: "http://www.cnblogs.com/Tommy-Yu"}


previous - 과 같습니다.previousAttributes[key] 
>m_obj.previous('name')

"tommy"


-----------소분할 -------------
toJSON() - json 객체로 전환
>m_obj.toJSON()

Object {name: "tommy", blog: "http://www.cnblogs.com/Tommy-Yu"}

keys() - 키를 배열로 변환
>m_obj.keys()

["name", "blog"]

values () - 값을 배열로 변환
m_obj.values()

["tommy", "http://www.cnblogs.com/Tommy-Yu"]


-----------소분할 -------------
isNew() - 클라이언트의 새 객체 만들기(서버와 동기화할 때 사용) 여부
>m_obj.isNew()

true


isValide() - 객체가 유효성 검사를 통과했는지 여부
호출validate(attributes).attributes는 키 값 대 집합입니다.
-----------소분할 ------------
bind(시간 코드, 시간 처리 함수)
이벤트 코드는:change,error,sync,...
각각 다른 처리 함수에 대응하여 익명 함수로 할 수 있다.
-----------소분할 -------------
CRUD 작업:fetch/save/destroy
일반적:sync
전제: url 설정 (string/funciton -->ajax 경로)
fetch/save/destroy/sync를 Backbone에 의뢰합니다.sync 함수, 이 함수는 Backbone과 서버 통신의 핵심, Backbone.sync 코드는 다음과 같습니다.
function (method, model, options) {

    var type = methodMap[method];



    // Default options, unless specified.

    _.defaults(options || (options = {}), {

      emulateHTTP: Backbone.emulateHTTP,

      emulateJSON: Backbone.emulateJSON

    });



    // Default JSON-request options.

    var params = {type: type, dataType: 'json'};



    // Ensure that we have a URL.

    if (!options.url) {

      params.url = _.result(model, 'url') || urlError();

    }



    // Ensure that we have the appropriate request data.

    if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {

      params.contentType = 'application/json';

      params.data = JSON.stringify(options.attrs || model.toJSON(options));

    }



    // For older servers, emulate JSON by encoding the request into an HTML-form.

    if (options.emulateJSON) {

      params.contentType = 'application/x-www-form-urlencoded';

      params.data = params.data ? {model: params.data} : {};

    }



    // For older servers, emulate HTTP by mimicking the HTTP method with `_method`

    // And an `X-HTTP-Method-Override` header.

    if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {

      params.type = 'POST';

      if (options.emulateJSON) params.data._method = type;

      var beforeSend = options.beforeSend;

      options.beforeSend = function(xhr) {

        xhr.setRequestHeader('X-HTTP-Method-Override', type);

        if (beforeSend) return beforeSend.apply(this, arguments);

      };

    }



    // Don't process data on a non-GET request.

    if (params.type !== 'GET' && !options.emulateJSON) {

      params.processData = false;

    }



    // If we're sending a `PATCH` request, and we're in an old Internet Explorer

    // that still has ActiveX enabled by default, override jQuery to use that

    // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8.

    if (params.type === 'PATCH' && noXhrPatch) {

      params.xhr = function() {

        return new ActiveXObject("Microsoft.XMLHTTP");

      };

    }



    // Make the request, allowing the user to override any Ajax options.

    var xhr = options.xhr = Backbone.ajax(_.extend(params, options));

    model.trigger('request', model, xhr, options);

    return xhr;

  } 


 
Backbone 이 주로 사용됩니다.ajax는 데이터의 상호작용을 실현하고 jqXHR(jquery XmlHttp Response)를 되돌려줍니다.
하나를 골라라. 예를 들어save가 Backbone을 어떻게 호출하는지 보자.sync의 save 코드는 다음과 같습니다.
function (key, val, options) {

      var attrs, method, xhr, attributes = this.attributes;



      // Handle both `"key", value` and `{key: value}` -style arguments.

      if (key == null || typeof key === 'object') {

        attrs = key;

        options = val;

      } else {

        (attrs = {})[key] = val;//attrs => Object {key: val}

      }



      options = _.extend({validate: true}, options);



      // If we're not waiting and attributes exist, save acts as

      // `set(attr).save(null, opts)` with validation. Otherwise, check if

      // the model will be valid when the attributes, if any, are set.

      if (attrs && !options.wait) {

        if (!this.set(attrs, options)) return false;

      } else {

        if (!this._validate(attrs, options)) return false;

      }



      // Set temporary attributes if `{wait: true}`.

      if (attrs && options.wait) {

        this.attributes = _.extend({}, attributes, attrs);

      }



      // After a successful server-side save, the client is (optionally)

      // updated with the server-side state.

      if (options.parse === void 0) options.parse = true;

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

        if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);

        if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {

          return false;

        }

        if (success) success(model, resp, options);

        model.trigger('sync', model, resp, options);

      };

      wrapError(this, options);



      method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');

      if (method === 'patch') options.attrs = attrs;

      xhr = this.sync(method, this, options);



      // Restore attributes.

      if (attrs && options.wait) this.attributes = attributes;



      return xhr;

    } 


  
책 네 번째 문장을 주목하라.
xhr  = this.sync(method, this, options); 
이렇게 해서save는sync에 작업을 잃어버렸는데, 그 주요 업무는options와method를 가공하고 리셋을 설정하며sync에 잃어버리기 전의 데이터 검증이다.
지금까지 몇 가지 유용한 정보를 잡았습니다.
1. 옵션에 URL을 전송할 수 있으며 모델보다 우선순위가 높습니다.
2. 모델의sync를 다시 써서 모델이 도대체 이 입력 매개 변수에 대해 무엇을 했는지 관찰할 수 있다.
3. 옵션에 success 리셋을 설정할 수 있습니다.데이터 타입 기본값은 json입니다.
4. options의 다른 옵션:
  • URL, 우선순위는 Backbone.Model.url 높음
  • 데이터, 설정하지 않으면 콘텐츠 type이'application/json'
  • 일 수 있습니다
  • attrs,데이터의 후보
  • emulateJSON, 오래된 서버 호환, JSON->HTML Form, 콘텐츠Type은'application/x-www-form-urlencoded', 데이터는 비어있음
  • emulateHTTP, 이 옵션은 더 오래된 서버를 호환하는 데 사용되며, http 헤더에 X-HTTP-method-Override 등을 추가
  • wait, 호출 여부validate 함수
  • parse, 함수/void 0, 클라이언트가 서버에서 전송된 데이터를 분석하는 함수, 기본값은 다음과 같습니다.
    function (resp, options) {
    
    return resp;
    
    }

  • success, function(모델,reponse,options) 리셋 성공
  • patch ,??

  • fetch의 호출 체인
    fetch -> this.sync -> Backbone.sync -> success(model, reponse, options) -> this.parse -> this.set -> this._validate -> changed -> update view
    편폭 관계로 코드가 여기에 없습니다.간단하게 말하면fetch입니다. 순조롭게 진행되면 바로 보기를 바꿉니다.
     
     
    전재는 본문이 Tommy.Yu의 블로그.에서 왔다는 것을 명기해 주십시오. 감사합니다!

    좋은 웹페이지 즐겨찾기