zoukankan      html  css  js  c++  java
  • 好文推荐系列---------(4)使用Yeoman自动构建Ember项目

    好文原文地址:http://segmentfault.com/a/1190000000368881

    我决定学习前端开发的效率工具Yeoman。本文将首先介绍Yeoman的基本情况,接着我们会使用Yeoman开发一个Ember应用。

    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
    

    今天就这些。保持反馈。

  • 相关阅读:
    我画着图,FluentAPI 她自己就生成了
    寻找性能更优秀的不可变小字典
    寻找性能更优秀的动态 Getter 和 Setter 方案
    数据治理方案技术调研 Atlas VS Datahub VS Amundsen
    数据库读写分离这个坑,你应该踩过吧?
    写了一套优雅接口之后,领导让我给大家讲讲这背后的技术原理
    年轻人不讲武德,竟然重构出这么优雅后台 API 接口
    贞炸了!上线之后,消息收不到了!
    一笔订单,但是误付了两笔钱!这种重复付款异常到底该如何解决?
    自动化运维工具之Puppet master/agent模型、站点清单和puppet多环境设定
  • 原文地址:https://www.cnblogs.com/alisayuan/p/5124158.html
Copyright © 2011-2022 走看看