前端MVC框架很多,angular处理DOM的方式比较特别,试用了下感觉不太顺手,backbone
之前学习过一次,由于作者文档写的太烂,遇到各种坑放了一段时间,最近重新学习了
下,组织了下项目结构,分享一下。
js使用coffee,本文由backbone 渐进到chaplin,介绍遇到的坑和学习方法。
此文算我上篇博客现代前端开发小记的姊妹帖
首先看backbone, 然后才是chaplin,看官方文档是没有用的,需要读源码
本文中用到的代码 chaplin脚手架
此项目可以方便的初始化一个chaplin项目,与gh:paulmillr/brunch-with-chaplin脚手架不
同的是项目文件的组织结构
google backbone + coffee
第一个链接是这个教程
那就根据这个来学习backbone,具体的教程就不细说了。
把项目克隆下来后 git checkout last-backbone
或者如果你不会用git 直接下载release中的last-backbone
具体的依赖安装方式|运行方式请参照master 分支的README.md
下图是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
skill_issues
backbone相关页面
backbone_issue
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
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[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>