前端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.md缓存
下图是last-backbone这个commit时的文件结构,如今略有不一样,app下每一个文件 夹都是一个模块,每一个模块都会有assets(写html),initialize(new出各个view), routes(backbone 路由),views(backbone view), views下有templates(hbs), styles(样式)app
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>