现在的位置: 首页 > 综合 > 正文

javascriptMVC教程 — 4.开始使用javascriptMVC–创建Cookbook

2013年06月24日 ⁄ 综合 ⁄ 共 7231字 ⁄ 字号 评论关闭

  我们将创建Cookbook应用,提供菜谱的创建和删除功能,他看起来像下面的样子。

  javascriptMVC使用 generator scripts 生成工具帮助你创建你的文件夹和文件,让你的工作变得更加轻松。

 

  创建应用程序

  创建应用程序,首先打开win的命令窗口,导航到应用程序的根目录,运行下面的代码:

> js jquery\generate\app cookbook

  脚本会帮你创建应用程序的文件夹和文件,目录如下:

cookbook/                // 应用程序目录
  cookbook.css           // app 的 css
  cookbook.html          // app 首页
  cookbook.js            // app js
  docs/                  // 文档
  fixtures/              // 模拟ajax请求
  funcunit.html          // functional 测试页面
  models/                // 模型数据层
  qunit.html             // unit 测试页面
  scripts/               // 命令行脚本
    build.html           // build 脚本页面
    build.js             // build 脚本
    clean.js             // clean代码
    crawl.js             // 生成 search 内容
    docs.js              // 创建文档
  test/                    
    funcunit             // functional 测试
      cookbook_test.js   // functional 测试
      funcunit.js        // 加载functional 测试
    qunit/               // unit 测试
      cookbook_test.js   // unit 测试
      qunit.js           // 加载unit 测试

  下面是我在自己机器上运行的效果:

  生成的cookbook文件夹:

  cookbook文件夹中的文件:

 

  我们将使用cookbook.html作为应用首页,如果你需要生成别的页面,可以使用下面的命令:

> js jquery\generate\page cookbook index.html

  在页面中添加下面的scripts标签:

<script type='text/javascript' src='../path/to/steal/steal.js?cookbook'></script>

  打开cookbook/cookbook.html页面,会显示下面的结果。

  打开cookbook/cookbook.html页面,你会发现

<script type='text/javascript' src='../steal/steal.js?cookbook'>

他会加载steal,steal会加载cookbook/cookbook.js,打开cookbook.js文件,你会看到下面的内容。

steal(
    './cookbook.css',           // app CSS 文件
    './models/models.js',       // steals 所有 models
    './fixtures/fixtures.js',   // 创建 models 的模拟ajax请求
    function(){                 // 配置 app

})

  应用程序文件加载和配置应用程序资源,包括css、js等。接下来我们创建插件工具、model、模拟请求等,并允许我们执行创建和删除菜单的操作。

 

  搭建菜谱

  我们将使用scaffold generator去快速创建菜谱,他会实现下列功能:

  • 菜谱 model 实现服务器端的CRUD操作
  • 模拟菜谱的服务器端请求
  • 创建菜谱的插件
  • 罗列和删除菜谱的插件

在命令下执行下面的命令,完成上述工作。

> js jquery\generate\scaffold Cookbook.Models.Recipe

  下面介绍生成的可部分代码及功能:

recipe.js:recipe模型,用于实现服务器端对recipe执行创建、获取、更新和删除操作。

recipe_test.js:测试recipe模型。

fixtures.js:模拟recipe的ajax请求。

recipe/create:文件夹下面包含创建recipe插件的代码、demo页面和测试代码。

recipe/list:文件夹下面包含罗列recipe插件的代码、demo页面和测试代码。

 

  (steal added)

  generator同时会罗列那些显示(steal added)文件,例如:

cookbook/models/models.js (steal added)

截图:

  "(steal added)"的意思是你的文件需要加载别的文件,generator在你的文件中使用steal为你完成了这个工作。例如,cookbook/models/models.js需要加载 recipe.js,我们来看models.js的代码:

// 加载 model 文件
steal("jquery/model", './recipe.js')

 

  设置页面

  generator运行之后,cookbook.js文件的代码如下:

steal(
    './cookbook.css',           // app CSS 文件
    './models/models.js',       // 加载所有 models
    './fixtures/fixtures.js',   // 为 models 创建模拟请求
    'cookbook/create',
    'cookbook/list',
    function(){                 // 配置你的应用

        $('#recipes').cookbook_recipe_list();
        $('#create').cookbook_recipe_create();
})

  你会注意到在完成cookbook/create 和cookbook/list加载中后,他们会把插件添加到#recipes 和 #create元素上。但是这两个元素并不存在,打开cookbook/cookbook.html文件,添加下面的代码完成对两元素的添加:

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <title>cookbook</title>
    </head>
    <body>
        <h1>Welcome to JavaScriptMVC 3.2!</h1>
        <ul id='recipes'></ul>
        <form id='create' action=''></form>
        <script type='text/javascript' 
                src='../steal/steal.js?cookbook'>    
        </script>
    </body>
</html>

 

  运行程序

  现在我们可以运行程序了,在浏览器打开cookbook/cookbook.html,我们来看运行结果。

 

  他是如何工作的

  cookbook应用可以分割为5个部分:

  • Recipe 模型(Model)
  • Recipe 请求模拟(Fixture)
  • Recipe 创建控制
  • Recipe 显示控制
  • Cookbook 应用程序,组合所有组件共同工作

 

  Recipe模型

  cookbook/models/recipe.js看起来像这样:

steal('jquery/model', function(){

  $.Model('Cookbook.Models.Recipe',
  {
    findAll: "/recipes.json",
    findOne : "/recipes/{id}.json", 
    create : "/recipes.json",
    update : "/recipes/{id}.json",
    destroy : "/recipes/{id}.json"
  },
  {});
})

  所有加载$.Model然后用它创建了Cookbook.Models.Recipe类,该类为我们提供了创建、获取、更新和销毁的功能,我们来看例子。

 

  create

// 创建一个 recipe 实例
var recipe = new Cookbook.Models.Recipe({
  name: 'Hot Dog',
  description: 'nuke dog, put in bun'
 })

// 调用 save 在服务器端保存实例
recipe.save()

 

  retrieve

// 从服务器获取 recipes
Cookbook.Models.Recipe.findAll({}, function(recipes){
  // 使用recipes
})

 

  update

// 更新 recipe 属性
recipe.attrs({
  name: 'Bratwurst',
  description: 'nuke bratwurst, put in bun'
});

// 调用 save 保存数据到服务器
recipe.save()

 

  delete

// 调用 destroy
recipe.destroy()

  我们没有服务器端,所以我们要使用fixture来模拟。

  Recipe Fixture

  Fixtures可以截获ajax请求并模拟返回结果,使用它的好处就是你可以在没有服务器的情况下开发你的前台代码。打开 cookbook/fixtures/fixtures.js你会发现下面的代码:

$.fixture.make("recipe", 5, function(i, recipe){
    var descriptions = ["grill fish", "make ice", "cut onions"]
    return {
        name: "recipe "+i,
        description: $.fixture.rand( descriptions , 1)
    }
})

  他为我们模拟了5个recipe。

 

  Recipe创建控制

  在浏览器打开cookbook/recipe/create/create.html,这里展示了Cookbook.Recipe.Create control控件,他为我们提供创建recipe的功能。我们打开cookbook/recipe/create/create.js来看她时如何实现的:

steal( 'jquery/controller',
       'jquery/view/ejs',
       'jquery/dom/form_params',
       'jquery/controller/view',
       'cookbook/models' )
.then('./views/init.ejs', function($){

  $.Controller('Cookbook.Recipe.Create',
  {
    init : function(){
      this.element.html(this.view());
    },
    submit : function(el, ev){
      ev.preventDefault();
      this.element.find('[type=submit]').val('Creating...');
      new Cookbook.Models.Recipe(el.formParams()).save(this.callback('saved'));
    },
    saved : function(){
      this.element.find('[type=submit]').val('Create');
      this.element[0].reset();
    }
  });
});

  代码使用steal来加载依赖项,然后创建Cookbook.Recipe.Create控制器,他创建了名为cookbookrecipecreate的jquery helper,我们可以这样使用它:

$('form#create').cookbook_recipe_create()

当jquery插件被调用的时候,init方法会被执行。

this.element.html(this.view());

  上面的代码把模版cookbook/recipe/create/views/init.ejs,加载到控制器所在的html元素上。当jquery插件被调用的时候,相关事件也会绑定到控制器的元素上,例如上面的代码就实现了对submit事件的监听。当有submit事件发生的时候,submit按钮的值会被修改,同时会创建一个新的recipe对象。

 

  Recipe显示控制

  在浏览器打开cookbook/recipe/create/create.html页面,这里展示了Cookbook.Recipe.List控件。他从服务器端加载recipe,并允许你执行删除操作。同时他也提供了创建recipe的功能,并会把记录展示。打开cookbook/recipe/list/list.js,我们来看Cookbook.Recipe.List的代码:

$.Controller('Cookbook.Recipe.List',
{
  init : function(){
    this.element.html(this.view('init',Cookbook.Models.Recipe.findAll()) )
  },
  '.destroy click': function( el ){
    if(confirm("Are you sure you want to destroy?")){
      el.closest('.recipe').model().destroy();
    }
  },
  "{Cookbook.Models.Recipe} destroyed" : function(Recipe, ev, recipe) {
    recipe.elements(this.element).remove();
  },
  "{Cookbook.Models.Recipe} created" : function(Recipe, ev, recipe){
    this.element.append(this.view('init', [recipe]))
  },
  "{Cookbook.Models.Recipe} updated" : function(Recipe, ev, recipe){
      recipe.elements(this.element)
          .html(this.view('recipe', recipe) );
  }
});

  当List加载到页面,init方法会被执行。

this.element.html(this.view('init',Cookbook.Models.Recipe.findAll()) )

上面一行代码完成了下面4项工作:

  • 从服务器端请求recipes
  • 加载 cookbook/recipe/list/views/init.ejs 模版
  • 当 recipes 数据返回,并且模版完成加载,呈现结果
  • 把结果插入到队列中

init.ejs文件内容:

<%for(var i = 0; i < this.length ; i++){ %>
    <li <%= this[i]%> >
        <%== $.View('//cookbook/recipe/list/views/recipe.ejs', this[i] )%>
    </li>
<%}%>

  上面的代码会遍历从服务器端获取的结果,为每个recipe创建li对象,并且会渲染子模版。注意到代码在<li>内部添加了

<%= this[i]%>

他会把model添加到jQuery.data中,并会为li添加一个‘recipe’ 的 className,我们之后会使用到。

 

  销毁Recipe

  每一个recipe都有一个销毁的链接,点击它之后会执行'.destroy click'方法:

if(confirm("Are you sure you want to destroy?")){
  el.closest('.recipe').model().destroy();
}

  他会首先询问你时候真要执行销毁操作,如果真要销毁,他通过recipe的父元素获取model实例(在jquery.data中),然后执行销毁操作。当实例被销毁的时候,destroyed事件会被执行,他是通过下面的方式注册的:

"{Cookbook.Models.Recipe} destroyed" : function(Recipe, ev, recipe) {
  recipe.elements(this.element).remove();
}

  当销毁事件发生的时候,List控制器会查询[jQuery.fn.elements elements]获取到jQuery.data中的实例,然后销毁它。

 

  创建Recipe

  当recipe创建的时候,List监听的"created"事件会被触发。

"{Cookbook.Models.Recipe} created" : function(Recipe, ev, recipe){
  this.element.append(this.view('init', [recipe]))
}

  所以当recipe被创建的时候,init视图会被渲染并把结果加载到recipe元素中。

 

  更新Recipe

  当recipe更新的时候,List监听的"updated"事件会被触发。

"{Cookbook.Models.Recipe} updated" : function(Recipe, ev, recipe){
  recipe.elements(this.element)
        .html(this.view('recipe', recipe) );
}

  当recipe更新的时候,List会更新html页面。

 

  整合代码

  cookbook应用加载所有相关组件,并把他们加载到页面。当Cookbook.Recipe.Create创建一个recipe,他会创建一个Cookbook.Recipe.List监听的'created'事件,然后把新创建的对象添加在列表中。

 

  最后我把demo附上,还是老样子,demo需要在iis等服务器上执行,javascriptMVC的代码自己去下。

  javascriptMVC下载地址:https://github.com/downloads/jupiterjs/javascriptmvc/javascriptmvc-3.2.4.zip

  demo下载地址:javascriptmvc_cookbook.zip

 

  javascriptMVC教程目录

抱歉!评论已关闭.