前端开发思惟转变——从事件驱动到数据驱动

加班加点连续一个多月,总算是快把一个开始时内心彻底没有底的项目收工了。新项目基于旧系统开发,在保留原有老架构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
        },
    }
}
相关文章
相关标签/搜索