Part 6: 新建任務列表

z.w發表於2015-01-15

準備

開始本教程之前,你需要了解以下幾點:

  • alexyoung / dailyjs-backbone-tutorial提交到了82fe08e版本
  • 第二部分中的API key
  • 第二部分中的“Client ID”
  • 更新app/js/config.js成你自己的key(如果你檢出了我的程式碼)

要檢出原始碼,請執行以下命令(或用Git GUI工具):

git clone git@github.com:alexyoung/dailyjs-backbone-tutorial.git
cd dailyjs-backbone-tutorial
git reset --hard 82fe08e

獲取任務列表的CRUD

本系列教程的最後幾部分將講講Google’s Tasks API和OAuth認證。到現在,你應該能夠登入並檢視任務列表。

你已經看到,我們用Backbone.js使用RESTful API來實現CRUD(create建立,read讀取,update更新和delete刪除)。在Part 4已經瞭解怎樣自定義一個Backbone.sync方法使用Google’s APIs,我們只用gapi.client.tasks實現了一個read(讀取)功能

現在我們就要實現CRUD的所有操作來管理我們的任務列表。Part 4我們知道Google’s Tasks API 與Backbone的method對應關係:

Google Tasks API    Backbone.sync方法           解釋
insert                create                     新建一個task
update                update                     更新已存在一個task
delete                delete                     刪除一個task
list                read                     獲取task列表

在這部分我們將新增“create”,基本實現和“read”類似。

新建任務列表

為了建立列表,需要幾個新的元件:

  1. 新建按鈕
  2. 表單模板
  3. 新建和編輯的檢視
  4. 控制器程式碼

Backbone.js裡模型和集合可以廣播事件。當一個新的model被新增到TaskLists集合中事,我們需要觸發相應的事件來管理任務列表檢視

在Backbone.js裡通過利用事件是一件值得推薦的好程式設計方式。

Backbone.sync

之前Backbone.sync實現了通過Google’s API讀取任務列表。我們只需用把讀取那段程式碼稍微擴充套件下就可以實現新建。

回到app/js/gapi.js檔案,修改Backbone.sync方法,通過呼叫gapiRequest來實現create:

Backbone.sync = function(method, model, options) {
  var requestContent = {};
  options || (options = {});

  switch (method) {
    case 'create':
      requestContent['resource'] = model.toJSON();
      request = gapi.client.tasks[model.url].insert(requestContent);
      Backbone.gapiRequest(request, method, model, options);
    break;

是不是和read的程式碼看起來差不多,只是我們使用了Backbone.gapiRequest來處理單個的資源。完整的這個方法的程式碼如下:

Backbone.gapiRequest = function(request, method, model, options) {
  var result;
  request.execute(function(res) {
    if (res.error) {
      if (options.error) options.error(res);
    } else if (options.success) {
      if (res.items) {
        result = res.items;
      } else {
        result = res;
      }
      options.success(result, true, request);
    }
  });
};

Google’s API會返回一個陣列或者一個簡單的物件,值得我們注意的是:Backbone.sync是作為Backbone物件屬性可以是用來設定模型的屬性的。當success成功的回撥接收到result,這個結果的模型會生成一個id屬性。Backbone會自動的給模型設定上id屬性。

模板修改

修改app/js/templates/app.html,把下面的div放到signed-in-container``div裡:

<ul class="nav nav-tabs" id="top-nav">
  <li class="buttons">
    <div class="btn-group">
      <a href="#" class="btn" id="add-list-button"><i class="icon-plus">Add List</i></a>
      <a href="#" class="btn" id="edit-list-button"><i class="icon-cog">Edit List</i></a>
      <a href="#" class="btn delete-list" id="delete-list-button"><i class="icon-trash">Delete List</i></a>
    </div>
  </li>
</ul>
<div id="content-container">
  <div id="list-editor"></div>
  <div id="tasks-container"></div>
</div>

這個模板你回發現有個“新增任務” 按鈕,點選這個按鈕我們應該給有一個用於新增/編輯的form表單,所以我們還需要新建一個表單模板app/js/templates/lists/form.html

<fieldset>
  <legend>
    <span class="form-title">Edit List</span>
    <a href="#" class="pull-right delete-list btn"><i class="icon-trash"></i></a>
  </legend>
  <div class="control-group">
    <label class="control-label" for="list_title">Title</label>
    <div class="controls">
      <input type="text" class="input-xlarge" name="title" id="list_title" value="" placeholder="The list's title">
    </div>
  </div>
</fieldset>
<div class="form-actions">
  <button type="submit" class="btn btn-primary">Save Changes</button>
  <button class="cancel btn">Close</button>
</div>

我們可以看到變數插值,將用於新增和編輯任務。

新增和編輯檢視

因為“add”和 “edit” 檢視的區別並不是太大,他們可以共用一個form.html模板,所以我們只需 在app/js/views/lists/edit.js新加一個檢視:

define(['text!templates/lists/form.html'], function(template) {
  var EditListView = Backbone.View.extend({
    tagName: 'form',
    className: 'form-horizontal well edit-list',
    template: _.template(template),

    events: {
      'submit': 'submit'
    , 'click .cancel': 'cancel'
    },

    initialize: function() {
      this.model.on('change', this.render, this);
    },

    render: function() {
      var $el = $(this.el);
      $el.html(this.template(this.model.toJSON()));

      if (!this.model.get('id')) {
        this.$el.find('legend').html('Add List');
      }

      return this;
    },

    submit: function() {
      var self = this
        , title = this.$el.find('input[name="title"]').val()
        ;

      this.model.save({ title: title }, {
        success: function() {
          self.remove();
        }
      });

      return false;
    },

    cancel: function() {
      this.$el.hide();
      return false;
    }
  });

  return EditListView;
});

在這個類裡面,我們給提交和關閉表單繫結了相應的處理函式,而且初始化的時候,我們給模型繫結了change事件觸發render,所以模型修改的時候會自動重繪。

render函式中,當模型的id不存在時,會改變表單legend的值為新建,當id存在時則將顯示為其他並顯示刪除按鈕。

對比的我們看下新建任務的app/js/views/lists/add.js檔案:

define([
'models/tasklist'
, 'views/lists/edit'
],

function(TaskList, EditListView) {
var AddListView = EditListView.extend({
  submit: function() {
    var self = this
      , title = this.$el.find('input[name="title"]').val()
      ;

    this.model.save({ title: title }, { success: function(model) {
      // Add the updated model to the collection
      bTask.collections.lists.add(model);
      self.remove();
    }});

    return false;
  }
});

return AddListView;
});

這個檔案裡面,我們用RequireJS載入了依賴EditListView,並繼承了EditListView檢視,與編輯不同的只是我們表單submit方法做的事情不一樣,當任務新建時,success成功回撥後會更新模型,將這個模型新增到全域性的lists集合中。這個表單自身會被刪除掉。

新建任務按鈕

很早之前我們就在app.html模板中就有一個新增任務的連結,現在只需在app/js/views/app.js新增一個addList函式:

addList: function() {
  var list = new bTask.collections.lists.model({ title: '' })
    , form = new AddListView({ model: list })
    , self = this
    ;

  this.$el.find('#list-editor').html(form.render().el);
  form.$el.find('input:first').focus();

  return false;
}

要通過AddListView模板顯示標題欄位,所以我們還需要在檔案頭部加上依賴檔案AddListView

define([
  'text!templates/app.html'
, 'views/lists/add'
],

function(template, AddListView) {

最後,在AppView加上事件繫結:

events: {
  'click #add-list-button': 'addList'
},

總結

enter image description here

執行伺服器node server,訪問http://localhost:8080,你可以看到新建任務的表單。暫時這個看起來沒那麼好看,不過很快就變號了。

教程中完整的程式碼可以在這裡找到:alexyoung / dailyjs-backbone-tutorial, commit 465523f

相關文章