前端編程提升之旅(六)----backbone實現todoMVC

            樂帝當年學習backbone時。最開始是看官網todoMVC的實現。後來瞭解到requireJS便於管理JS代碼。就對官網代碼作了requireJS管理。但此時樂帝感受此時的todoMVC仍然不夠簡明,爲了加深對MVC架構的理解。樂帝對原有appview代碼進行了重構,將相關顯示模塊單獨提取出自稱view。實現view原子化。樂帝已經將這個項目上傳(下載地址)。javascript

    增長requireJS的文件夾結構:html

   這裏主要用到templates用於放置view相應的模板。views則相應backbone中view文件。假設說backbone是前端MVC,那麼model是對數據創建模型。collection則是對model統一管理,view則起到控制器的做用,用於填充數據到模板,並渲染模板到顯示。model、collection起到M做用。view起到C的做用,模板則起到V的做用。前端

   而後咱們看一下todoMVC的效果圖:java



    從終於效果圖。咱們可以分析出,要對原有appview中解耦出原子view。就需要推斷出哪些是原子view。原子view需要具有兩點:jquery

  • 具備動態交互效果
  • 與其它頁面部分獨立
   固然這裏的原子view定義還值得商榷。樂帝依據以上兩個原則對view進行了又一次劃分。
   且看views文件夾結構:

   相應模板文件夾結構:
   需要注意的是,這裏appview並無相應的模板。而是經過設置el: "#todoapp",在index.html文件裏,統一對原子view進行管理。

   如下以ToggleAllView類源碼爲樣例,咱們分析下,原子view職能的組成:
define([
    'jquery',
    'underscore',
    'backbone',
    'text!templates/toggleAll.html'
], function($, _, Backbone, toggleTemplate) {
    var ToggleAllView = Backbone.View.extend({
        toggleTemplate: _.template(toggleTemplate),
        events: {
            "click #toggle-all": "toggleAllComplete"
        },
        initialize: function() {
            this.listenTo(this.collection, "all", this.render); //除了todoview與todomodel一一相應
            // 其它相關操做都會監聽collection
        },
        render: function() {
            this.$el.html(this.toggleTemplate());
            var done = this.collection.done().length;
            var remaining = this.collection.remaining().length;
            this.allCheckbox = this.$("#toggle-all")[0];
            this.allCheckbox.checked = !remaining;
            return this;
        },
        toggleAllComplete: function() {
            var done = this.allCheckbox.checked;
            this.collection.each(function(todo) {
                todo.save({
                    done: done
                });
            }); //這裏經過推斷單選框是否選中。改動所有modeldone屬性
        }

    });
    return ToggleAllView;
});

   上述代碼中職能主要有例如如下幾種:
  • 設置el或tagname,用於定義在上一層view放置的位置,或包裹的標籤
  • 設置相應模板(Template)
  • 定義交互事件,並連帶定義交互函數
  • 初始化函數(initialize),通常設置對collection或者model的監聽,用於view之間的通訊
  • 渲染函數(render),用於渲染數據到模板中。設置其它一些全局函數
   因而可知。原子view將職能劃分的很是清楚。這也是前端MVC架構的緣由,而不是以前純腳本時代,代碼間高度耦合。牽一髮而動全身。
   對於學習backbone,原子view和appview各自代碼都不難理解。難於理解或者它精妙之處,在於對事件的監聽機制,正是這樣的機制,處理了view之間的通訊,從而將鬆散的view拼裝成性能優良的整理。

   todoView的監聽:
initialize: function() {
            this.listenTo(this.model, "change", this.render);
            this.listenTo(this.model, "destroy", this.remove); //當模型被刪除,視圖對應被移除

        }

   這裏對每個todoview進行與之綁定的model數據監聽。改動,則又一次渲染;銷燬。則移除此todoview。

   再看ToggleAllView的監聽:
initialize: function() {
            this.listenTo(this.collection, "all", this.render); //除了todoview與todomodel一一相應
            // 其它相關操做都會監聽collection
        }

   這個監聽更「狠」。僅僅要collection有變更,就會又一次渲染,以達到實時交互的效果。

   那麼appview是怎樣管理各個子view的呢?
   且看兩個appview函數:
 initialize: function() {
      // 初始化加入各類視圖,新建視圖並加入到父視圖指定位置
      this.footer = this.$el.find('footer');
      this.main = $('#main');
      this.todoCollection = new todos;
      inputview = new InputView({
        collection: this.todoCollection
      });
      $("#todoapp").prepend(inputview.render().el); //加入輸入框

      var toggleAllview = new ToggleAllView({
        collection: this.todoCollection
      });
      this.main.prepend(toggleAllview.render().el); //取得數據後,再初始化
      this.allCheckbox = this.$("#toggle-all")[0];

      this.listenTo(this.todoCollection, "add", this.addOne);
      this.listenTo(this.todoCollection, "reset", this.addAll);
      this.listenTo(this.todoCollection, "all", this.render);
      // 需要數據的視圖。在獲取數據後定義
      this.todoCollection.fetch();
      // 狀態視圖
      statusview = new StatusView({
        collection: this.todoCollection
      });
      this.footer.append(statusview.render().el); //取得數據後,再初始化
    },
    render: function() {
      // 由於設置了all監聽所有collection的操做。故加入一個項就會被渲染一次,這保證了有修改都會獲得渲染到頁面
      var done = this.todoCollection.done().length;
      var remaining = this.todoCollection.remaining().length;
      this.allCheckbox = this.$("#toggle-all")[0];
      if (this.todoCollection.length) {
        //渲染時運行顯示或隱藏的代碼
         this.main.show();
         this.footer.show();
        this.footer.html();
        //假設collection爲空的話,則清空footer
      } else {
        this.main.hide();
        this.footer.hide();
      }
    }, // 實現整體顯示


   與原子view的差異,在於appview初始化函數除了監聽collection變化外。還初始化各個原子view,並加入到指定界面位置,同一時候渲染函數依據邏輯需要。渲染整個頁面。
   以上是對整個todoMVC程序的整體性架構分析。詳細交互細節可查看樂帝源碼。
相關文章
相關標籤/搜索