<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Fork me on GitHub

      Ember.js實現單頁面應用程序

      1.1.1 摘要

      單頁應用程序 (SPA) 是加載單個HTML 頁面并在用戶與應用程序交互時動態更新該頁面的Web應用程序。

      SPA使用AJAX和HTML5創建流暢且響應迅速的Web應用程序,不會經常進行頁面重載。 但是,這意味著許多工作在客戶端的JavaScript中進行。這導致我們需要在客戶端中編程更多的Javascript代碼來處理數據的交互問題,幸運的是,我們可以借助許多開放源代碼JavaScript框架來簡化創建SPA的任務,例如:Ember、Backbone、Angular、Knockout、DurandalJS和Hot Towel等等。

      目錄

      1.1.2 正文

      Ember是一個強大的JavaScript MVC框架,它用來創建復雜的Web應用程序,消除了樣板,并且提供了一個標準的應用程序架構,它支持用戶界面綁定、視圖、Web表示層并且很好的和其他框架結合,為了創建一個實時交互的Web應用程序中,這里我們使用了ASP.NET MVC的REST服務。

      MVC概念

      相信大家對于MVC模式再熟悉不過了,這里我們簡單說一下MVC模式:它目的是為了分離視圖、模型和控制器而設計出來的;其中模型用來儲存數據,視圖用來向用戶展示應用程序,控制器充當模型和視圖之間的橋梁。

      SPA8

      圖1 MVC模式

      SPA1

      圖2 Ember MVC

      上圖是Ember實現MVC模式,它包括了View、Controller、Router、Template以及Model等概念,接下來,我們將通過實現單頁面應用程序來介紹Ember和Web API結合使用。

      創建ASP.NET MVC 項目

      首先,我們創建一個ASP.NET MVC 4 Web應用程序,然后,選擇項目模板Web API,這里為了簡單所以沒有使用Ember.js的模板,如果大家想使用或學習請到這里下載。

      SPA2

       

      SPA3

      圖3 創建ASP.NET MVC 4程序

      接著,我們在Script文件夾中添加引用腳本文件ember.js、ember-data.js、handlebars-1.0.0.js和jquery-2.0.3.js等,然后創建app文件,它用來存放客戶端的腳本文件,我們創建application.js、models.js、routes.js和controllers.js文件。

      SPA4

      圖4 創建ASP.NET MVC 4程序

      現在,我們通過實現ASP.NET MVC應用程序來提供服務端的API,單頁面應用程序通過調用我們的API接口對數據進行操作,接下來,我們將給出具體的實現方法。

      服務端的Model

      接下來,我們在Models文件中創建一個數據傳輸類Employee,具體定義如下:

      /// <summary>
      /// Defines a DTO Employee.
      /// </summary>
      public class Employee
      {
          public int Id { get; set; }
          public string FirstName { get; set; }
          public string LastName { get; set; }
          public string Title { get; set; }
          public string Department { get; set; }
          public string Remarks { get; set; }
      }

      接著,我們使用EF6進行數據持久化操作,我們知道EF的編程模式有3種:

      • Database First:數據庫先行
      • Model First:模型先行
      • Code First:代碼先行

      前面,我們已經定義數據傳輸對象Employee,但我們沒有定義數據表,所以我們將使用代碼先行(Code First)模型創建數據表。

      接下來,我們定義EmployeesContext類型,具體定義如下:

      /// <summary>
      /// Defines a DB context.
      /// </summary>
      public class EmployeesContext : DbContext
      {
          /// <summary>
          /// Initializes a new instance of the <see cref="EmployeesContext"/> class.
          /// </summary>
          public EmployeesContext()
              : base("name=EmployeesContext")
          {
          }
      
          /// <summary>
          /// Gets or sets the employees.
          /// </summary>
          /// <value>
          /// The employees.
          /// </value>
          public DbSet<Employee> Employees { get; set; }
      }

      在構造函數EmployeesContext()中,我們定義了數據庫連接的名稱為EmployeesContext,接下來,我們需要在Web.config文件中添加相應的數據庫連接,具體定義如下:

      <connectionStrings>
        <add name="EmployeesContext" providerName="System.Data.SqlClient" connectionString="Data Source=Your_DataSourceName;Initial Catalog= Your_DataBaseName;Integrated Security=True" />
      </connectionStrings>
      

      RESTful服務

      接下來,我們需要提供接口讓客戶端程序調用,所以,我們在Controller文件中創建REST API的web控件器EmployeesController,它繼承于ApiController并且定義方法GetEmployeesBy()和PutEmployee(),具體定義如下:

      HTTP 動詞

      URI

      說明

      GET

      /api/employees

      獲取所有員工的列表

      GET

      /api/employees/{id}

      獲取 ID 等于 {id} 的員工信息

      PUT

      /api/employees/{id}

      更新 ID 等于 {id} 的員工信息

      POST

      /api/employees

      向數據庫添加新員工信息

      DELETE

      /api/employees/{id}

      從數據庫中刪除員工信息

      表1 REST API

      /// <summary>
      /// PUT api/Employees/30005
      /// </summary>
      /// <param name="id">The identifier.</param>
      /// <param name="employee">The employee.</param>
      /// <returns></returns>
      public async Task<IHttpActionResult> PutEmployee(int id, Employee employee)
      {
          if (!ModelState.IsValid)
          {
              return BadRequest(ModelState);
          }
      
          if (id != employee.Id)
          {
              return BadRequest();
          }
      
          db.Entry(employee).State = EntityState.Modified;
      
          try
          {
              await db.SaveChangesAsync();
          }
          catch (DbUpdateConcurrencyException)
          {
              if (!EmployeeExists(id))
              {
                  return NotFound();
              }
              // You can log the error.
              throw;
          }
          return Ok();
      }

      上面,我們實現了REST API提供了接口GetEmployeesBy()和PutEmployee(),客戶端通過將類型置于URI的查詢字符串中進行調用;例如,我們要獲取 IT部所有員工的信息,客戶端會發送Http GET請求/api/employees?department=IT,那么Web API將自動將查詢參數綁定到 GetEmployeesBy()方法中。

      也許有人會疑問:“Web API是如何自動將查詢綁定到不同的API方法中的呢?”首先,我們要知道在客戶端是通過發送Http請求來調用Web API的,當我們的Web API接受到Http請求時,它會根據路由選擇來綁定具體的方法。

      接下來,讓我們看看默認路由方法的實現,具體定義如下:

      /// <summary>
      /// Registers the specified configuration.
      /// </summary>
      /// <param name="config">The configuration.</param>
      public static void Register(HttpConfiguration config)
      {
          // Web API configuration and services
          // Web API routes
          config.Routes.MapHttpRoute(
              name: "DefaultApi",
              routeTemplate: "api/{controller}/{id}",
              defaults: new { id = RouteParameter.Optional }
          );
      }

      在WebApiConfig類中,已經提供了默認的路由實現,當然我們也可以重新實現該方法,但是我們這里還是使用默認的路由方法。

      例如:客戶端發送Http請求/api/employees?department=IT,路由選擇會到EmployeesController控制器中找參數是department的方法,最后綁定該方法調用。

      SPA5

      圖5 Http請求

      現在,我們已經實現了服務器端REST API了,接下來,我們將通過EF的Code First模式創建數據庫表。

      我們的程序使用是EF 6和Web API 5.0,我們可以在程序包管理控制臺中輸入以下命令進行安裝。

      • Install-Package Microsoft.AspNet.WebApi -Version 5.0.0
      • Install-Package EntityFramework -Version 6.0.2

      我們也可以使用Update-Package口令更新所有的包,Code First遷移有三個主命令,具體如下:

      • Enable-Migrations:啟用遷移。
      • Add-Migration:將根據自創建上次遷移以來您對模型所做的更改,為下一次遷移搭建基架。
      • Update-Database:將所有掛起的遷移應用于數據庫。

      當成功啟用數據遷移會在我們的項目中增加Migrations文件并且會在我們的數據庫中生成相應的數據庫表。

      SPA6

      圖6 數據遷移

      SPA7

      圖 7 Employees數據表

      前面,我們通過創建ASP.NET MVC應用程序來提供服務器端的API,接下來讓我們實現Ember客戶端吧,關于Ember入門可以參考這里。

      Ember應用程序

      首先,我們在application.js文件中創建一個Ember應用程序,具體定義如下:

      /// <summary>
      /// Create an ember application.
      /// </summary>
      window.App = Ember.Application.create({
          // For debugging, log the information as below.
          LOG_TRANSITIONS: true,
          LOG_TRANSITIONS_INTERNAL: true
      });

      Ember Model

      接著,我們需要在客戶端中創建一個數據存儲對象Employee,具體定義如下:

      /// <summary>
      /// Create an employee model.
      /// </summary>
      App.Employee = DS.Model.extend({
          Id: DS.attr(),
          FirstName: DS.attr(),
          LastName: DS.attr(),
          Title: DS.attr(),
          Department: DS.attr(),
          Remarks: DS.attr(),
      });

      在之前的部分中,我們已經定義了服務器端的數據模型Employee,由于RESTful服務只返回JSON格式的對象,為了方便把數據模型綁定到視圖中,我們需要在客戶端中定義一個與服務器端對應的Ember數據模型Employee。

      Ember Controller

      控制器定義在Scripts/app/controllers.js中,如果我們要表示單一的模型(單個Employee對象),那么我們可以繼承ObjectController。

      如果我們表示多模型(一系列Employee對象),那么就需要繼承ArrayController。

      /// <summary>
      /// To represent a collection of models by extending Ember.ArrayController.
      /// </summary>
      App.EmployeesController = Ember.ArrayController.extend();
      
      
      /// <summary>
      /// To represent a single model, extend Ember.ObjectController
      /// </summary>
      App.EmployeeController = Ember.ObjectController.extend({
      
          // Marks the model is edited or not.
          isEditing: false,
          // Binding corresponding event.
          actions: {
              edit: function() {
                  this.set('isEditing', true);
              },
              save: function() {
                  this.content.save();
                  this.set('isEditing', false);
              },
              cancel: function() {
                  this.set('isEditing', false);
                  this.content.rollback();
              }
          }
      });

      上面,我們定義了兩個控制器分別是EmployeeController和EmployeesController,在EmployeesController中,我們實現了事件處理方法;當用戶點擊保存時調用save()方法,接著,我們需要定義EmployeeAdapter對象序列化數據,并且調用Web API的方法進行保存。

      /// <summary>
      /// Create a custom adapter for employee, it will invoke our web api.
      /// </summary>
      App.EmployeeAdapter = DS.RESTAdapter.extend({
          // Override how the REST adapter creates the JSON payload for PUT requests.
          // Of course, we can use other verbs POST, DELETE and so forth.
          updateRecord: function(store, type, record) {
              var data = store.serializerFor(type.typeKey).serialize(record);
              return this.ajax(this.buildURL(type.typeKey, data.Id), "POST", { data: data });
          },
          namespace: 'api'
      });

      我們實現了updateRecord()方法,獲取用戶提交的數據進行序列化,然后調用Web API進行保存。

      Ember Route

      路由定義在Scripts/app/routes.js中,這里我們定義了departments和about的路由。

      /// <summary>
      /// Defines departments and about router.
      /// </summary>
      App.Router.map(function() {
          this.route('about');
          this.resource('departments', function() {
              // The employees router under department.
              this.route('employees', { path: '/:department_name' });
          });
      });

      Ember Template

      我們知道Ember使用Handlebars模板引擎,那么我們定義的模板是基于Handlebars語法的,如果大家有使用過jQuery模板或其他腳本模板,那么對于掌握handlebars.js的使用就沒有太大的困難了,如果確實沒有使用過也不用擔心,因為handlebars.js的使用也是挺簡單的。

      首先,我們定義了6個模板,它們分別是application、about、departments、departments/employees、_employees和error。

      application.hbs:當應用程序啟動時默認加載的模板。

      about.hbs:為“/about”路由的模板。

      departments.hbs:為“/departments”路由的模板,顯示部門導航條。

      departments/employees.hbs:為“/departments/employees”路由的模板,根據部門獲取所有用戶信息。

      _employees:現在每個用戶信息的模板,這里我們要注意模板名開頭的下劃是有意義的,因為我們使用了partial來渲染_employees,簡單來說,接收一個模板作為其參數,然后恰當地渲染這個模板(具體請參考這里)。

      error:是現在一些錯誤信息的模板。

      SPA10

      圖 8 程序界面設計

      <!-- application START -->   
       <script type="text/x-handlebars" data-template-name="application">
            <div class="container">    
               <h1>Ember SPA Demo</h1>    
                <div class="well">
                    <div class="navbar navbar-static-top">
                        <div class="navbar-inner">
                            <ul class="nav nav-tabs">
                                <li>{{#linkTo 'departments'}}Departments{{/linkTo}} </li>
                                <li>{{#linkTo 'about'}}About{{/linkTo}} </li>
                            </ul>
                        </div>
                    </div>
                </div>
                <div class="container">
                    <div class="row">{{outlet}}</div>
                </div>
            </div>
      
            <div class="container">
                <p>&copy;2013 Jackson Huang</p>
            </div>
        
        </script>
       <!-- application END -->   
      
       <!-- about START -->   
       <script type="text/x-handlebars" data-template-name="about">
            <div class="container"></div>
            <h3>Ember SPA Demo</h3>
        </script>
       <!-- about END -->   
      
       <!-- departments START -->   
       <script type="text/x-handlebars" data-template-name="departments">
            <div class="span2">
                <div class="navbar">
                    <div class="navbar-inner">
                        <ul class="nav nav-stacked">
                            {{#each item in model}}
                   
                            <li>{{#linkTo 'departments.employees' item}}{{item.name}}{{/linkTo}}</li>
                            {{/each}}
               
                        </ul>
                    </div>
                </div>
            </div>
            <div class="span8">{{outlet}}</div>
        </script>
       <!-- departments END -->   
      
       <!-- departments/employees START -->   
       <script type="text/x-handlebars" data-template-name="departments/employees">{{partial "employees"}}</script>
       <!-- departments/employees END -->   
      
       <!-- _employees START -->   
       <script type="text/x-handlebars" data-template-name="_employees">
            {{#if model}}
            <table class="table table-bordered table-condensed" >
                <thead>
                    <tr><th>FirstName</th><th>LastName</th><th>Department</th><th>Title</th><th>Remarks</th></tr>
                </thead>
                <tbody>
                {{#each employee in model itemController="employee"}}
                    <tr>
                        {{#if employee.isEditing}}
                        
                        <td>{{input type="text" value=employee.FirstName }}</td>
                        <td>{{input type="text" value=employee.LastName}}</td>
                        <td>{{view Ember.Select class="input-small" contentBinding="App.EmployeeController.departments" valueBinding="employee.Department"}}</td>
                        <td>{{input type="text" value=employee.Title }}</td>
                        <td>{{input type="text" value=employee.Remarks }}</td>
                        <td>
                            <button class="btn" {{action 'save'}}>Save</button>
                            <button class="btn" {{action 'cancel'}}>Cancel</button>
                        </td>
      
                        {{else}}
      
                        <td>{{employee.FirstName}}</td>
                        <td>{{employee.LastName}}</td>
                        <td>{{employee.Department}}</td>
                        <td>{{employee.Title}}</td>
                        <td>{{employee.Remarks}}</td>
                        <td>
                            <button class="btn" {{action 'edit'}}>Edit</button>
                        </td>
                        {{/if}}
                        </tr>
                {{/each}}
                </tbody>
            </table>
            {{else}}
            <p>No matches.</p>
            {{/if}}
        </script>
       <!-- _employees END -->   
      
       <!-- error START -->   
       <script type="text/x-handlebars" data-template-name="error">
              <h1>Error</h1>
              <h2>{{status}}.. {{statusText}}</h2>
       </script>
       <!-- error END –>   
      上面,我們分別定義了application、about、departments、departments/employees、_employees和error,其中,在departments/employees模板中,通過partial方法把模擬通過參數的形式傳遞給_employee模板。

       SPA9        

      圖 9程序界面

      現在,我們已經完成了Ember單頁面應用程序,這里我想大家推薦一個好用Chrome插件Ember Inspector,通過它我們可以更加容易理解Ember的模板,路由和控制之間的關系,從而提高我們的開發效率。

      1.1.3 總結

      我們通過一個單頁面應用程序的實現介紹了Ember和Web API的結合使用,其實,Ember中控制器、視圖、模型和路由的概念和ASP.NET MVC非常相似,如果我們有ASP.NET MVC編程經驗,那么對于掌握Ember的使用就沒有太多的困難,本文僅僅是介紹關于Ember.js一些基礎知識,如果大家想進一步學習,推薦大家到官方論壇學習或參考相應的文章。

      最后,祝大家新年快樂,身體健康,闔家幸福,Code with pleasure。

      參考

      posted @ 2013-12-31 21:26  JK_Rush  閱讀(27392)  評論(6)    收藏  舉報
      主站蜘蛛池模板: 国产免费一区二区不卡| 激情综合网五月婷婷| 另类 专区 欧美 制服| 7m精品福利视频导航| 国产av日韩精品一区二区| 国产精品午夜福利精品| 久久成人 久久鬼色| 亚洲av激情久久精品人| 国产精品天干天干综合网| √天堂资源地址在线官网| 亚洲天堂成人一区二区三区| 亚洲一区二区三区啪啪| 积石山| 久久久久久国产精品美女| 天天做日日做天天添天天欢公交车| 2021亚洲爆乳无码专区| 亚洲av无码国产在丝袜线观看| 麻豆最新国产AV原创精品| 久久精品国产蜜臀av| 亚洲色最新高清AV网站| 红杏av在线dvd综合| 精品人妻二区中文字幕| 久99久热免费视频播放| 17岁日本免费bd完整版观看| 蜜桃av无码免费看永久| 中文字幕在线精品人妻| 久久精品亚洲精品国产色婷| 国产精品自偷一区在线观看| 熟女一区二区中文字幕| 日本高清视频网站www| 丰满岳乱妇久久久| 青青草原国产精品啪啪视频| 成av免费大片黄在线观看| 国产盗摄xxxx视频xxxx| 女人被狂躁c到高潮喷水一区二区| 熟女精品色一区二区三区| 亚洲人亚洲人成电影网站色| 国产99青青成人A在线| www国产精品内射熟女| 另类 专区 欧美 制服丝袜| 麻豆一区二区三区精品视频|