前端MVC框架不少,angular處理DOM的方式比較特別,試用了下感受不太順手,backbone
以前學習過一次,因爲做者文檔寫的太爛,遇到各類坑放了一段時間,最近從新學習了
下,組織了下項目結構,分享一下。javascript
js使用coffee,本文由backbone 漸進到chaplin,介紹遇到的坑和學習方法。css
此文算我上篇博客現代前端開發小記的姊妹帖html
首先看backbone, 而後纔是chaplin,看官方文檔是沒有用的,須要讀源碼
本文中用到的代碼 chaplin腳手架前端
此項目能夠方便的初始化一個chaplin項目,與gh:paulmillr/brunch-with-chaplin腳手架不
同的是項目文件的組織結構java
google backbone + coffee
第一個連接是這個教程git
那就根據這個來學習backbone,具體的教程就不細說了。github
把項目克隆下來後 git checkout last-backbone
或者若是你不會用git 直接下載release中的last-backbonechrome
具體的依賴安裝方式|運行方式請參照master 分支的README.mdsegmentfault
下圖是last-backbone這個commit時的文件結構,如今略有不一樣,app下每一個文件
夾都是一個模塊,每一個模塊都會有assets(寫html),initialize(new出各個view),
routes(backbone 路由),views(backbone view), views下有templates(hbs), styles(樣式)緩存
common模塊放各類基類,和會複用到的東西
app ├── assets │ ├── images │ └── index.html ├── common │ ├── application.coffee │ ├── config.coffee │ ├── mediator.coffee │ ├── mock.coffee │ ├── models │ │ └── base │ │ ├── collection.coffee │ │ └── model.coffee │ └── views │ ├── base │ │ └── view.coffee │ └── styles │ └── application.styl ├── lib │ ├── utils.coffee │ └── view-helper.coffee └── tutorial ├── assets │ └── README.md ├── controllers │ └── README.md ├── initialize.coffee ├── models │ ├── item.coffee │ └── list.coffee ├── routes.coffee └── views ├── home │ ├── item-view.coffee │ ├── list-view.coffee │ ├── styles │ │ └── item.styl │ └── templates │ └── README.md └── README.md
backbone相關頁面
backbone和chaplin最長遇到的問題就是view中沒找到具體的DOM,
記住一條金科玉律
el container 選中的DOM必須是在new這個view前已經存在的元素
注意,取屬性值的時候須要用雙引號,由於解釋器不識別單引號 $('ul').append "<li>item #{@counter}</li>"
el必須是**pre exist**,也就是在調用前必須存在此元素 View = require 'common/views/base/view' module.exports = class ListView extends View el: '#test' initialize: -> _.bindAll @ @render() render: -> $(@el).append('<ul><li>hello backbone</li></ul>') @
注意<script>require('/tutorial/initialize');</script>
這一行須要寫在 id='test'
的元素後面,不然會找不到這個dom
<!doctype html> <!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]--> <!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]--> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title>Brunch example application</title> <meta name="viewport" content="width=device-width"> <link rel="stylesheet" href="/stylesheets/app.css"> <script src="/javascripts/vendor.js"></script> <script src="/javascripts/app.js"></script> </head> <body> <header> <h1>title</h1> <p>p p p p</p> </header> <div id="test"></div> <script>require('/tutorial/initialize');</script> </body> </html>
backbone是沒有controllers的,所以chaplin在backbone的基礎上加上了controller
以及一些緩存等等
git checkout master
或者直接下載最新的代碼
使用chaplin後有一些變化,以及用法
根據源碼
https://github.com/chaplinjs/chaplin/blob/master/src/chaplin/views/view.coffee
backbone view中的el如今爲container
constructor: @el = @container if @container
autoRender是否在constructor裏面調用一次render
constructor: @render() if @autoRender
不要在使用_bindAll會出現問題
item-view繼承自Chaplin.View,之前使用render添加dom,如今能夠直接使用
hbs模板,不過根據源碼getTemplateFunction必須重寫
* getTemplateFunction -> throw new Error 'View#getTemplateFunction must be overridden'
重寫成,能夠放在你自定義的View基類裏面
getTemplateFunction: -> @template
hbs模板使用雙括號引用model中的屬性 {{attr}}
與item-view相同,也是須要重寫getTemplateFunction
list view中的itemView指明具體的ItemView,當list view的collection中
有變化時會自動渲染dom,此例中的addItem在collection裏面調用add會處發
這個事件,注意container和listSelector的不一樣
源碼中listSelector的註釋:
# as the container of the item views. If you specify `listSelector`, the # item views will be appended to this element. If empty, $el is used. listSelector: null
例如本例子中的模板裏面有一個ul,注意listSelector是在本模板的dom中選擇,
即:
最初 <div id="test">listview會加在這裏</div> 加載listview後 <div id="test"><button ...><ul></ul></button></div> 若是listSelector爲 'div ul'會選不中這個ul的 使用ul才能夠選中 View = require 'common/views/base/view' CollectionView = require 'common/views/base/collection-view' List = require 'tutorial/models/list' Item = require 'tutorial/models/item' ItemView = require './item-view' module.exports = class ListView extends CollectionView autoRender: true container: '#test' itemView: ItemView listSelector: 'ul' template: require './templates/list' events: 'click button': 'addItem' initialize: -> @collection = new List @counter = 0 super addItem: -> @counter++ item = new Item item.set part2: "#{item.get 'part2'} #{@counter}" @collection.add item 模板list.hbs <button class="pure-button pure-button-primary">Add List Item</button> <ul></ul>