返回介绍

Day 24: 使用 Yeoman 自动构建 Ember 项目

发布于 2025-01-31 20:47:31 字数 12942 浏览 0 评论 0 收藏 0

到目前为止,我们这个系列讨论了 BowerAngularJSGruntJSPhoneGapMeteorEmberTimelineJS 等 JavaScript 技术。今天的 《30 天学习 30 种新技术》 ,我决定学习前端开发的效率工具 Yeoman 。本文将首先介绍 Yeoman 的基本情况,接着我们会使用 Yeoman 开发一个 Ember 应用。本文不会介绍 EmberJS 的基本知识,所以请参考 day 19

Yeoman 是什么?

Yeoman 按照官方说法,它不只是一个工具,还是一个工作流。它其实包括了三个部分 yo、grunt、bower,分别用于项目的启动、文件操作、包管理。

  1. Yo: Yo 是一个项目初始化工具,可以生成一套启动某类项目必需的项目文件。
  2. GruntJS: GruntJS 是基于 JavaScript 的命令行构建工具,它可以帮助开发者们自动化重复性的工作。阅读 day 5 获取更多信息。
  3. Bower: Bower 是一个客户端技术的软件包管理器,它可用于搜索、安装和卸载如 JavaScript、HTML、CSS 之类的网络资源。阅读 day 1 获取更多信息。

我为什么关心 Yeoman

如果你需要说服自己学习 Yeoman,你可以读读 Yeoman 网站上的 whyyeoman

安装

使用 npm 安装:

npm install -g yeoman

安装 Yeoman Ember 生成器

Yeoman 依赖生成器为 web 项目提供支架。所有的现代 JavaScript MV* 框架都有相应的生成器。本文使用 Ember:

npm install -g generator-ember

我们将开发一个社交化书签应用,允许用户提交和分享链接。你可以在 这里 查看这个应用。这个应用和我们 day 19 开发的一样。

Github 仓库

今天的示例应用代码可从 Github 取得。

创建 Ember 应用

现在开始应用开发。首先创建项目目录,接着运行 yo ember 命令,它会询问你是否使用 Twitter Bootstrap。我习惯在自己的项目中使用 Bootstrap,所以我选了是。

; mkdir getbookmarks
; cd getbookmarks
; yo ember

   _-----_
  |     |
  |--(o)--|   .--------------------------.
   ---------  |  Welcome to Yeoman,  |
  ( __ )   |   ladies and gentlemen!  |
  /___A___\   '__________________________'
   |  ~  |
   __'.___.'__


[?] Would you like to include Twitter Bootstrap for Sass? Yes

之后 Yeoman 会创建一个 Ember 应用,自动使用 bowernpm 安装依赖。

现在让我们看看 Yeoman 生成的 Ember 应用。应用有三个顶层目录: appnode_modulestest 。还有一些配置文件: .bowerrc.gitignore.jshintrcGruntfile.jspackage.json 。目录结构如下所示。

所有的应用相关代码都在 app 目录下。目录结构遵循 Ember 的最佳实践。

  1. bower_components 目录包括了客户端依赖,例如 Ember、Twitter Bootstrap,等等。Bower 在所有文件夹内安装所有依赖。
  2. image 目录包括了应用相关的图像。Yeoman 会优化 image 目录内的图片。
  3. index.html 包含了所有的 ember.js 依赖,所有的 bootstrap 依赖,以及 build 注释(Gruntfile.js 可以据此替换或移除引用的未优化的脚本和样式表)。
  4. scripts 目录包含了 Ember 应用的 controller、view、model 和 route。
  5. styles 目录包含了应用相关的 css 文件。
  6. 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="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="#">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

今天就这些。保持反馈。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文