从JavaScriptMVC开始如何完成项目之创建应用程序

如何使用JavaScriptMVC开发项目第一步,就是创建应用程序。

在这里我们使用一个例子开始讲解。

下面我们将创建一个基本厨师手册应用系统,它让我们可以创建和删除食谱。如下图:

JavaScriptMVC提供生成脚本来帮助你们安装应用程序的文件和文件夹。

1、创建一个应用程序

在创建你的应用程序之前,打开一个Window系统的控制台窗口,即doc命令窗口,并且把目录定位到JavaScriptMVC包目录下。
在DOC命令窗口,执行:
js jquery/generate/app cookbook
这个脚本将生成一个应用程序的文件夹和文件。生成最张的程序目录如下:
cookbook/                // 应用程序的主目录文件夹
  cookbook.css           // 默认的应用程序样式文件
  cookbook.html          // 默认的应用程序主页面文件
  cookbook.js            // 应用程序主文件,相当我们main方法,加载所有程序需要的资源
  docs/                  // 帮助文件文件夹
  fixtures/              // 模拟的Ajax请求服务端
  funcunit.html          // 功能的测试页面,主要测试C和V
  models/                // 模型 即MVC中的M数据层
  qunit.html             // 单元测试页面,主要测试M
  scripts/               // 命令行脚本
    build.html           // html for build script
    build.js             // 压缩程序所有文件,这个命令可以让我们只压缩项目中需要的资源
    clean.js             // code cleaning / linting
    crawl.js             // generate search content
    docs.js              // 生成帮助文档,相对我们之前的Web项目,这个可以让Web阅读和维护起到很大的帮助
  test/                   
    funcunit             // 功能测试文件夹,包含程序中所有功能的测试文件
      cookbook_test.js   // cookbook功能的测试文件
      funcunit.js        // 加载程序中所有功能的测试文件
    qunit/               //  单元测试文件夹,包含程序中所有单元测试文件
      cookbook_test.js   // cookbook单元测试文件
      qunit.js           // 加载程序中所有单元测试文件
我们将使用cookbook.html来做为我们应用程序的主页面文件。当然,如果你需要创建其它文件做为应用程序的主页面文件。
执行:
js jquery/generate/page cookbook index.html
或者我们直接创建一个其它文件,然后再在这个文件中添加如下代码即可。
<script type='text/javascript'
        src='../path/to/steal/steal.js?cookbook'>
</script>

如果用浏览器打开cookbook.html,你将看到一个JavaScriptMVC欢迎界面。


用编辑器打开cookbook.html文件,你将看到如下代码:
<script type='text/javascript'
        src='../steal/steal.js?cookbook'>
</script>

这行代码的意思是加载steal,且告诉steal加载cookbook/cookbook.js文件。

打开cookbook.js文件,你将看到如下代码:
steal(
    './cookbook.css',           // Web程序的CSS样式文件
    './models/models.js',       // 加载所有模型
    './fixtures/fixtures.js',   // 为模型设置模拟的Ajax请求服务端
    function(){                 // 配置你的应用程序,这个相当于main方法

});

这个相当我们平时经常写的main函数。
这个文件实现了加载和配置你的应用程序所需要的资源。当前,它只是加载了应用程序的CSS样式文件,模型和fixture。

下面我们将创建窗口,模型,和模拟的Ajax请求服务端使我们可以创建和删除食谱。

脚手架上的食谱

我们将使用脚手架产生器快速生成:

一个在服务端具有添删查改功能的食谱模型
一个模拟的食谱服务
一个创建食谱的窗口
一个显示和删除食谱的窗口

脚手架食谱生成只需要在执行以下命令:
js jquery\generate\scaffold Cookbook.Models.Recipe

      cookbook/models/recipe.js //创建一个食谱模型,它可以生成,检索,修改,和删除食谱在服务端。
      cookbook/test/qunit/recipe_test.js //食谱模型单元测试文件
      cookbook/models/models.js (steal added)
      cookbook/test/qunit/qunit.js (steal added)
      //这个产生器添加模拟的食谱模型Ajax请求代码。(你没有真正的食谱服务,如果你存在真正的服务端,可以把这部分代码删除掉。)
      cookbook/fixtures/fixtures.js (code added)
      //包含创建食谱的代码的文件夹
      cookbook/recipe/create/create.html
      cookbook/recipe/create/create.js
      cookbook/recipe/create/create_test.js
      cookbook/recipe/create/funcunit.html
      cookbook/recipe/create/views/init.ejs
      //包含显示和删除食谱的代码的文件夹
      cookbook/recipe/list/funcunit.html
      cookbook/recipe/list/list.html
      cookbook/recipe/list/list.js
      cookbook/recipe/list/list_test.js
      cookbook/recipe/list/views/recipe.ejs
      cookbook/recipe/list/views/init.ejs
      cookbook/test/funcunit/funcunit.js (steal added)
      cookbook/test/funcunit/funcunit.js (steal added)
      cookbook/cookbook.js (steal added)
      cookbook/cookbook.js (steal added)
      cookbook/cookbook.js (code added)

页面安装

产生器执行后,你的应用程序文件(cookbook.js)如下:

steal(
    './cookbook.css',           // application CSS file
    './models/models.js',       // steals all your models
    './fixtures/fixtures.js',   // sets up fixtures for your models
    'cookbook/create',
    'cookbook/list',
    function(){                 // configure your application

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

新添加的代码加载cookbook/create和cookbook/list模块,且在#recipes和#create元素上添加控件。

然而, #recipes和#create元素不存在。打开cookbook.html文件,添加一个#recipes的ul元素和一个#create的form元素,
代码如下:
<!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.html文件。显示如下:


下面我们继续测试厨师手册和讲解这些代码是如何工作的。

这些代码如何工作?

厨师手册程序分为5个部分:

1、食谱模块
2、食谱模拟Ajax请求
3、食谱创建控制器
4、食谱列表控件器
5、厨师手册主程序把上面4个部分放在一起

食谱模块和模拟Ajax请求(Fixture)

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
// create a recipe instance
var recipe = new Cookbook.Models.Recipe({
  name: 'Hot Dog',
  description: 'nuke dog, put in bun'
 })

// call save to create on the server
recipe.save()
retrieve

// get recipes from the server
Cookbook.Models.Recipe.findAll({}, function(recipes){
  // do something with recipes
})

update

// update the properties of a created recipe
recipe.attrs({
  name: 'Bratwurst',
  description: 'nuke bratwurst, put in bun'
});

// call save to send updates to the server
recipe.save()

delete

// call destroy
recipe.destroy()

当然,在这里我们没有一个真实的服务端响应请求。只能用模拟Ajax请求(Fixture)来实现。

食谱模拟Ajax请求(The Recipe Fixture)

固定装置拦截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个食谱的模拟服务。

创建食谱控制器

在浏览器打开cookbook/recipe/create/create.html文件.
这个页面演示创建食谱控制器和让你创建食谱。它是一个创建食谱程序,可以独立执行。
打开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();
    }
  });
});

上面代码实现使用steall加载依赖模块和创建一个Cookbook.Recipe.Create控制器。
并且为一个form元素绑定上这个Cookbook.Recipe.Create控制器。

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

当上面这句代码执行后,Cookbook.Recipe.Create控制器的init方法被调用和执行下面语句:

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

这个代码是把cookbook/recipe/create/views/init.ejs模板渲染到控制器的元素上。并且在控制器的元素上绑定事件处理。在这个例子中,
监听的是"submit"事件在这个元素上。

当一个submit事件产生后,更新submit按钮文本,并且创建一个新的食谱。

食谱列表控制器

在浏览器打开cookbook/recipe/list/list.html.
这个页面演示Cookbook.Recipe.List控制器。它从服务端加载食谱列表,让你可以删除食谱,和它也监听食谱的创建和添加到列表中。

打开cookbook/recipe/list/list.js文件,代码如下:

$.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) );
  }
});

当食谱列表控制器添加到页面上,init函数被调用:

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

这个代码做了4件事:

1、从服务端请求食谱列表。
2、加载cookbook/recipe/list/views/init.ejs模板。
3、当请求和模板加载完后,渲染它。
4、把最终结果插入到列表元素中。

init.ejs 代码如下:

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


通过循环生成一个li元素并且把内容通过recipe.ejs子模板渲染到页面上。
我们还会发现一个很特别的地方,就是在<li>上加上<%= this[i]%>,这个地方很重要,它代表
把每个食谱模型实现绑定到对应的LI元素中。且在LI元素上设置了一个名为recipe的Class。我们一会将使用到它。

删除食谱

每个食谱都有一个删除链接。当它被点击时,列表中的'.destroy click'方法将被调用:

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

它找到'recipe'元素且获得该模型实例。接着执行这个模型的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]))
}

所以,当一个食谱创建后,它将渲染单个食谱init视图并且把视图加到食谱列表中。

修改食谱

When a recipe is updated, an "updated" event is triggered. The List control listens for this with:
当一个食谱修改后,一个修改事件将被触发。列表控制器监听:
"{Cookbook.Models.Recipe} updated" : function(Recipe, ev, recipe){
  recipe.elements(this.element)
        .html(this.view('recipe', recipe) );
}
所以,当这个食谱修改后,列表将刷新HTML中的元素。


把所有放到一起

厨师手册程序加载这个窗体并把它们加到页面上。当Cookbook.Recipe.Create创建一个食谱,它产生一个创建事件,列表监听到会把这个新创建食谱添加到列表中来。

下一节,我们讲解测试厨师手册程序。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值