backbone 모형층 분석
14707 단어 backbone
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의 다른 옵션:
var myM = Backbone.Model.extend({})// Model ,myM
>_.keys(myM)
["extend", "__super__"]
>_.keys(Backbone.Model)
["extend"]
>_.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"]
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);
}
function () {
return Backbone.sync.apply(this, arguments);
}
>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"]
>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"]
>_.filter(m_obj_funcs, function(f){return !_.contains(base_funcs,f);})
["constructor"]
>m_obj.constructor
function (){ return parent.apply(this, arguments); }
>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"}
>m_obj.set({'name':'joe'})
>m_obj.changed
Object {name: "joe"}
>m_obj._previousAttributes
Object {name: "tommy", blog: "http://www.cnblogs.com/Tommy-Yu"}
>m_obj.has('name')
true
>m_obj.has('age')
false
>m_obj.get('name')
"tommy"
>m_obj.previousAttributes()
Object {name: "tommy", blog: "http://www.cnblogs.com/Tommy-Yu"}
>m_obj.previous('name')
"tommy"
>m_obj.toJSON()
Object {name: "tommy", blog: "http://www.cnblogs.com/Tommy-Yu"}
>m_obj.keys()
["name", "blog"]
m_obj.values()
["tommy", "http://www.cnblogs.com/Tommy-Yu"]
>m_obj.isNew()
true
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;
}
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;
}
function (resp, options) {
return resp;
}
fetch의 호출 체인
fetch -> this.sync -> Backbone.sync -> success(model, reponse, options) -> this.parse -> this.set -> this._validate -> changed -> update view
편폭 관계로 코드가 여기에 없습니다.간단하게 말하면fetch입니다. 순조롭게 진행되면 바로 보기를 바꿉니다.
전재는 본문이 Tommy.Yu의 블로그.에서 왔다는 것을 명기해 주십시오. 감사합니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
backbone 학습 노트:보기(View)Backbone 뷰 객체는 주로 데이터를 렌더링하고 이벤트를 수신하는 데 사용됩니다. Backbone의 보기 대상은 모델 데이터를 보여줄 수도 있고 사용자가 편집한 모델 데이터를 백엔드에 전달할 수도 있으며 이벤트 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.