iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 9
0

昨天說功能加越多網頁會越來越難管理有以下原因

  1. Server 用 API 溝通時要一直去翻 DOM 裡面的資料,大部分的時間會做 DOM 轉換成 object 的處理
  2. 檔案越寫越亂,到底這個 code 是在新增還是讀取都混在一塊
  3. 修改新增功能都在同個檔案查找,檔案越來越大

依照昨天寫的 code View 跟 Data(Model) 都綁在 View 上,所以維護和加新功能會比較麻煩,那如果試試看用頁面上的 MVC 看能不能改善

這邊的 MVC 跟傳統網頁的在講得有一點不一樣,不過暫時找不到合適的名詞,而邏輯上差不多,所以姑且稱之為 MVC

Model

資料的模型,在這邊通常是 API 或 TodoList 上的物件

Controller

業務邏輯,可以將 model 的 data 印在模板上,當使用者對 UI 進行操作,Controller 會對 Model 進行更改,因為 Model 更新了 Controller 也會對 View 進行更新

View

有著 template 模板樣式,讓 Controller 可以簡單的使用它來做 Render

TodoList

以這個為例 code

Model


var data = [];
function TodoItem(content, check) {
  this.content = content;
  this.check = Boolean(check);
  this.time = new Date();
};

TodoItem.prototype.getTime = function() {
  return this.time.toDateString();
};

TodoItem.prototype.toggle = function () {
  return this.check = !this.check;
};

做了一個 TodoItem 的類別有什麼新的待辦事項就往 data 塞
那這個 data 就是我們的 Model 了

View

很簡單的模板做法

var view = '<li class="{{check}}" data-i="{{i}}"><span class="todo-content">{{content}}</span><span class="close">x</span></li>';

用了類似 mustache 的做法,有了這個 template 我們只要修改它, controller 就很簡單的更改了!

Controller

function TodoController({ view, data, bindId }) {
  this.data = data;
  this.view = view;
  this.element = document.querySelector(bindId);
}

TodoController.prototype.addTodo = function(content, checked) {
  this.data.push(new TodoItem(content, checked))
  this.render();
}

TodoController.prototype.deleteItem = function (index) {
  this.data.splice(index, 1);
  this.render();
}

TodoController.prototype.checkItem = function (index) {
  this.data[index].toggle();
  this.render();
}

TodoController.prototype.render = function () {
  var renderViewText = this.view,
      i,
      length = this.data.length,
      item,
      checkValue
      resultView = '';

  this.empty();

  // set values, skip sanitize text for now...
  for (i = 0; i < length; i += 1) {
    item = this.data[i];
    renderViewText = this.view;
    checkValue = item.check ? 'checked' : '';
    renderViewText = renderViewText.replace('{{check}}', checkValue);
    renderViewText = renderViewText.replace('{{content}}', item.content);
    renderViewText = renderViewText.replace('{{i}}', i);
    resultView += renderViewText;
  }
  this.element.innerHTML = resultView;
}

TodoController.prototype.empty = function () {
  while (this.element.firstChild) {
    this.element.removeChild(this.element.firstChild);
  }
}

TodoController.prototype.registerEvent = function (eventType, callback) {
  if (typeof callback === 'function') {
    this.element.addEventListener(eventType, callback, false);
  }
}

Controller 只是我做出的概念想法,所以要讓他壞掉也是很容易的!
Controller 會在每次物件被更新的時候,將整個列表做更新
在 render 的 function 剛開始跑 empty 的 method,有注意到這麼使用 while loop 一個一個把 firstChild 移除 jsperf 說這樣比較快 就跟著做(有興趣可以自己試試看,哪個比較快!)

接下來把 data 跑過一遍然後產生出要 render 的 string

眼尖的朋友有沒有發現,雖然這樣 code 很好讀,也很直覺,但是 render function 直覺看一定沒有先前寫的速度快,這邊想要晚點回來研究探討


上一篇
Day08 - 在 TodoList 上加新功能
下一篇
Day-10 - 聽說以前都是這樣做模組,今天來踩踩地雷
系列文
認真學前端開發 - 以 TodoList 為例30

尚未有邦友留言

立即登入留言