Backbone.jsã¯RIA JavaScriptã¢ããªã±ãŒã·ã§ã³ãäœæããããã®ãã¬ãŒã ã¯ãŒã¯ã§ããããã®äœæè ã¯CoffeeScriptã®äœæè ã§ããJeremy Ashkenasã§ãããBackboneã¯Document Cloudã®äžéšã§ãããUnderscrore.jsã«ãã£ãŠãææããããŠããŸãã ããã¯ããŒã³ã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã®äœæã«åœ¹ç«ã€éåžžã«è»œéãªã©ã€ãã©ãªã§ãã ããã¯ããªããæ £ã芪ããã§ããã©ã€ãã©ãªã§åäœããŸãã
Backboneã¯ããµã€ãºã4Kbæªæºã®ã¯ã©ã¹ã®ã»ããã§ãããã³ãŒãã®æ§é ã圢æããé«å質ã®MVC Webã¢ããªã±ãŒã·ã§ã³ã®äœæãæ¯æŽããŸããBackboneã¯ãããŒãšå€ã®ãããªã¹ãã¬ãŒãžãšç¬èªã®ã€ãã³ããåããã¢ãã«ãè±å¯ãªAPIãåããã³ã¬ã¯ã·ã§ã³ã宣èšçãªã€ãã³ãåŠçãåãããã¥ãŒïŒå ã®ãã¥ãŒïŒãå°å ¥ããããšã«ãããéãJavaScriptã¢ããªã±ãŒã·ã§ã³ã®æ§é ã圢æããããããã¹ãŠãRESTful JSONã€ã³ã¿ãŒãã§ã€ã¹ããµããŒããã1ââã€ã®ã¢ããªã±ãŒã·ã§ã³ã«çµåããŸãã
Backboneã¯Underscore.jsãªãã§ã¯æ©èœããŸããã REST APIããµããŒããã Backbone.Viewã§DOMèŠçŽ ãæäœããã«ã¯ã json2.jsãšjQueryã®ãããªã©ã€ãã©ãªjQueryãŸãã¯Zeptoãæ¥ç¶ããããšã匷ããå§ãããŸãã
ãã®èšäºã§ã¯Backbone.jsã®æ§é ã調ã¹ãç°¡åãªTodoã¢ããªã±ãŒã·ã§ã³ã段éçã«äœæããŸãã
BackboneãæäŸããã¬ãã¬ããžã以äžã«ç€ºããŸãã
Key-Valueã¹ãã¬ãŒãžãšã«ã¹ã¿ã ã€ãã³ã
ã¢ãã«ã®ã³ã³ãã³ããå€æŽããããšãã¢ãã«ã®å€æŽã«ãµãã¹ã¯ã©ã€ãããããã¹ãŠã®ãªããžã§ã¯ããéç¥ãåãåããããã«ã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãã ããšãã°ããã¥ãŒïŒå ã®ãã¥ãŒïŒã¯ã¢ãã«ã®å€æŽããªãã¹ã³ããã¢ãã«ããã¥ãŒã®ç¶æ ãå€æŽãã代ããã«ç¶æ ãæŽæ°ããŸãã ççµåãã¿ãŒã³ã䜿çšãããŸãã
åæé¢æ°ã®è±å¯ãªAPI
Backboneã«ã¯ãããŒã¿ãåŠçããããã®éåžžã«äŸ¿å©ãªæ©èœãå€æ°ä»å±ããŠããŸãã ä»ã®èšèªãšã¯ç°ãªããJavaScriptã®é åã¯ãæªå®æãã§ããã倧éã®ããŒã¿ãåŠçããå Žåã¯å€§ããªåé¡ã«ãªããŸãã
宣èšçãªã€ãã³ããã¥ãŒ
ã¹ãã²ããã£ã®ãããªã³ãŒããæžããæ¥ã ã¯çµããã«è¿ã¥ããŠããŸãã ã©ã®ã³ãŒã«ããã¯ãã©ã®ãªããžã§ã¯ãã«é¢é£ä»ããããŠããããããã°ã©ã ã§æ±ºå®ã§ããŸãã
RESTful JSONã€ã³ã¿ãŒãã§ãŒã¹
ãµãŒããŒãšéä¿¡ããå¿ èŠãããå Žåã¯ãã衚瀺ãã³ãŒãã§AJAXãªã¯ãšã¹ããå®è¡ããå¿ èŠãªãã®ãååŸããå¿ èŠããããŸãã ããã¯ãã¹ãŠãããŸããŸãªxhrã¢ããã¿ãŒãWebSocketsãããã³localStorageã䜿çšããŠéšåçã«åçŽåãããŠããŸãããããåçŽã«ããããšãã§ããŸãã ãã®ãããªãšã³ãã£ãã£ã¯ããã€ãã®å°ããªãšã³ãã£ãã£ã«åå²ããå¿ èŠããããŸããBackboneã¯ãããæ¯æŽããŸãã
Backboneã¯ããã¬ãŒã³ããŒã·ã§ã³ããããŒã¿ãåé¢ããæ©èœãæäŸããŸãã ããŒã¿ãåŠçãããµãŒããŒãšåæãããã¥ãŒãã¢ãã«ã®å€æŽããªãã¹ã³ããŠãã®ç¶æ ãå€æŽããïŒããŒã¿ãHTMLã§æç»ããïŒã¢ãã«çŸåšçºçããå¯èœæ§ã®ãã質åã«å¯Ÿããåçãããã«ãªã¹ãããŸãã
jQueryã眮ãæããŸããïŒ
ãã ç®æšã¯å€§ããç°ãªããŸãã Backboneã¯é«ã¬ãã«ã®æœè±¡åã§åäœããŸãããjQueryãŸãã¯åæ§ã®ã©ã€ãã©ãªã¯DOMã§åäœããã€ãã³ããæ£èŠåããŸãã
ç°ãªãã¢ããªã±ãŒã·ã§ã³ããããŸããããã©ã€ãã©ãªãç¥ã£ãŠããã°ãå¥ã®ã©ã€ãã©ãªãç¥ãå¿ èŠããããšããæå³ã§ã¯ãããŸããã ãã ããJavaScriptéçºè ã¯ãäž¡æ¹ãå¹æçã«äœ¿çšããæ¹æ³ãç¥ãå¿ èŠããããŸãã
ãªãç§ã¯åœŒå¥³ã䜿ãã¹ãã§ããïŒ
ã»ãšãã©ã®å Žåãã€ã³ã¿ãŒãã§ã€ã¹ã³ãŒãã¯ããã¹ããããã³ãŒã«ããã¯ãDOMæäœãHTMLãã³ãã¬ãŒãããŸãã¯ããŒã¿ãè¡šãHTMLãçæããé¢æ°ã®ããŒãã£ã»ããã§ãã Backboneã¯ããã®ã«ãªã¹ãå¶åŸ¡ããåªããããŒã«ãæäŸããŸãã
ã©ãã§äœ¿çšããã°ããã§ããïŒ
ããã¯ããŒã³ã¯ãé äžãªã€ã³ã¿ãŒãã§ã€ã¹ãšããŒã¿é§ååã¢ããªã±ãŒã·ã§ã³ã®æ§ç¯ã«æé©ã§ãã ããšãã°ãGMailã€ã³ã¿ãŒãã§ãŒã¹ãæ°ããTwitterãŸãã¯ãã®ä»ã®é¢é£ã¢ããªã±ãŒã·ã§ã³ã Backboneã䜿çšãããšãè€éãªã¢ããªã±ãŒã·ã§ã³ãç°¡åã«äœæã§ããŸãã
ããã䜿çšãããšãJavaScriptãè±å¯ãªã·ã³ãã«ãªhtmlããŒãžãäœæã§ããŸãããæŠããŠãBackboneã¯Webã¢ããªã±ãŒã·ã§ã³ãäœæããããã«èšèšãããŠããŸãã
ã«ãããŒããã¹ãã©ãŠãã³ã¢ã®ããã«èŠããŸããïŒ
ã¯ãããããã ã¯ããåè¿°ã®ãã¬ãŒã ã¯ãŒã¯ãšåæ§ãäž»ãªç®æšã¯Webã¢ããªã±ãŒã·ã§ã³çšã®è€éãªã€ã³ã¿ãŒãã§ã€ã¹ãäœæããããšã§ãã ãããã¯ãããã¯ããŒã³ãéåžžã«è»œããšããç¹ã§ç°ãªããåè¿°ã®ã©ã€ãã©ãªã®ã©ãããããšæ¯èŒã§ããŸããã
ããã¯ããŒã³ã¯éåžžã«è»œéã§ã4kbæªæºã§ããå®éãçŽ4 kbã¯ããã«åœãŠã¯ãŸããŸãããBackbone4 kb + Underscore.js 3 kb + jQuery 31 KB = 38 KB
Cappuccinoã§ã¯ãObjective-Jã§ã³ãŒããèšè¿°ããå¿ èŠããããŸãããSproutcoreãã¥ãŒã¯JavaScriptã³ãŒãã§å®£èšããå¿ èŠããããŸãã ãããããããã®ã¢ãããŒãã®ãããããééã£ãŠãããšã¯èšããŸããããBackboneã䜿çšãããšãéåžžã®JavaScriptãèšè¿°ããéåžžã®HTMLãšCSSã䜿çšããŸãã
Backboneã§ä»ã®ã©ã€ãã©ãªã䜿çšã§ããŸããïŒ
ãã¡ããã DOMãAJAXã©ãããŒã ãã§ãªãããã³ãã¬ãŒããšã¹ã¯ãªããããŒããŒã«ãã¢ã¯ã»ã¹ã§ããŸãã Backboneã¯éåžžã«ççµåã§ããããã¯ãBackboneãšçµã¿åãããŠã»ãšãã©ãã¹ãŠã®ããŒã«ã䜿çšã§ããããšãæå³ããŸãã
ããã¯ããŒã³ã®æ§ç¯
æåãBackboneã¯ã¢ãã«ããã¥ãŒãããã³ã³ã¬ã¯ã·ã§ã³ã®ã¿ã§æ§æãããŠããŸãããã³ã³ãããŒã©ãŒã¯å«ãŸããŠããŸããã§ããã æéãçµã€ã«ã€ããŠãã³ã³ãããŒã©ãŒãè¿œå ãããŸããã ããã¯ããŒã³ã¯çŸåšã4ã€ã®äž»èŠãªã¯ã©ã¹ã§æ§æãããŠããŸãã
- ã¢ãã«
- ã³ã¬ã¯ã·ã§ã³
- 衚瀺ãã
- ã³ã³ãããŒã©ãŒ
ã¢ãã«
ç°ãªããã®ã¯ãç°ãªãMVCãã¬ãŒã ã¯ãŒã¯ã®ã¢ãã«ãšåŒã°ããŸãã Backboneã§ã¯ãã¢ãã«ã¯åå¥ã®ãšã³ãã£ãã£ãšåŒã°ããæãè¿ãé¡äŒŒç©ã¯ããŒã¿ããŒã¹å ã®ã¬ã³ãŒãã§ãã ããããå³æ Œãªã«ãŒã«ã¯ãããŸããã ãã¬ãŒã ã¯ãŒã¯Webãµã€ãããïŒ
ã¢ãã«ã¯ãã€ã³ã¿ã©ã¯ãã£ããªããŒã¿ãšãããããæ§æããã»ãšãã©ã®ããžãã¯ïŒå€æãæ€èšŒãèšç®ãããããããã£ãã¢ã¯ã»ã¹æš©ïŒãå«ããã¹ãŠã®JavaScriptã¢ããªã±ãŒã·ã§ã³ã®äžå¿ã§ããã¢ãã«ã¯ãããŒã¿ã»ããã®ããããã£ãŸãã¯å±æ§ãèªã¿æžãããæ¹æ³ã§ãã ã¢ãã«ã®äŸã次ã«ç€ºããŸãã
var Game = Backbone.Model.extend({});
å°ãè€éã«ããŸãããïŒ
var Game = Backbone.Model.extend({ initialize: function(){ alert("Oh hey! "); }, defaults: { name: 'Default title', releaseDate: 2011, } });
ãªããžã§ã¯ããäœæããããšãinitializeã¡ãœãããå®è¡ãããŸãã ãã®æ¹æ³ã§ã¯ãæçšãªããšã¯äœãããŠããŸããã äžéšã®ããŒã¿ã転éãããªãå Žåã«åããŠãããã€ãã®ããã©ã«ãå€æ°ãå®çŸ©ããŸãã
å±æ§ãèªã¿æžãããæ¹æ³ãèŠãŠã¿ãŸãããã ãã ããæåã«ãªããžã§ã¯ããäœæããŸãã
// var portal = new Game({ name: "Portal 2", releaseDate: 2011}); // releaseDate var release = portal.get('releaseDate'); // 2011 // portal.set({ name: "Portal 2 by Valve"});
å±æ§ïŒobject.attributeïŒãçŽæ¥æäœããããšã¯ã§ããŸãããããŒã¿ãå€æŽãŸãã¯ååŸããã«ã¯ã¡ãœãããåŒã³åºãå¿ èŠããããŸãïŒç¶æ³ã¯Proxyã®åºçŸã«ããå€ãããšæããŸãïŒã
ããã§ããã¹ãŠã®ããŒã¿ãã¢ããªã±ãŒã·ã§ã³ã¡ã¢ãªã«æ ŒçŽãããŸããã ãããããµãŒããŒã«ä¿åããŸãããïŒ
portal.save();
ãã£ãšæåŸ ããïŒ AJAXïŒ 1è¡ã§ããµãŒããŒã«ãªã¯ãšã¹ããéä¿¡ããŸãã ãªã¯ãšã¹ãã®ã¿ã€ããå€ããããšã«æ³šæããŠãã ãããæ°ãããªããžã§ã¯ããäœæãããšãPOSTãªã¯ãšã¹ããéä¿¡ãããããã§ãªãå Žåã¯PUTãéä¿¡ãããŸãã
ã¢ãã«ã«ã€ããŠç°¡åã«è§ŠããŸããã Backboneã¯ãã¢ãã«ãæäœããããã®éåžžã«å€ãã®ãªãã·ã§ã³ãæäŸããŸãã 詳现ã¯ããã¥ã¡ã³ãã«èšèŒãããŠããŸãã
ã³ã¬ã¯ã·ã§ã³
Backboneã®ã³ã¬ã¯ã·ã§ã³ã¯ãåãªãã¢ãã«ã®ã³ã¬ã¯ã·ã§ã³ã§ãã ã³ã¬ã¯ã·ã§ã³ããŒã¿ããŒã¹ãšåæ§ã«ããããã¯æååïŒã¢ãã«ïŒãå«ãããŒã¿ããŒã¹ã¯ãšãªã®çµæã§ãã
ã²ãŒã ã®ã³ã¬ã¯ã·ã§ã³ãäœæããŸãããïŒ
var GamesCollection = Backbone.Collection.extend({ model : Game });
æåã«æ°ã¥ãã®ã¯ãã³ã¬ã¯ã·ã§ã³ãã©ã®ã¢ãã«ã§æ§æãããŠããããå€æããããšã§ãã ã²ãŒã ã¢ãã«ã§æ§æãããã²ãŒã ã®ã³ã¬ã¯ã·ã§ã³ãäœæããŸããã
ããã§ãããŒã¿ãæäœã§ããŸãã ããšãã°ãå€ãã²ãŒã ãå®çŸ©ããã¡ãœãããè¿œå ããŠãã³ã¬ã¯ã·ã§ã³ãæ¡åŒµããŸãããã
var GamesCollection = Backbone.Collection.extend({ model : Game, old : function() { return this.filter(function(game) { return game.get('releaseDate') < 2009; }); } });
ã·ã³ãã«ã§ããïŒ 2009幎以åã«äœæããããããã®ã²ãŒã ããã§ãã¯ããããããè¿ããŸãã ã³ã¬ã¯ã·ã§ã³ãçŽæ¥ç®¡çããããšãã§ããŸãã
var games = new GamesCollection games.get(0);
äžèšã®äŸã¯ãæ°ããã³ã¬ã¯ã·ã§ã³ãäœæããID 0ã®ã¢ãã«ãååŸããŸãããªããžã§ã¯ãã®äœçœ®ãžã®ãªã³ã¯ãä»ããŠãç¹å®ã®äœçœ®ã®èŠçŽ ãèŠã€ããããšãã§ããŸã
games.at(0);
æåŸã«ã次ã®ããã«ã³ã¬ã¯ã·ã§ã³ãåçã«è£å ã§ããŸãã
var GamesCollection = Backbone.Collection.extend({ model : Game, url: '/games' }); var games = new GamesCollection games.fetch();
ããŒã¿ã管çããURLã®å©ããåããŠBackboneã«éç¥ããŸãã 次ã«ãåçŽã«æ°ãããªããžã§ã¯ããäœæãã
fetch
ã¡ãœãããåŒã³åºããŸããããã«ããããµãŒããŒããã®ããŒã¿ã®éåæèŠæ±ãçºçããã³ã¬ã¯ã·ã§ã³ã«å€ãèšå®ãããŸãã
ããã§ãBackboneã³ã¬ã¯ã·ã§ã³ã®åºæ¬ãããããŸããã äžã§è¿°ã¹ãããã«ãããšãã°ãUnderscoreã©ã€ãã©ãªã®ãã¹ãŠã®ã¡ãœãããªã©ãBackboneã§ã§ãã䟿å©ãªæ©èœããŸã ãããããããŸãã å®éšããåã«ããã¥ã¡ã³ããèªãã§ãã ããã
衚瀺ãã
äžèŠãããšããã¥ãŒã¯æ··ä¹±ããŠããããã«èŠãããããããŸããã çŽç²ãªMVCãšã¯ç°ãªããBackboneã®ãã¥ãŒã«ã¯ã³ã³ãããŒã©ãŒæ©èœã®äžéšããããŸãã
çš®ã®è²¬ä»»ã¯æ¬¡ã®ãšããã§ãã
- DOMã€ãã³ããã¢ãã«ãã³ã¬ã¯ã·ã§ã³ãèŽããŸãã
- ã¢ããªã±ãŒã·ã§ã³ã®ç¶æ ã®è¡šçŸïŒãã¥ãŒã®ã¬ã³ããªã³ã°ïŒã
var GameView = Backbone.View.extend({ tagName: "div", className: "game", render: function() { // } });
ãã¹ãŠãéåžžã«ç°¡åã§ãã ãã¥ãŒïŒtagNameãšclassNameïŒã®ã©ããã«äœ¿çšããHTMLèŠçŽ ã決å®ããã ãã§ãã
次ã®ã³ãŒãã¯ãã¥ãŒãã¬ã³ããªã³ã°ããŸãã
render : function() { this.el.innerHTML = this.model.get('name'); // jQuery: $(this.el).html(this.model.get('name')); }
elã¯ããã®ãã¥ãŒãè¡šãDOMèŠçŽ ãæããŸãã åã«HTMLèŠçŽ ã«ã²ãŒã ã®ååãå ¥ããŸãã æããã«ãjQueryã®äœ¿çšã¯ããå°ãç°¡åã§ãã
ããè€éãªããŒã¯ã¢ããã§ã¯ãJavaScriptå ã§HTMLã³ãŒãã䜿çšããã®ã¯é¢åã§ç¡æå³ã§ãã ãããã®å Žåããã¿ãŒã³ã䜿çšãã䟡å€ããããŸãã
Backboneã«ã¯ç¬èªã®ãã³ãã¬ãŒããšã³ãžã³ïŒUnderscore.JSã®äžéšïŒããããŸãããä»»æã®çš®é¡ã®ãã³ãã¬ãŒããèªç±ã«äœ¿çšã§ããŸãã
æåŸã«ãçš®ãã€ãã³ãããªãã¹ã³ããæ¹æ³ãèŠãŠã¿ãŸãããã æåã®DOMã€ãã³ãã
events: { 'click .name': 'handleClick' }, handleClick: function(){ alert('In the name of science... you monster'); // Other actions as necessary }
ãã¡ãããjQueryã»ã©éŠŽæã¿ããªããã·ã³ãã«ã§ããããŸãã Eventsãªããžã§ã¯ããä»ããŠãªãã¹ã³ããã€ãã³ãã決å®ããŸãã äžèšã®ã³ãŒããããããããã«ãæåã®éšåã¯ã€ãã³ããåç §ãã次ã®éšåã¯ã€ãã³ãã«é¢é£ä»ããããŠããé¢æ°ãå®çŸ©ããŸãã
次ã«ããã¥ãŒãã¢ãã«ã«æ¥ç¶ããŸãã
var GameView = Backbone.View.extend({ initialize: function (args) { _.bindAll(this, 'changeName'); this.model.bind('change:name', this.changeName); } });
æåã«æ³šæããããšã¯ããã€ã³ãã£ã³ã°ã³ãŒããåæåé¢æ°ã«é 眮ããæ¹æ³ã§ãã åæåã¯ã€ãã³ãããã€ã³ãããã®ã«æé©ãªå Žæã ãšæããŸãã
bindAll
ã¯ããã®ã³ã³ããã¹ããé¢æ°ã«ãã€ã³ãããã¢ã³ââããŒã¹ã³ã¢ã¡ãœããã§ãã ããã¯ãã€ãã³ãã§ç¹ã«åœ¹ç«ã¡ãŸãã
ããã§ãã¢ãã«åãå€æŽããããšããã«ãchangeNameé¢æ°ã
changeName
ãŸãã
change:
代ããã«ä»ã®ãã¬ãã£ãã¯ã¹ã䜿çšããŠãã¢ãã«ã®ç¶æ ãç §äŒã§ããŸãã
ã³ã³ãããŒã©ãŒ
ã³ã³ãããŒã©ãŒã䜿çšãããšãããã·ã¥URLïŒhashbangsïŒã®ç¶æ ãèšæ¶ããã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸãã
var Hashbangs = Backbone.Controller.extend({ routes: { "!/": "root", "!/games": "games", }, root: function() { // }, games: function() { // } });
ããã¯ãåŸæ¥ã®ãµãŒããŒMVCãã¬ãŒã ã¯ãŒã¯ã®ã«ãŒãã«éåžžã«äŒŒãŠããŸãã ããšãã°
!/games
ã¯é¢æ°ã«é¢é£ä»ãããããã©ãŠã¶ã®URLã¯
domain/#!/games
ãŸãã
hashbangsã䜿çšãããš ããã®ç¶æ ãèšæ¶ããGoogleãã€ã³ããã¯ã¹ãäœæã§ããWebã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸãã
ããã«ãã[æ»ã]ãã¿ã³ãå£ããã®ã§ã¯ãªãããšå¿é ããŠããå Žåã¯ãBackboneãåŠçããŸãã
// var ApplicationController = new Controller; Backbone.history.start();
ããã¯ããŒã³ã¯
#hash
ã®å€æŽãç£èŠããã³ã³ãããŒã©ãŒã«éç¥ããŸãã
Backboneã®åºæ¬ãç解ããã®ã§ããã¹ãã¢ããªã±ãŒã·ã§ã³ãäœæããŠã¿ãŸãããã
äŸïŒTodoãªã¹ã
ãã®ã¢ããªã¯JérÃŽmeGravel-Niquetã«ãã£ãŠäœæãããŸãã ã åçŽãªlocalStorageã¢ããã¿ãŒã䜿çšããŠããã©ãŠã¶ãŒã«ããŒã¿ãä¿åããŸãïŒã¢ããã¿ãŒã§åæ¢ããã®ã§ã¯ãªããã³ãŒããèŠãŠãã ããããã¹ãŠãéåžžã«åçŽã§ãïŒã ã³ãŒãã®ç解ãæ·±ããããã«æåŸã«äœãèµ·ããããèŠãŠãã ããïŒ Todo List
Tuduã¢ãã«
åºæ¬ã¢ãã«ã¯ã
content
ã
order
ããã³
done
å±æ§ãæã€ãªã¹ãtodoèŠçŽ ãèšè¿°ããŸãã
window.Todo = Backbone.Model.extend({ // , // , default EMPTY: "empty todo...", // `content`, initialize: function() { if (!this.get("content")) { this.set({"content": this.EMPTY}); } }, // `done` toggle: function() { this.save({done: !this.get("done")}); }, // localStorage clear: function() { this.destroy(); this.view.remove(); } });
ããã¥ãŒã³ã¬ã¯ã·ã§ã³
tuduã³ã¬ã¯ã·ã§ã³ã¯localStorageã«ä¿åãããŸã
window.TodoList = Backbone.Collection.extend({ // Todo model: Todo, // "todos" localStorage localStorage: new Store("todos"), // , done: function() { return this.filter(function(todo){ return todo.get('done'); }); }, // , remaining: function() { return this.without.apply(this, this.done()); }, // , . // GUID . . nextOrder: function() { if (!this.length) return 1; return this.last().get('order') + 1; }, // comparator: function(todo) { return todo.get('order'); } }); // window.Todos = new TodoList;
ãã¥ãŒ-ãã¥ãã¥èŠçŽ
// DOM window.TodoView = Backbone.View.extend({ // tagName: "li", // // template: _.template($('#item-template').html()), // DOM, events: { "click .check" : "toggleDone", "dblclick div.todo-content" : "edit", "click span.todo-destroy" : "clear", "keypress .todo-input" : "updateOnEnter" }, // TodoView . // ---, // . initialize: function() { _.bindAll(this, 'render', 'close'); this.model.bind('change', this.render); this.model.view = this; }, // render: function() { $(this.el).html(this.template(this.model.toJSON())); this.setContent(); return this; }, // XSS `jQuery.text` setContent: function() { var content = this.model.get('content'); this.$('.todo-content').text(content); this.input = this.$('.todo-input'); this.input.bind('blur', this.close); this.input.val(content); }, // "done" toggleDone: function() { this.model.toggle(); }, // edit: function() { $(this.el).addClass("editing"); this.input.focus(); }, // , close: function() { this.model.save({content: this.input.val()}); $(this.el).removeClass("editing"); }, // `enter`, updateOnEnter: function(e) { if (e.keyCode == 13) this.close(); }, // DOM remove: function() { $(this.el).remove(); }, // clear: function() { this.model.clear(); } });
ãã¥ãŒ-ã¢ããªã±ãŒã·ã§ã³
ãããã¢ããªã±ãŒã·ã§ã³ã®åºæ¬çãªãã¥ãŒã§ãã
window.AppView = Backbone.View.extend({ // , HTML el: $("#todoapp"), // // statsTemplate: _.template($('#stats-template').html()), // , events: { "keypress #new-todo": "createOnEnter", "keyup #new-todo": "showTooltip", "click .todo-clear a": "clearCompleted" }, // : // , , . , // localStorage initialize: function() { _.bindAll(this, 'addOne', 'addAll', 'render'); this.input = this.$("#new-todo"); Todos.bind('add', this.addOne); Todos.bind('refresh', this.addAll); Todos.bind('all', this.render); Todos.fetch(); }, // - . . render: function() { var done = Todos.done().length; this.$('#todo-stats').html(this.statsTemplate({ total: Todos.length, done: Todos.done().length, remaining: Todos.remaining().length })); }, // . `<ul>` addOne: function(todo) { var view = new TodoView({model: todo}); this.$("#todo-list").append(view.render().el); }, // addAll: function() { Todos.each(this.addOne); }, // newAttributes: function() { return { content: this.input.val(), order: Todos.nextOrder(), done: false }; }, // return - . // createOnEnter: function(e) { if (e.keyCode != 13) return; Todos.create(this.newAttributes()); this.input.val(''); }, // , . clearCompleted: function() { _.each(Todos.done(), function(todo){ todo.clear(); }); return false; }, // . showTooltip: function(e) { var tooltip = this.$(".ui-tooltip-top"); var val = this.input.val(); tooltip.fadeOut(); if (this.tooltipTimeout) clearTimeout(this.tooltipTimeout); if (val == '' || val == this.input.attr('placeholder')) return; var show = function(){ tooltip.show().fadeIn(); }; this.tooltipTimeout = _.delay(show, 1000); } }); // - window.App = new AppView;
泚éä»ãã®ãªãªãžãã«ã¯ããã§è¡šç€ºã§ããŸãã
HTMLãã³ãã¬ãŒããšCSS
<!-- --> <div id="todoapp"> <div class="title"> <h1>Todos</h1> </div> <div class="content"> <div id="create-todo"> <input id="new-todo" placeholder="What needs to be done?" type="text" /> <span class="ui-tooltip-top" style="display:none;">Press Enter to save this task</span> </div> <div id="todos"> <ul id="todo-list"></ul> </div> <div id="todo-stats"></div> </div> </div> <!-- --> <script type="text/template" id="item-template"> <div class="todo <%= done ? 'done' : '' %>"> <div class="display"> <input class="check" type="checkbox" <%= done ? 'checked="checked"' : '' %> /> <div class="todo-content"></div> <span class="todo-destroy"></span> </div> <div class="edit"> <input class="todo-input" type="text" value="" /> </div> </div> </script> <!-- --> <script type="text/template" id="stats-template"> <% if (total) { %> <span class="todo-count"> <span class="number"><%= remaining %></span> <span class="word"><%= remaining == 1 ? 'item' : 'items' %></span> left. </span> <% } %> <% if (done) { %> <span class="todo-clear"> <a href="#"> Clear <span class="number-done"><%= done %></span> completed <span class="word-done"><%= done == 1 ? 'item' : 'items' %></span> </a> </span> <% } %> </script>
CSSã¯é©çšããŸããã éåžžã«é·ã ãå®å šã«ãããã¯ããå€ããŠããŸãã
ããã§ãã¹ãã¢ããªã±ãŒã·ã§ã³ã®æºåãæŽããŸãã ãçµæã¯ãã¡ãã§ç¢ºèªã§ããŸã ã
ããã¯ããŒã³ããåŠã¹ãããš
Backboneã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ããåŠã¹ãããã€ãã®ã¬ãã¹ã³ã次ã«ç€ºããŸãã
- ã€ã³ã¿ãŒãã§ãŒã¹ã«ã¯MVCãæ¬åœã«å¿ èŠã§ãã åŸæ¥ã®ã¡ãœããã¯ãããèªäœã«éåžžã«åŒ·ãçµã³ä»ããããã³ãŒããäœæããŸããããã¯æ±ããç¶æããã®ãå°é£ã§ãã
- DOMã«ããŒã¿ãšç¶æ ãä¿æããã®ã¯æªãèãã§ãã ããã¯ãã¢ããªã±ãŒã·ã§ã³ã®ããŸããŸãªéšåãåãããŒã¿ã䜿çšããŠæŽæ°ããå¿ èŠãããã¢ããªã±ãŒã·ã§ã³ãäœæããŠããå Žåã«ç¹ã«æ·±å»ã§ãã
- åãã¢ãã«ãšèãã³ã³ãããŒã©ãŒãé©ããŠããŸãã ããžãã¹ããžãã¯ãã¢ãã«ã«ãã£ãŠé§åãããå Žåãéçºããã»ã¹ã¯å€§å¹ ã«ç°¡çŽ åãããŸãã
- ãã³ãã¬ãŒãã¯éåžžã«éèŠã§ãã JavaScriptã«HTMLãè¿œå ãããšãæªãã«ã«ããçºçããŸãã
æžã蟌ã¿æã«äœ¿çšããããœãŒã¹
Backbone.jsã䜿çšããŠJavaScriptã¢ããªãäœæãã ïŒJim HoskinsïŒ
Backbone.jsã®éå§æ¹æ³ ïŒSiddharthïŒ
ã¢ããã¿ãŒã®ããã¯ããŒã³äœçœ®ã¹ãã¬ãŒãž
Todosã®äŸ ïŒJérÃŽmeGravel NiquetïŒ
泚éä»ãã®Todos.jsãœãŒã¹
ä»ã«èªããã®
GitHub ããã¯ããŒã³ããã¥ã¡ã³ã
GitHubã®ã¢ã³ããŒã¹ã³ã¢ããã¥ã¡ã³ã
ããŒããã¥ãŒããªã¢ã«ããŒã19ïŒBackbone.js ïŒAlex YoungïŒ
倧èŠæš¡ãªJavaScriptã¢ããªã±ãŒã·ã§ã³ã®äœæ ïŒãªãªãžãã«ã®Addy Osmaniã翻蚳trurl123 ïŒ