前端開發思惟轉變——從事件驅動到數據驅動

加班加點連續一個多月,總算是快把一個開始時內心徹底沒有底的項目收工了。新項目基於舊系統開發,在保留原有老架構jade + knockout + jquery + gulp的同時,新頁面徹底採用vue + vue-route + vuex + webpack。兩套框架都沒正兒八經作過,jade和knockout第一次接觸,vue和webpack之前只是寫寫demo,vue-route和vuex也沒用過,又恰巧另一個前端同事離職,因此當時決定新頁面徹底用新框架的時候,仍是鼓了很多勇氣的。前端

趁熱打鐵,梳理下這段時間學習和使用vue之後,給本身最大的收穫:開發思惟轉變vue

事件驅動

先說說之前前端發開的思惟方式。
好比說,要實現ajax方式提交一個表單,那麼就要監聽一個提交按鈕的事件。在觸發點擊事件後,從頁面的DOM元素中一個個收集數據,而後在作數據處理,最後調用接口提交。收集數據是個特別繁瑣的事情,各類選擇器各類變量。jquery

再好比說,在固定區域內,事件觸發展現不一樣組件,那就要監聽事件傳遞來的條件,來判斷哪一個組件要display:block,其餘組件要display:none,甚至可能大量用到DOM操做,各類appendChild,insertBefore,removeChild。webpack

其餘相似根據條件addClass, removeClass調整組件樣式;經過getAttribute、dataset等等獲取DOM綁定的數據;經過setAttribute、innerHtml等等直接修改DOM的操做也是數不勝數。web

我的感受這種方式的好處就是直觀,頁面作任何改變全交由js處理,先幹什麼後幹什麼都由本身一手代碼操控全場,有種掌控一切的感受。ajax

可是,大型項目裏,代碼編寫的成本和維護的成本都很高。對代碼規範的要求高,對抽象的要求高,尤爲是抽象程度,全賴我的編程水平,抽象程度低的話,冗長的代碼根本不想多看一眼。這大概就是爲啥項目裏有一個代碼寫的爛的人在,代碼就會愈來愈爛的緣由。vuex

數據驅動

網上已經不少關於數據驅動的文章了,但光看文章,體會遠不如本身實踐一遍來的印象深入。在基於vue開發的新頁面中,用js直接處理DOM的代碼極少(剛開始上手的時候通常都會不太習慣數據驅動編程,寫些操做DOM的代碼,後來慢慢會替換掉的)。編程

數據驅動的前提是事先將DOM與數據綁定,像vue這種就是依賴defineProperties, setter, getter將一個vue對象與一個DOM節點模板關聯起來,這個DOM節點裏全部子節點、全部節點屬性,全均可以和vue對象中的data綁定,作到data中某個屬性值變化時,相應DOM節點中對應的某個屬性就變化。gulp

如此一來,關注點徹底分離。分開設計頁面DOM結構和數據結構,而後將DOM與數據結構作關聯,以後全部的事件觸發的都只是數據的變化,DOM會自動根據數據的變化作相應改變。後端

前面例子中的表單提交,交由v-model屬性將input雙向綁定到data中去,在觸發表單提交時,直接把data傳給後端完事兒了;不一樣組件之間的切換,vue官網就有個動態組件的例子:

var vm = new Vue({
  el: '#example',
  data: {
    currentView: 'home'
  },
  components: {
    home,
    posts,
    archive
  }
})

<component v-bind:is="currentView">
  <!-- 組件在 vm.currentview 變化時改變! -->
</component>

只需關心currentView的指向即可輕易切換組件,或者經過v-if或v-show來實現根據value的真假值來控制相應DOM節點是否顯示;其餘DOM屬性變化均可以用v-bind與data作綁定,好比v-bind:class="dataClass",只要dataClass一變化,DOM的class就會改變。

vue的這些動態綁定的功能很容易上手,相對上手比較慢的是vue提供的組件功能,涉及父子組件通信,以及用vuex實現全局state管理等等,先掌握數據驅動的思想,再接觸這些會容易得多。

固然即便vue也會遇到不得不直接操做DOM的狀況。記錄一個目前遇到實際問題:

有一個table組件,展現從後臺傳過來的數據。數據中會有"http://xxx.xxx/xxx.png"須要渲染成<img src="http://xxx.xxx/xxx.png">標籤。通常表格組件會提供formatter方法來處理單元格特殊處理邏輯,這裏我就不得不直接生成DOM節點

formatter: function({picUrl}){
    this.$createElement('img', {
        attrs: {
            src: picUrl
        },
    }
}
相關文章
相關標籤/搜索