03 September 2014

在经典的MVC架构模式中,前端的东西(html,css,javascript)都属于一个大view中,因此我们要更加深入的拆分javascript做的事情,使得js在各段位置中的职责更加清晰。
比如说数据校验,数据存储可以抽象成前端这个层面的model;
参数解析,数据和表现的组合,逻辑跳转等可以抽象成前端这个层面的controller;
css,html模板,事件绑定等可以抽象成前端这个层面的view。

传统组件开发模式:

我们往往会像下面这段代码一样去开发一个js组件

var newComponent = Class({
    init : function(cfg) {
        var defaults = {};
        cfg = $.extend({},defaults,cfg);
        this.renderUI();
        this.bindEvents();
    },
    // 绘制UI
    renderUI : function() {
        var htmlStr = itpl(tpl,data);
        $('body').append(htmlStr);
    },
    // 事件绑定
    bindEvents : function() {
        var handleEvent = this.handleEvent;
        cfg.el.on('click',handleEvent);
        cfg.el.on('mouseenter',handleEvent);
        ...
    },
    // 事件处理
    handeEvent : function(e) {
        switch (e.type) {
            case : 'click' : this._onClick();
                break;
            case : 'mouseenter' : this._onMouseEnter();
        }
    },
    _onClick : function() {
        ...
    },
    _onMouseEnter : function() {
        ...
    },
    // 销毁,释放内存
    destory : function() {
        ...
    }

})

大致上看我们每开发一个组件,都会有init,bindEvents,handleEvent,renderUI,destory这些方法,使用这种命名及代码结构,肯以让我们清晰的知道这个组件有哪些内容。当A写了这样一个组件,B去修改时,往往从bindEvents方法中去顺推着往下找就可以很轻松的找到需要修改的代码。这样写非常好阿,代码职责也很清晰,那又有什么问题呢?
1.依赖于JQUERY之类的框架操作DOM,以至于造成代码臃肿,不利于维护
2.renderUI中,数据往往和视图模板耦合在一起,代码职责不清晰。
3.类似于这样的命名方式,往往依赖于前端小组内的代码规范,不同团队,可能规范不一样,跨团队的前端代码维护起来也会非常的麻烦。即使是统一小组内,也有可能会有不遵守代码规范的情况,使用命名,约定,结构的方法去规范前端代码始终不是上乘之道。

MVC组件开发(解决方案):

jsMVC分解原则

数据校验,数据存储可以抽象成前端这个层面的model;
参数解析,数据和表现的组合,逻辑跳转等可以抽象成前端这个层面的controller;
css,html模板,事件绑定等可以抽象成前端这个层面的view。

依据上面的原则,我们来看angular.js是如何划分一个MVC的组件结构,前端MVC组件方案是否可行?
html:

<ul class="list-group">
  <li class="list-group-item repeat" ng-repeat="item in vm.items">

    <button type="button" class="close" ng-click="vm.delItem($index)">&times;</button>
  </li>
</ul>
<button class="btn btn-default mmm" ng-click="vm.addItem()">添加一条</button>

css:

/*给repeat中的enter和leave事件添加基础动画*/
.repeat.ng-enter,
.repeat.ng-leave {
  -webkit-transition: 0.5s linear all;
  transition: 0.5s linear all;
}

.repeat.ng-enter,
.repeat.ng-leave.ng-leave-active {
  opacity: 0;
}

.repeat.ng-leave,
.repeat.ng-enter.ng-enter-active {
  opacity: 1;
}

js:

angular.module('ngShowcaseApp').controller('ctrl.animation.basic', function ($scope) {
  var vm = $scope.vm = {};

  vm.items = ['item1', 'item2'];
  vm.itemId = 3;

  vm.addItem = function() {
    vm.items.push('item' + vm.itemId);
    vm.itemId++;
  };

  vm.delItem = function(index) {
    vm.items.splice(index, 1);
  };
});

依据angular的这个实现Demo,我们可以看到,事件绑定,UI渲染被牢牢的控制在view层,数据和逻辑控制被解耦在了angular提供的controller里。模块与模块之间又被module所区分,这样的代码职责清晰,且利于维护。

当然了,在前端领域性能也是一个非常重要的考量维度,当页面的数据操作不多,就不建议使用angular这样的MVVM框架了,毕竟angular的代码已经上W行了。

希望这篇文章能对你有用,和我一起交流~