BACKBONE.JS 단순 입문 범례
18552 단어 BACKBONE.JS
1.구조 적 으로 4 절 로 나 뉘 어 Model/View/collection 을 소개 하고 원 격 으로 데 이 터 를 가 져 와 표 에 표시 하고 수정 삭제 합 니 다.
2.'범례'라 고 부 르 기 때문에 코드 를 위주 로 하고 각 절의 첫 번 째 코드 는 전체 코드 이 며 복사 붙 여 넣 기 를 하면 사용 할 수 있 습 니 다.모든 코드 는 앞의 코드 를 바탕 으로 작성 되 기 때문에 각 코드 의 새로운 내용 은 20 줄 을 초과 하지 않 습 니 다(대괄호 계산 포함).
3.각 줄 코드 에 주석 이 없 지만 중요 한 내용 을 쓴 후에 구체 적 인 설명 이 있다.
4.개발 환경 은 Chrome 입 니 다.github 의 API 를 사용 하면 Chrome 으로 로 컬 경로(file://와 같은 경로)에서 도 데 이 터 를 얻 을 수 있 습 니 다.
0. Introduction
거의 모든 프레임 워 크 는 두 가지 일 을 하고 있 습 니 다.하 나 는 코드 를 정확 한 곳 에 쓰 는 것 입 니 다.둘 째 는 너 를 도와 더러 운 일 을 하고 힘 든 일 을 하 는 것 이다.Backbone 은 뚜렷 한 MVC 코드 구 조 를 실현 하여 데이터 모델 과 보기 맵 의 문 제 를 해결 했다.모든 JS 관련 항목 을 사용 할 수 있 지만 Backbone 은 이런 장면 에 가장 적합 합 니 다.JS 로 대량의 페이지 내용(HTML 위주)을 생 성 해 야 하고 사용자 와 페이지 요 소 는 많은 상호작용 을 합 니 다.
Backbone 대상 은 5 개의 중요 한 함수,Model/collection/View/Router/History 가 있 습 니 다.Router 와 History 는 웹 애플 리 케 이 션 의 최적화 로 push State 에 관 한 지식 을 먼저 익히 는 것 을 권장 합 니 다.입문 단 계 는 Model/collection/View 만 알 수 있 습 니 다.모델 을 핵심 으로,컬 렉 션 은 모델 의 집합 으로,뷰 는 모델 의 변경 이 전면 에 반 영 될 수 있 도록 하기 위 한 것 이다.
1. Model
Model 은 모든 JS 응용의 핵심 이 고 많은 Backbone 튜 토리 얼 은 View 부터 말 하 는 것 을 좋아 합 니 다.사실은 View 의 내용 이 많 지 않 고 View 의 의미 가 크 지 않 고 Model 을 이해 하 는 것 이 더 중요 합 니 다.다음 코드 는 github 의 API 에서 gist 정 보 를 가 져 와 페이지 에 표시 합 니 다.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone-min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
</head>
<body>
<table id="js-id-gists" class="table">
<thead><th>description</th><th>URL</th><th>created_at</th></thead>
<tbody></tbody>
</table>
<script type="text/javascript">
var Gist = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return (response[0]);
}
}),
gist = new Gist();
gist.on('change', function (model) {
var tbody = document.getElementById('js-id-gists').children[1],
tr = document.getElementById(model.get('id'));
if (!tr) {
tr = document.createElement('tr');
tr.setAttribute('id', model.get('id'));
}
tr.innerHTML = '<td>' + model.get('description') + '</td><td>' + model.get('url') + '</td><td>' + model.get('created_at') + '</td>';
tbody.appendChild(tr);
});
gist.fetch();
</script>
</body>
</html>
LINE 4~8:사용 할 JS 라 이브 러 리 를 불 러 옵 니 다.ajax 요청 과 일부 View 기능 은 jQuery 지원 이 필요 합 니 다(또는 ajax/View 를 다시 쓰 는 기능).Backbone 의 코드 는 Underscore 를 기반 으로 작 성 된 것 입 니 다(또는 Lo-Dash 로 대체).bootstrap.css 를 불 러 오 는 것 은 기본 스타일 이 너무 못 생 겨 서...LINE 16~22:모델 을 만 들 고 예화 합 니 다.url 은 데이터 원본(API 인터페이스)의 주소 이 며,parse 는 되 돌아 오 는 데 이 터 를 처리 합 니 다.실제 되 돌아 온 것 은 Array 입 니 다.여기 서 첫 번 째 Object 를 가 져 옵 니 다.
LINE 24~33:바 인 딩 change 이벤트.아직 View 를 사용 하지 않 았 기 때문에 HTML 을 스스로 처리 해 야 합 니 다.이 10 줄 코드 는 주로 get 의 용법(model.get)이 고 다른 기능 은 나중에 View 로 이 루어 집 니 다.
LINE 34:fetch 를 실행 합 니 다.원 격 으로 데 이 터 를 가 져 오 면 데 이 터 를 얻 으 면 change 이벤트 가 발생 합 니 다.sync 방법 을 다시 쓸 수 있 습 니 다.
Chrome 의 Console 을 열 고 gist 를 입력 하면 Model 에서 얻 은 속성 을 볼 수 있 습 니 다.
모델 은 데이터 와 데이터 관련 논 리 를 제공한다.위의 그림 에서 출력 한 속성 은 데이터 입 니 다.코드 에 있 는 fetch/parse/get/set 는 모두 데 이 터 를 조작 합 니 다.다른 것 은 escape/unset/clear/destory 도 있 습 니 다.함수 이름 에서 그 용 도 를 대체적으로 알 수 있 습 니 다.그리고 자주 사용 하 는 vaidate 함수 도 있 습 니 다.set/save 작업 시 데이터 검증 에 사용 되 며 검증 에 실패 하면 invalid 이벤트 가 발생 합 니 다.
/* JS (LINE16~34) */
var Gist = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return (response[0]);
},
defaults: {
website: 'dmyz'
},
validate: function (attrs) {
if (attrs.website == 'dmyz') {
return 'Website Error';
}
}
}),
gist = new Gist();
gist.on('invalid', function (model, error) {
alert(error);
});
gist.on('change', function (model) {
var tbody = document.getElementById('js-id-gists').children[1],
tr = document.getElementById(model.get('id'));
if (!tr) {
tr = document.createElement('tr');
tr.setAttribute('id', model.get('id'));
}
tr.innerHTML = '<td>'+ model.get('description') +'</td><td>'+ model.get('url') +'</td><td>'+ model.get('created_at') +'</td>';
tbody.appendChild(tr);
});
gist.save();
이전 코드 와 비교 하면 4 곳 이 변경 되 었 습 니 다.LINE 7~9:defaults 가 추가 되 었 습 니 다.속성 에 웹 사이트 가 없 으 면 웹 사이트 값 이 비어 있 지 않 음 을 주의 하 십시오.웹 사이트 값 은 dmyz 로 설정 합 니 다.
LINE 10~14:validate 함 수 를 추가 합 니 다.웹 사이트 값 이 dmyz 일 때 invalid 이벤트 가 발생 합 니 다.
LINE 18~20:invalid 이벤트,alert 가 되 돌아 오 는 오류 입 니 다.
LINE 31:fetch 를 하지 않 고 직접 save 작업 을 합 니 다.
fetch 가 없 기 때문에 페이지 에 데이터 가 표시 되 지 않 습 니 다.save 작업 을 실행 하면 vaidate 함 수 를 호출 합 니 다.검증 실패 시 invalid 이벤트 가 발생 합 니 다.alert 에서 오류 알림 이 발생 합 니 다.또한 save 작업 도 Model 의 URL 에 PUT 요청 을 합 니 다.github 이라는 API 는 PUT 를 처리 하지 않 았 기 때문에 404 오 류 를 되 돌려 줍 니 다.
Console 에 gist.set('description','demo')를 입력 하면 페이지 요소 에 도 변화 가 있 음 을 볼 수 있 습 니 다.gist.set('description',gist.previous('description')를 실행 하여 이전 값 을 복원 합 니 다.이것 이 바로 Model 과 View 의 맵 입 니 다.지금도 스스로 이 루어 지고 있 습 니 다.다음 절 은 Backbone 의 View 로 이 루어 집 니 다.
2. View
Backbone 의 View 로 이전 코드 LINE 24~33 부분 을 고 칩 니 다.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone-min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
</head>
<body>
<table id="js-id-gists" class="table">
<thead><th>description</th><th>URL</th><th>created_at</th><th></th></thead>
<tbody></tbody>
</table>
<script type="text/javascript">
var Gist = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response[0];
}
}),
gist = new Gist();
var GistRow = Backbone.View.extend({
el: 'tbody',
MODEL: gist,
events: {
'click a': 'replaceURL'
},
replaceURL: function () {
this.MODEL.set('url', 'http://dmyz.org');
},
initialize: function () {
this.listenTo(this.MODEL, 'change', this.render);
},
render: function () {
var model = this.MODEL,
tr = document.createElement('tr');
tr.innerHTML = '<td>' + model.get('description') + '</td><td>' + model.get('url') + '</td><td>' + model.get('created_at') + '</td><td><a href="javascript:void(0)" rel="external nofollow" rel="external nofollow" rel="external nofollow" >®</a></td>';
this.el.innerHTML = tr.outerHTML;
return this;
}
});
var tr = new GistRow();
gist.fetch();
</script>
</body>
</html>
LINE 25:모든 View 는 DOM 기반 입 니 다.el 을 지정 하면 페이지 의 요 소 를 선택 합 니 다.tagName 을 지정 하면 해당 DOM 을 만 듭 니 다.지정 하지 않 으 면 빈 div 입 니 다.LINE 27~32:click 이 벤트 를 a 탭 에 연결 하면 replace URL 함수 가(set)url 속성의 값 을 수정 합 니 다.
LINE 33~35:View 의 초기 화 함수(initialize),change 이 벤트 를 감청 하고 Model 데이터 가 업 데 이 트 될 때 render 함 수 를 터치 합 니 다.
LINE 36~42:render 함수.주로 LINE 41~42 두 줄 로 생 성 된 HTML 코드 를 this.el 에 쓰 고 this 로 되 돌려 줍 니 다.
LINE 44:GistRow 를 실례 화하 면 함수 초기 화(initialize)가 실 행 됩 니 다.
줄 끝의 a 탭 을 누 르 면 페이지 에 표 시 된 이 기록 의 URL 이 수 정 됩 니 다.http://dmyz.org。
이 View 는 GistRow 라 고 하 는데 tbody 라벨 을 선택 한 것 은 분명 합 리 적 이지 않다.다음은 JS 코드 를 변경 하여 API 가 되 돌아 오 는 30 개의 데 이 터 를 표시 합 니 다.
/* JS (LINE16~45) */
var Gist = Backbone.Model.extend(),
Gists = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response;
}
}),
gists = new Gists();
var GistRow = Backbone.View.extend({
tagName: 'tr',
render: function (object) {
var model = new Gist(object);
this.el.innerHTML = '<td>' + model.get('description') + '</td><td>'+ model.get('url') + '</td><td>' + model.get('created_at') + '</td><td></td>'
return this;
}
});
var GistsView = Backbone.View.extend({
el: 'tbody',
model: gists,
initialize: function () {
this.listenTo(this.model, 'change', this.render);
},
render: function () {
var html = '';
_.forEach(this.model.attributes, function (object) {
var tr = new GistRow();
html += tr.render(object).el.outerHTML;
});
this.el.innerHTML = html;
return this;
}
});
var gistsView = new GistsView();
gists.fetch();
LINE 2~9:두 개의 Model(Gist 와 Gists)을 만 들 었 습 니 다.parse 는 이제 첫 번 째 가 아 닌 전체 Array 로 돌아 갑 니 다.LINE 11~18:tr 를 만 듭 니 다.render 방법 은 Object 를 보 내 서 Gist 의 Model 을 예화 하고 이 Model 에서 get 에 필요 한 값 을 얻 습 니 다.
LINE 26~34:Model 의 모든 속성 을 옮 겨 다 닙 니 다.현재 Collection 대신 Model 을 사용 하고 있 기 때문에 Object 를 옮 겨 다 니 고 있 습 니 다.foreach 는 Underscore 의 함수 입 니 다.
Backbone 의 View 는 조직 코드 의 역할 이 더 많 고 실제 적 으로 하 는 일이 매우 적다.View 의 model 속성 은 이 절 첫 번 째 코드 에 대문자 로 사용 되 는데 하나의 이름 임 을 나타 내 는 것 입 니 다.View 에 Model 을 보 내 면 무엇 을 완성 할 것 인지,논 리 를 제어 할 것 인지,아니면 스스로 써 야 합 니 다.그리고 View 에서 자주 사용 하 는 template 함수 도 스스로 정의 해 야 합 니 다.구체 적 으로 어떤 템 플 릿 엔진 을 결합 해서 사용 하 는 지 는 자신의 수 요 를 볼 수 있 습 니 다.
이 코드 의 Gists 는 그 중의 모든 값 을 조작 하기 어렵 습 니 다.이것 은 사실 Gist 의 집합 이 어야 합 니 다.이것 이 바로 Backbone 의 Collection 이 하 는 일 입 니 다.
3. Collection
Collection 은 Model 의 집합 입 니 다.이 Collection 에 있 는 Model 이 어떤 사건 을 촉발 하면 Collection 에서 받 아 처리 할 수 있 습 니 다.2 절의 코드 는 Collection 으로 이 루어 집 니 다.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone-min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
</head>
<body>
<table id="js-id-gists" class="table">
<thead><th>description</th><th>URL</th><th>created_at</th><th></th></thead>
<tbody></tbody>
</table>
<script type="text/javascript">
var Gist = Backbone.Model.extend(),
Gists = Backbone.Collection.extend({
model: Gist,
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response;
}
}),
gists = new Gists();
var GistRow = Backbone.View.extend({
tagName: 'tr',
render: function (model) {
this.el.innerHTML = '<td>' + model.get('description') + '</td><td>'+ model.get('url') + '</td><td>' + model.get('created_at') + '</td><td></td>'
return this;
}
});
var GistsView = Backbone.View.extend({
el: 'tbody',
collection: gists,
initialize: function () {
this.listenTo(this.collection, 'reset', this.render);
},
render: function () {
var html = '';
_.forEach(this.collection.models, function (model) {
var tr = new GistRow();
html += tr.render(model).el.outerHTML;
});
this.el.innerHTML = html;
return this;
}
});
var gistsView = new GistsView();
gists.fetch({reset: true});
</script>
</body>
</html>
LINE 17~23:기본적으로 2 절의 2 단 코드 와 같 습 니 다.Model 을 Collection 으로 변경 하고 Collection 의 Model 을 지정 합 니 다.그러면 Collectio 가 반환 값 을 얻 으 면 자동 으로 Model 의 Array 로 봉 인 됩 니 다.LINE 38:Collection 은 Model 과 달리 데 이 터 를 가 져 와 도 이벤트 가 발생 하지 않 기 때문에 reset 이 벤트 를 연결 하고 다음 fetch 작업 에서{reset:true}을 전달 합 니 다.
LINE 42~45:Collection 에서 Model 을 옮 겨 다 니 며 GistRow 라 는 View 에 전달 하여 HTML 을 생 성 합 니 다.
Collection 은 Backbone 에서 가장 많은 기능 을 가 진 함수(Underscore 의 경우 가 많 지만)이 며,Model 과 View 의 관 계 를 이해 하면 Collection 을 사용 하 는 데 아무런 장애 가 없 을 것 이다.Collection 에 각종 이 벤트 를 연결 하여 풍부 한 상호작용 기능 을 실현 합 니 다.아래 의 JS 코드 는 삭제/편집 작업 을 추가 하여 JSBIN 에서 소스 코드 와 실행 결 과 를 볼 수 있 습 니 다.이벤트 만 추 가 했 을 뿐 새로운 내용 이 없어 서 설명 을 하지 않 겠 습 니 다.JSBIN 의 프 리 젠 테 이 션 주 소 를 동봉 합 니 다http://jsbin.com/jevisopo/1
/* JS (LINE16~51) */
var Gist = Backbone.Model.extend(),
Gists = Backbone.Collection.extend({
model: Gist,
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response;
}
}),
gists = new Gists();
var GistRow = Backbone.View.extend({
tagName: 'tr',
render: function (model) {
this.el.id = model.cid;
this.el.innerHTML = '<td>' + model.get('description') + '</td><td>'+ model.get('url') + '</td><td>' + model.get('created_at') + '</td><td><a href="javascript:void(0)" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="js-remove">X</a> <a href="javascript:void(0)" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="js-edit">E</a> </td>'
return this;
}
});
var GistsView = Backbone.View.extend({
el: 'tbody',
collection: gists,
events: {
'click a.js-remove': function (e) {
var cid = e.currentTarget.parentElement.parentElement.id;
gists.get(cid).destroy();
gists.remove(cid);
},
'click a.js-edit': 'editRow',
'blur td[contenteditable]': 'saveRow'
},
editRow: function (e) {
var tr = e.currentTarget.parentElement.parentElement,
i = 0;
while (i < 3) {
tr.children[i].setAttribute('contenteditable', true);
i++;
}
},
saveRow: function (e) {
var tr = e.currentTarget.parentElement,
model = gists.get(tr.id);
model.set({
'description' : tr.children[0].innerText,
'url': tr.children[1].innerText,
'created_at': tr.children[2].innerText
});
model.save();
},
initialize: function () {
var self = this;
_.forEach(['reset', 'remove', 'range'], function (e) {
self.listenTo(self.collection, e, self.render);
});
},
render: function () {
var html = '';
_.forEach(this.collection.models, function (model) {
var tr = new GistRow();
html += tr.render(model).el.outerHTML;
});
this.el.innerHTML = html;
return this;
}
});
var gistsView = new GistsView();
gists.fetch({reset: true});
Afterword입문 범례 이지 만 편폭 이 제한 되 어 있 기 때문에 일부 기본 적 인 언어 특징 과 Backbone 의 기능 이 모두 갖 추어 질 수 없습니다.아직 모 르 겠 으 면 제 가 설명 할 점 을 빠 뜨 렸 을 것 입 니 다.(구 글 이후)댓 글 이나 메 일 로 알려 주세요.
Backbone 은 jQuery 플러그 인 이 아 닙 니 다.도입 후 전체 DOM 은 즉시 삭제 검 사 를 실 현 했 습 니 다.KnockoutJS/AnlarJS 처럼 DOM 에서 데이터 바 인 딩 을 하면 자동 으로 논 리 를 완성 할 수 없습니다.이것 은 일부 전단 작업 을 더욱 잘 처리 하고 규범화 시 키 는 것 이다.만약 에 전단 MVC 를 배 우 는 목적 이 쉽게 일 을 완성 하려 는 것 이 라면 Backbone 은 최선 의 선택 이 아 닐 것 이다.만약 에 하나의 항목 이 있다 면 100 여 줄 의 HTML 과 1000 여 줄 의 JS,JS 는 주로 페이지 DOM(+번 연결 HTML 이 싫 으 면 React/JSX 와 함께 쓸 수 있다)을 조작 하고 있다.그러면 Backbone 으로 다시 쓰 는 것 을 고려 할 수 있다.이것 은 다른 거대 한 MVC 프레임 워 크 보다 훨씬 쉽게 파악 할 수 있 고 입문 학습 으로 도 매우 좋다.