yoeman 简介:http://www.infoq.com/cn/news/2012/09/yeoman
yeoman 官网: http://yeoman.io/
yeoman 是快速创建骨架应用程序的WEB前端工具,实际由 yo, grunt, bower 三个组建而成。
-
Yo scaffolds out a new application, writing your Grunt configuration and pulling in relevant Grunt tasks that you might need for your build.
-
Grunt is used to build, preview and test your project, thanks to help from tasks curated by the Yeoman team and grunt-contrib.
-
Bower is used for dependency management, so that you no longer have to manually download and manage your scripts.
简单来说就是 Yo 是配置 Grunt 的 task 的工具,Grunt 是一个部署、预览和测试前端项目的工具,而 Bower 是一个包的管理工具,可以下载 jquery, backbone 等库。
PS: 要运行 yeoman 首先需要配置环境,配置好 node.js 、git 环境。
下面开始写一个 todo-list demo 作为例子
一、首先安装 yo,这会自动安装 grunt, bower
npm install -g yo
npm install -g generator-webapp
PS: yo 是命令开头,webapp 是 另外一个参数. yo 可以生成其他各种应用配置。如 backbone, angularjs等,前提首先安装 generator-backbone,即
yo webapp
此时可以看到
webapp 默认带有 Sass 版的 bootstrap库,等到下载完毕后可以看到以下文件:
app 为项目主目录,是部署的根目录
node_modules 为 nodejs的包文件
test 为测试目录,专门用于单元测试,用的是 mocha 来测试
Gruntfile.js 是配置 grunt 自动化任务的配置文件,具体配置可以参考下 Grunt官网
二、添加JS库,这里添加 backbone,bower 会自动下载 underscore.
bower install backbone
三、运行
grunt server
它将运行应用,并监控文件的变化,一旦有改变,就会自动刷新浏览器。
文件又这几个,用的是
- HTML5 Boilerplate 模板(默认)
- RequireJS (可选)
四、开始写应用
index.html
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <!doctype html> 2 <!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> 3 <!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]--> 4 <!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]--> 5 <!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]--> 6 <head> 7 <meta charset="utf-8"> 8 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 9 <title></title> 10 <meta name="description" content=""> 11 <meta name="viewport" content="width=device-width"> 12 <!-- Place favicon.ico and apple-touch-icon.png in the root directory --> 13 <!-- build:css(.tmp) styles/main.css --> 14 <link rel="stylesheet" href="styles/bootstrap-2.3.2.min.css"> 15 <link rel="stylesheet" href="styles/main.css"> 16 <!-- endbuild --> 17 <!-- build:js scripts/vendor/modernizr.js --> 18 <script src="bower_components/modernizr/modernizr.js"></script> 19 <!-- endbuild --> 20 </head> 21 <body> 22 <div class="container"> 23 <div class="todo-container"> 24 <div class="header"> 25 <h2>Todo List</h2> 26 <div class="todo-input"> 27 <div class="controls"> 28 <input type="text" placeholder="Enter to save" class="todo-input-text" autofocus> 29 </div> 30 </div> 31 </div> 32 <div class="content"> 33 <div class="todo-item-list todo-undone-list clearfix"> 34 <p>Things to do:</p> 35 </div> 36 <div class="todo-item-list todo-done-list clearfix"> 37 <p>Done Things:</p> 38 </div> 39 </div> 40 <div class="footer"> 41 </div> 42 </div> 43 </div> 44 45 <script type="text/template" id="todo-input-template"> 46 </script> 47 <script type="text/template" id="todo-item-template"> 48 <span class="order"><%= order%></span> 49 <a href="javascript:void(0);" class="done-<%= done%>"> 50 <b><%= title%></b> 51 <button title="删除" class="btn btn-mini pull-right todo-item-remove"><i class="icon-remove"></i></button> 52 <% if (done) { %> 53 <button title="撤销" class="btn btn-mini pull-right todo-item-undone"><i class="icon-repeat"></i></button> 54 <% } else { %> 55 <button title="完成" class="btn btn-mini pull-right todo-item-done"><i class="icon-ok"></i></button> 56 <% } %> 57 </a> 58 </script> 59 <!--[if lt IE 7]> 60 <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> 61 <![endif]--> 62 63 <!-- build:js scripts/main.js --> 64 <script data-main="scripts/main" src="bower_components/requirejs/require.js"></script> 65 <!-- endbuild --> 66 </body> 67 </html>
main.coffee
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 require.config 2 baseUrl : './scripts/' 3 shim : 4 underscore : 5 exports : '_' 6 backbone : 7 deps : [ 8 'underscore' 9 'jquery' 10 ] 11 exports : 'Backbone' 12 backboneLocalStorage : 13 deps : [ 14 'backbone' 15 ] 16 app : 17 deps : [ 18 'underscore' 19 'jquery' 20 'backbone' 21 ] 22 23 paths : 24 jquery : '../bower_components/jquery/jquery' 25 underscore : '../bower_components/underscore/underscore' 26 backbone : '../bower_components/backbone/backbone' 27 backboneLocalStorage: '../bower_components/backbone/examples/backbone.localStorage' 28 29 require ['app'], (app) -> 30 app.init()
app.coffee
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 define 'app', ['jquery', 'underscore', 'backbone', 'backboneLocalStorage'], ($, _, Backbone) -> 2 3 TodoModel = Backbone.Model.extend 4 defaults : () -> 5 title : 'Untitle', 6 done : false, 7 order : Todos.length+1 8 9 initialize : () -> 10 this.save() 11 12 13 TodoList = Backbone.Collection.extend 14 model : TodoModel 15 localStorage : new Backbone.LocalStorage 'todos-backbone' 16 done : () -> 17 this.where done : true 18 19 Todos = new TodoList # todo 集合 20 21 TodoView = Backbone.View.extend 22 tagName : 'div' # 外容器 23 template : _.template $('#todo-item-template').html() # 模板HTML 24 25 # 初始化,坚听对象 26 initialize : () -> 27 this.listenTo this.model, 'change', this.render 28 this.listenTo this.model, 'destroy', this.remove 29 30 # 事件绑定 31 events : 32 'click button.todo-item-done' : 'done' 33 'click button.todo-item-remove' : 'clear' 34 'click button.todo-item-undone' : 'undone' 35 36 done : () -> 37 if this.model.get('done') == false # 本身是未完成状态的 38 this.model.set done : true 39 this.remove() 40 41 undone : () -> 42 if this.model.get('done') == true # 本身是完成状态的 43 this.model.set done : false 44 this.remove() 45 46 clear : () -> 47 this.model.destroy() 48 49 render : () -> 50 this.$el.html this.template this.model.toJSON() 51 return this 52 53 AppView = Backbone.View.extend 54 # 初始化保存DOM对象 55 initialize : () -> 56 this.$input = this.$('.todo-input-text').focus() 57 this.$todoList = this.$('.todo-undone-list') 58 this.$todoDoneList = this.$('.todo-done-list') 59 60 this.listenTo Todos, 'add', this.addOne 61 this.listenTo Todos, 'change:done', this.addOne 62 63 Todos.fetch() 64 65 events : 66 'keypress input.todo-input-text' : 'createOnEnter' 67 68 # Enter 时保存 69 createOnEnter : (e) -> 70 if e.keyCode != 13 71 return 72 if !this.$input.val() 73 return; 74 75 Todos.create title: this.$input.val() 76 this.$input.val('') 77 78 addOne : (todo) -> 79 view = new TodoView model : todo 80 if todo.get('done') 81 # 已经完成的加入已完成列表 82 this.$todoDoneList.append(view.render().el); 83 else 84 # 未完成的加入未完成列表 85 this.$todoList.append(view.render().el); 86 87 # Todos.each (todo) -> 88 todo.save() 89 90 App = new AppView el : $('.todo-container') # 主应用UI 91 92 return init : () -> 93 Backbone.history.start() 94
main.css
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 .todo-container { 2 margin: 50px auto 0 auto; 3 width: 300px; 4 } 5 .todo-item-list { 6 margin-top: 20px; 7 } 8 .todo-item-list > div { 9 float: left; 10 width: 90%; 11 margin-top: 10px; 12 padding-left: 5%; 13 } 14 .todo-item-list > div a:hover { 15 text-decoration: none; 16 } 17 .todo-item-list > div button { 18 margin: 0 3px; 19 } 20 .todo-item-list > div span.order { 21 margin-right: 10px; 22 color: #B6B6B6; 23 font-style: italic; 24 } 25 .todo-item-list > p { 26 font-weight: bold; 27 margin-top: 1em; 28 }
效果图
补充:
这里用的是 coffeescript,yeoman会自动转成js。关于todo-list,可以上官网参考下,我这里简化了部分代码。