• MVVM框架 v1发布


    如果经常浏览我博客的人就发现,我三个月前就搞鼓过一下什么MVVM与MVC的比较,knockout.js与ember.js。然后就没动静了,因为之后一个月,我的MVVM就孵化出来,开发代码很逆天也很龌鹾,就叫avalon(WPF开发代号)。我觉得,都是好东西,相互借鉴是没所谓,只要造福IT民工!

    说说MVVM的重要性,它虽然是从MVC中衍生出来的,但其双向绑定机制是特有的,完全是面向界面开发而生,这是传统的MVC比不了。最近我拉了一伙人在搞我的mass UI就遇到这问题了。

    //由mass UI开发团队的Hodor 提供
    define('panel',[
        '$node',
        '$event',
        '$css',
        '$flow',
        './ejs'
    ], function(){
        $.ui = $.ui||{}
         var defaults = {
            showHead    : true,
            showFoot    : true,
            closeAble   : true,
            parent      : 'body',
            content     : {
                title       : 'title',
                body        : 'body',
                foot        : ''
            },
            css         : {
                width       : 400,
                height      : 200
            }
         };
        $.ui.Panel = $.factory({
            inherit: $.Flow,
            init: function(opts) {
                this.setOptions ("data", defaults, opts )
                var self = this;
                self.template = $.ejs.compile(
                    '<div class="panel_wrap">\
                        <% if( data.showHead ){ %>\
                            <div class="panel_header">\
                                <div class="panel_title">\
                                    <%= data.content.title %>\
                                </div>\
                                <% if( data.closeAble ){ %>\
                                <span class="panel_closer"></span>\
                                <% } %>\
                            </div>\
                        <% } %>\
                        <div class="panel_body">\
                            <%= data.content.body %>\
                        </div>\
                        <% if( data.showFoot ){ %>\
                            <div class="panel_foot">\
                                <%= data.content.foot %>\
                            </div>\
                        <% } %>\
                    </div>');
                self.show();
            },
            show : function() {
                this.fire ( 'beforeshow' )
                this.ui && this.ui.remove();
                this.ui = $(this.template( this.data ))
                    .appendTo( this.parent )
                    .css     ( this.css    )
                    .show    ();
                this.fire ( 'show' )
            },
            hide : function() {
                this.ui && this.ui.hide().remove();
                this.ui = undefined;
                this.fire ( 'hide' );
            },
            set : function( keyChain, val ) {//每改一个属性就重刷整个视图,因此不能容纳子控件,除非我们多做一些额外工作
                var keys = keyChain.split('.');
                var key;
                var ret = this;
                while( keys.length > 1){
                    key = keys.shift();
                    ret[key] = ret[key] != undefined ?
                               ret[key] :
                               {};
                    ret = ret[key];
                }
                ret[keys.shift()] = val;
                this.show();
                return this;
            }
        });
    })

    遇到的问题与其他UI团队一样,其实你看一下jquery UI就知了。一个控件,它肯定有视图层,这里我们是用ejs v10来生成。生成HTML插入到DOM算是完成了一半,但当我们要修改这个控件的一些属性,一些与视图相关的属性就遇到麻烦了。比如说title属性,如果是jquery ui,它肯定先到这个控件的ID,然后再找包含这个title的元素节点,再替换掉它的文本。用jquery是这样写出:

    setTilte: function(newTitle){
        $(this.UIid).find("jquery-panel-title").text(newTitle);//更新视图
        this.title = newTitle;//同时同步对应的属性
    }
    getTitle: function(){
        return this.title;
    }

    如果一个控件涉及的视图属性越多,控件这样的访问器就越多!长此以往不是办法!像日历组件,你可以看到它是多么臃肿。

    这时该到MVVM出马了。它把这些与视图显示相关的属性全部收集到一起,包括基于这些属性的属性,比如说fullName是基于lastName与firstName,它是通过函数生成的,这个在模型(M)里是不存在的,但它存于视图模型(VM)中。由于双向绑定的存在,我们修改了VM的一个值,它立即自动刷新视图中对应的位置的值,这过程完全不需要动用到选择器!

    基于选择器的方式是最不可靠的,因为视图的变更最频繁,某一天PM说要多加一功能或不要一功能,于是就多几个父节点或少几个子节点,把HTML的层级关系搞得乱七八糟,我们的选择器寻找就得重写一次!

    因此对于这些DOM操作,我们最好也封装一层,这是比jquery的DOM操作函数更高层的封装,目的是让控件开发者远离视图层,他们只需要关注于模型层。如果我们把DOM操作看成增删改查,那么原始的DOM API相当于直接用二进制手段暴力去改数据库,而像jQuery等主流库提供了强大的选择器引擎与DOM操作函数,相当于发明SQL,而像knockout.js这样的MVVM框架拥有尖端的依赖链机制、双向绑定,让智能的集化操作,事务与锁成为可能,是DOM级别的“ORM系统”!

    顺便一提,在VM中,所有属性都是函数,每个函数都是读写结合,像jquery的html, attr, text那样便捷!这有出于兼容IE678的考量,因为它们不支持Object.defineProperty这样的属性描述符(或支持不良好,如IE8)。

    我的MVVM v1完全是向knockout.js致敬的,用法与它的一模一样,不过代码量少了许多。具体教程与实可以看以下链接:

    最近看了许多MVVM的实现,功力大增,估计v2秒换胎脱骨,更精简更高效,敬请期待!

     
     
    标签: javascriptmass
  • 相关阅读:
    Tabs 选项卡插件(续)
    Menu 菜单插件
    jquery Star Rating - 星形评级插件
    Tabs 选项卡插件
    jQuery Tooltips插件
    jQuery信息提示插件(jQuery Tooltip Plugin)
    Accordion 手风琴 折叠菜单插件
    Calendars 日历插件
    Microsoft Windows 2000 professional(集成SP4)简体中文专业版下载
    俄罗斯商务资讯网(门户网站)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2687967.html
Copyright © 2020-2023  润新知