首页 > 代码库 > 使用Yeoman自动构建Ember项目
使用Yeoman自动构建Ember项目
Yeoman是什么?
Yeoman按照官方说法,它不只是一个工具,还是一个工作流。它其实包括了三个部分yo、grunt、bower,分别用于项目的启动、文件操作、包管理。
Yo: Yo是一个项目初始化工具,可以生成一套启动某类项目必需的项目文件。
Grunt: Grunt是基于JavaScript的命令行构建工具,它可以帮助开发者们自动化重复性的工作。
Bower: Bower是一个客户端技术的软件包管理器,它可用于搜索、安装和卸载如JavaScript、HTML、CSS之类的网络资源。
安装
使用npm
安装:(npm的安装方法可自行百度,它其实就是nodejs的包管理工具,在windwos有安装包直接setup即可)
npm install -g yo grunt-cli bower
安装Yeoman Ember生成器
Yeoman依赖生成器为web项目提供支架。所有的现代JavaScript MV* 框架都有相应的生成器。本文使用Ember:
npm install -g generator-ember
创建Ember应用
现在开始应用开发。首先创建项目目录,接着运行yo ember
命令
之后Yeoman会创建一个Ember应用,自动使用bower
和npm
安装依赖。
现在让我们看看Yeoman生成的Ember应用。应用有三个顶层目录:app
、node_modules
和test
。还有一些配置文件:.bowerrc
、.gitignore
、.jshintrc
、Gruntfile.js
和package.json
。目录结构如下所示。
所有的应用相关代码都在app
目录下。目录结构遵循Ember的最佳实践。
bower_components
目录包括了客户端依赖,例如Ember、Twitter Bootstrap,等等。Bower在所有文件夹内安装所有依赖。image
目录包括了应用相关的图像。Yeoman会优化image
目录内的图片。index.html
包含了所有的ember.js
依赖,所有的bootstrap依赖,以及build
注释(Gruntfile.js可以据此替换或移除引用的未优化的脚本和样式表)。scripts
目录包含了Ember应用的controller、view、model和route。styles
目录包含了应用相关的css文件。templates
目录包含了应用的handlebar模板。
现在我们可以启动预览服务器了:
grunt server
这会使用系统默认浏览器打开应用:
生成Story Model
我们在day19中开发的GetBookmarks应用中创建了一个Ember Model:Story。Yeoman的次级生成器可以用来构建项目的部分,包括model。运行如下命令生成Story model:
yo ember:model Story
命令的输出如下:
create app/scripts/models/story_model.js invoke ember:controller:/usr/local/lib/node_modules/generator-ember/model/index.js create app/scripts/controllers/stories_controller.js create app/scripts/controllers/story_edit_controller.js create app/scripts/routes/stories_route.js create app/scripts/routes/story_route.js create app/scripts/routes/story_edit_route.js invoke ember:view:/usr/local/lib/node_modules/generator-ember/controller/index.js create app/scripts/views/story_view.js create app/scripts/views/story_edit_view.js create app/scripts/views/stories_view.js create app/templates/story.hbs create app/templates/story_edit.hbs create app/templates/stories.hbs create app/scripts/views/bound_text_field_view.js invoke ember:router:/usr/local/lib/node_modules/generator-ember/controller/index.js conflict app/scripts/router.js[?] Overwrite app/scripts/router.js? overwrite force app/scripts/router.js
这会在app/scripts/models
目录下生成story_model.js
,同时会生成相应的view、controller和route。
修改下story_model
:
Emberapp.Story = DS.Model.extend({ url : DS.attr(‘string‘), tags : DS.attr(‘string‘), fullname : DS.attr(‘string‘), title : DS.attr(‘string‘), excerpt : DS.attr(‘string‘), submittedOn : DS.attr(‘date‘)});
重新启动Grunt server以便改动生效。
安装Ember LocalStorage适配器
我们将使用HTML 5 LocalStorage来存储数据。使用bower安装适配器。
bower install --save ember-localstorage-adapter
然后更新index.html
页面,添加依赖:
<script src=http://www.mamicode.com/"bower_components/ember-localstorage-adapter/localstorage_adapter.js"></script>
同时更新app/scripts/store.js
,配置应用使用LSAdapter:
Getbookmarks.Store = DS.Store.extend();Getbookmarks.ApplicationAdapter = DS.LSAdapter.extend({ namespace: ‘stories‘});
更新路由
修改router.js
:
Getbookmarks.Router.map(function () { this.resource(‘index‘,{path : ‘/‘}); this.resource(‘story‘, { path: ‘/story/:story_id‘ }); this.resource(‘story_edit‘, { path: ‘/story/new‘ });});
提交新报道
我们首先添加用户访问#/story/new
后会出现的表单。修改app/templates/story_edit.hbs
:
<form class="form-horizontal" role="form"> <div class="form-group"> <label for="title" class="col-sm-2 control-label">Title</label> <div class="col-sm-10"> <input type="title" class="form-control" id="title" name="title" placeholder="Title of the link" required> </div> </div> <div class="form-group"> <label for="excerpt" class="col-sm-2 control-label">Excerpt</label> <div class="col-sm-10"> <textarea class="form-control" id="excerpt" name="excerpt" placeholder="Short description of the link" required></textarea> </div> </div> <div class="form-group"> <label for="url" class="col-sm-2 control-label">Url</label> <div class="col-sm-10"> <input type="url" class="form-control" id="url" name="url" placeholder="Url of the link" required> </div> </div> <div class="form-group"> <label for="tags" class="col-sm-2 control-label">Tags</label> <div class="col-sm-10"> <textarea id="tags" class="form-control" name="tags" placeholder="Comma seperated list of tags" rows="3" required></textarea> </div> </div> <div class="form-group"> <label for="fullname" class="col-sm-2 control-label">Full Name</label> <div class="col-sm-10"> <input type="text" class="form-control" id="fullname" name="fullname" placeholder="Enter your Full Name like Shekhar Gulati" required> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-success" {{action ‘save‘}}>Submit Story</button> </div> </div> </form>
现在,访问 http://localhost:9000/#/story/new 可以看到提交报道的表单。
更新StoryEditController
,将数据持续化入本地存储:
Getbookmarks.StoryEditController = Ember.ObjectController.extend({ save: function(){ var url = $(‘#url‘).val(); var tags = $(‘#tags‘).val(); var fullname = $(‘#fullname‘).val(); var title = $(‘#title‘).val(); var excerpt = $(‘#excerpt‘).val(); var submittedOn = new Date(); var store = this.get(‘store‘); console.log(‘Store .. ‘+store); var story = store.createRecord(‘story‘,{ url : url, tags : tags, fullname : fullname, title : title, excerpt : excerpt, submittedOn : submittedOn }); story.save(); this.transitionToRoute(‘index‘); }});
列出所有报道
接下来我们要实现的功能是在侧边栏展示报道列表。
在application_route.js
,我们从本地存储获取所有的报道。
Getbookmarks.ApplicationRoute = Ember.Route.extend({ model : function(){ var stories = this.get(‘store‘).findAll(‘story‘); return stories; }});
接着我们更新application.hbs
,为每个报道的标题添加链接:
<div> <nav class="navbar navbar-default navbar-fixed-top" role="navigation"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href=http://www.mamicode.com/"#">GetBookmarks</a> </div> <div class="collapse navbar-collapse navbar-ex1-collapse"> <ul class="nav navbar-nav pull-right"> <li>{{#link-to ‘story_edit‘}}<span class="glyphicon glyphicon-plus"></span> Submit Story{{/link-to}}</li> </ul> </div> </nav> <div class="container" id="main"> <div class="row"> <div> <div class="col-md-3"> <div class="well sidebar-nav"> <table class=‘table‘> <thead> <tr><th>Recent Stories</th></tr> </thead> {{#each controller}} <tr><td> {{#link-to ‘story‘ this}} {{title}} {{/link-to}} </td></tr> {{/each}} </table> </div> </div> <div class="col-md-9"> {{outlet}} </div> </div> </div> </div></div>
应用的用户界面会刷新。
查看单独的报道
最后要添加的功能是,用户访问 http://localhost:9000/#/story/:id 的时候可以查看单独的报道。:id
对应于story id
。修改story_routejs
。
Getbookmarks.StoryRoute = Ember.Route.extend({ model : function(params){ var store = this.get(‘store‘); return store.find(‘story‘,params.story_id); }});
修改app/templates/story.hbs
:
<h1>{{title}}</h1><h2> by {{fullname}} <small class="muted">{{submittedOn}}</small></h2>{{#each tagnames}} <span class="label label-primary">{{this}}</span>{{/each}}<hr><p class="lead"> {{excerpt}}</p>
为生产环境构建
最后,我们运行grunt build
命令创建一个可分发的应用。grunt build
命令将app
目录下的源文件转换成dist
目录下的可分发的应用。
grunt build
使用Yeoman自动构建Ember项目