Part 10: 任務項新增、修改和切換狀態
準備
開始本教程之前,你需要了解以下幾點:
- alexyoung / dailyjs-backbone-tutorial提交到了
0491ad
版本 - 第二部分中的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 0491ad
任務項
如圖所示任務項的相關功能介面
可以看到我們還有很多功能要實現,現在我們只是實現了任務項列表,還沒有實現互動,下面將分幾個小節來實現:
- 新增任務項
- 編輯任務項
- 刪除任務項
- 切換任務項狀態
大部分的內容其實我們在實現任務列表的時候都已經講到過了,這部分只是帶大家鞏固下Backbone一下用法。
新增任務項
在app/js/views/tasks/index.js
中,確定我們有一個addTask
事件:
events: {
'submit .add-task': 'addTask'
},
在initialize
方法中,新增監聽到這個類的集合
initialize: function() {
this.children = [];
this.collection.on('add', this.renderTask, this);
},
這樣就實現了當我們集合中有新任務項被新增的時候會自動渲染任務項列表。
addTask
函式裡會使用Task.prototype.save
中的Google’s API來實現任務項儲存到服務端,成功回撥後會新增任務項到集合中,這樣就實現了新任務項的顯示,預設我們新增了Google’s Tasks指定的引數{ at: 0}
是讓新任務項顯示在最前面,當然這需要連網支援,也可以先儲存到本地然後同步到Google,但這個不是我們的重點。
addTask: function() {
var $input = this.$el.find('input[name="title"]')
, task = new this.collection.model({ tasklist: this.model.get('id') })
, self = this
;
task.save({ title: $input.val() }, {
success: function() {
self.collection.add(task, { at: 0 });
}
});
$input.val('');
return false;
},
renderTask: function(task, list, options) {
var item = new TaskView({ model: task, parentView: this })
, $el = this.$el.find('#task-list');
if (options && options.at === 0) {
$el.prepend(item.render().el);
} else {
$el.append(item.render().el);
}
this.children.push(item);
},
renderTask
方法裡有個option
引數主要是用來確定如何將任務項新增到列表中,如果我們不想讓新新增的任務項到最前面,我們就可以重構下render
如下:
render: function() {
this.$el.html(this.template());
var $el = this.$el.find('#task-list')
, self = this;
this.collection.fetch({ data: { tasklist: this.model.get('id') }, success: function() {
self.collection.each(function(task) {
task.set('tasklist', self.model.get('id'));
self.renderTask(task);
});
}});
}
開啟app/js/views/lists/menuitem.js
,修改open
方法,通過Tasks
集合來例項化bTask.views.tasksIndexView
檢視:
bTask.views.tasksIndexView = new TasksIndexView({
collection: new Tasks({ tasklist: this.model.get('id') }),
model: this.model
});
然後在define
中加入Tasks
:
define(['text!templates/lists/menuitem.html', 'views/tasks/index', 'collections/tasks'],
function(template, TasksIndexView, Tasks) {
要使得Google’s API可以起作用,我們還需要修改下app/js/gapi.js
,給requestContent
新增tasklist
ID:
Backbone.sync = function(method, model, options) {
var requestContent = {};
options || (options = {});
switch (model.url) {
case 'tasks':
requestContent.task = model.get('id');
requestContent.tasklist = model.get('tasklist');
break;
新增任務項到這裡就已經OK了,這裡我們沒有新建模板是因為我們在其他部分已經寫過了。
編輯任務項
要實現編輯任務項,我們需要:
- 一個表單模板
- 一個Backbone.View
- 儲存時的觸發事件
新建一個表單模板app/js/templates/tasks/edit.html
:
<fieldset>
<legend>
Task Properties
<a href="#" data-task-id="" class="pull-right delete-task btn"><i class="icon-trash"></i></a>
</legend>
<div class="control-group">
<label for="task_title">Title</label>
<input type="text" class="input-block-level" name="title" id="task_title" value="" placeholder="The task's title">
</div>
<div class="control-group">
<label class="radio"><input type="radio" name="status" value="needsAction" > Needs action</label>
<label class="radio"><input type="radio" name="status" value="completed" > Complete</label>
</div>
</div>
<div class="control-group">
<label for="task_notes">Notes</label>
<textarea class="input-block-level" name="notes" id="task_notes" placeholder="Notes about this task"></textarea>
</div>
</fieldset>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save Changes</button>
<button class="cancel btn">Close</button>
</div>
模板中我們使用了Bootstrap一些標籤和樣式,這樣能好看些。
相應的檢視app/js/views/tasks/edit.js
如下:
define(['text!templates/tasks/edit.html'], function(template) {
var TaskEditView = Backbone.View.extend({
tagName: 'form',
className: 'well edit-task',
template: _.template(template),
events: {
'submit': 'submit'
, 'click .cancel': 'cancel'
},
initialize: function() {
this.model.on('change', this.render, this);
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
submit: function() {
var title = this.$el.find('input[name="title"]').val()
, notes = this.$el.find('textarea[name="notes"]').val()
, status = this.$el.find('input[name="status"]:checked').val()
;
this.model.set('title', title);
this.model.set('notes', notes);
if (status !== this.model.get('status')) {
this.model.set('status', status);
if (status === 'needsAction') {
this.model.set('completed', null);
}
}
this.model.save();
return false;
},
cancel: function() {
this.remove();
return false;
}
});
return TaskEditView;
});
表單提交的時候我們觸發submit
方法,關閉的時候我們會有相應的cancel
方法。
在app/js/views/tasks/index.js
中新增一個方法,來例項化TaskEditView
:
editTask: function(task) {
if (this.taskEditView) {
this.taskEditView.remove();
}
this.taskEditView = new TaskEditView({ model: task });
this.$el.find('#selected-task').append(this.taskEditView.render().el);
}
保證TaskEditView
載入:
define(['text!templates/tasks/index.html', 'views/tasks/task', 'views/tasks/edit', 'collections/tasks'],
function(template, TaskView, TaskEditView, Tasks) {
同時我們還要知道修改的是哪個任務項例項,所以把如下程式碼加app/js/views/tasks/task.js
的open
方法中:
this.parentView.editTask(this.model);
寫兩個檢視之間有很多的耦合, 這樣TaskView
很難再服用,雖然看起來好像TasksIndexView
沒有用,這裡我們要怎麼才能寫出更易維護的Backbone程式碼,需要我們自己多思考下。
刪除任務項
在app/js/views/tasks/edit.js
檔案中新增destroy
方法:
destroy: function() {
this.model.destroy();
return false;
}
然後給帶垃圾桶圖示(類名為.delete-task
)的標籤繫結上這個方法,這樣當這個模型被刪除就可以觸發這個事件:
events: {
'submit': 'submit'
, 'click .cancel': 'cancel'
, 'click .delete-task': 'destroy'
},
initialize: function() {
this.model.on('change', this.render, this);
this.model.on('destroy', this.remove, this);
},
切換任務項狀態
我們有個帶圖示標籤用來切換任務項狀態,隨著這一變化,應用程式將真正看起來一個真正的待辦事項列表的應用程式了,開啟app/js/views/tasks/task.js
給列表的核取方塊新增一個叫change
的事件:
events: {
'click': 'open'
, 'change .check-task': 'toggle'
},
然後我們基於這個核取方塊的狀態通過toggle
方法來實現status
屬性的切換:
toggle: function() {
var id = this.model.get('id')
, $el = this.$el.find('.check-task')
;
this.model.set('status', $el.attr('checked') ? 'completed' : 'needsAction');
if (this.model.get('status') === 'needsAction') {
this.model.set('completed', null);
}
this.model.save();
return false;
}
依照Google針對任務項狀態的命名規範,還有completed
和needsAction
,如需瞭解更多的可以去看看文件。
總結
到這裡,我們要熟悉這些陌生的特性APIs需要很多耐心。如果你嘗試執行這個專案的程式碼,請確保你確實在Gmail裡有一些任務—如沒任務將執行不起來,這我還在之後修復這個它。
教程中完整的程式碼可以在這裡找到:alexyoung / dailyjs-backbone-tutorial, commit 0491ad
相關文章
- win10中word怎麼切換改寫狀態_win10怎樣切換插入狀態和改寫狀態Win10
- Part 9: 任務項
- Java執行緒狀態及切換Java執行緒
- 春節假期“清零”,任務管理飛項快速助你回到高效狀態
- win10修改輸入法切換方式 win10修改輸入法切換快捷鍵Win10
- 工作流從無狀態切換到有狀態的好處
- UCOSIII(1)——SVC與PenSV實現任務切換
- win10快捷鍵任務視角怎麼用_win10怎麼快捷鍵切換任務檢視Win10
- Elastic-Job:動態新增任務,支援動態分片AST
- UIButton三狀態切換小技巧(可擴充套件至更多狀態)UI套件
- 點選按鈕實現狀態切換效果
- 任務的分解綜合狀態與單據
- Part 6: 新建任務列表
- Java執行緒生命週期與狀態切換Java執行緒
- 物理dataguard 正常切換 角色轉換,switchover_status 狀態改變
- CSS3 tab選項卡動態切換CSSS3
- 基於websocket的celery任務狀態監控Web
- Part 7: 編輯任務列表
- Part 8: 刪除任務列表
- Part 5: 任務列表檢視
- 系統呼叫時為什麼發生任務切換?
- 【freertos】006-任務切換實現細節
- 物理dataguard 正常切換 腳色轉換,switchover_status 狀態改變
- 備庫的切換狀態為SWITCHOVER PENDING時進行dataguard主備庫角色切換
- 架構設計(五):有狀態服務和無狀態服務架構
- Locust 任務巢狀巢狀
- 從任務中心看狀態機功能元件設計元件
- flink學習(加餐)——job任務狀態變化
- Spring Boot整合quartz實現定時任務並支援切換任務資料來源Spring Bootquartz
- Flowable啟動流程例項和查詢任務以及完成任務
- jquery實現的class樣式類的新增和刪除切換程式碼例項jQuery
- [- Flutter 狀態篇 -] 主題色切換+國際化 三連Flutter
- Vim實戰手冊(2)常用的狀態切換按鍵
- [原始碼分析] 定時任務排程框架 Quartz 之 故障切換原始碼框架quartz
- 解密函式計算非同步任務能力之「任務的狀態及生命週期管理」解密函式非同步
- 測試庫採用DataGuard同步,狀態自動切換指令碼指令碼
- Input-Source-Pro:自動切換輸入法並提示狀態
- 動態切換JDK8和JAVA17JDKJava