关于js封装框架类库之DOM操作模块(一)

在前端开发的过程中,javascript极为重要的一个功能就是对DOM对象的操作,而对其封装就是为了更好地进行DOM操作,提高浏览器的支持效率

  • 现在给出一个案例:页面创建三个div,然后给其添加样式

1、第一种方法

//第一种方法
    var i, node;
    for ( i = 0; i < 3; i++ ) {
        node = document.createElement( 'div' );
        node.setAttribute( 'class', 'c' );
        //node.className = 'c';
        document.body.appendChild( node );
    }
View Code

 上面方法缺点:由于每次循环都使用 document.body.appenChild 因此会导致每次 for 都要刷新页面结构,影响浏览器性能,应该采用一个临时的数据
 存储这些 dom 对象, 在全部创建完成以后再加入

2、第二种方法

var i, node, container = document.createElement( 'div' );
        for ( i = 0; i < 3; i++ ) {
            node = document.createElement( 'div' );
            // node.setAttribute( 'class', 'c' );
            node.className = 'c';
            container.appendChild( node );
        }
        document.body.appendChild( container );
View Code

这种方法同样能实现,但是改变了页面结构

3、第三种方法

//这里的DocumentFragment是文档片段(nodeType 11) 用于缓存的DOM对象,页面结构不会影响
            /*var i, node, 
            container = document.createDocumentFragment();
        for ( i = 0; i < 3; i++ ) {
            node = document.createElement( 'div' );
            node.setAttribute( 'class', 'c' );
            //node.className = 'c';
            container.appendChild( node );
        }
        document.body.appendChild( container );
View Code

4、第四种方法

var i, s = "";
            for ( i = 0; i < 3; i++ ) {
                s += '<div> ' + ' </div>';
            }
            document.body.innerHTML = s;
//在这只实现了添加标签
View Code

5、在实际框架中创建html中的方法

//在实际框架中创建html中的方法
           var parseDom = function (html){
           var docfrag = document.createDocumentFragment();
           var div = document.createElement('div');//必须创建一个真正的div
           div.innerHTML = html;
           // 在 DOM 元素中默认有一个特征, 即元素只允许有一个 父节点
        // 如果添加元素到另一个节点中, 该元素会自动的离开原来的父节点
           while(div.firstChild){
               docfrag.appendChild(div.firstChild);
           }
           return docfrag;
       };
        var dom = parseDom( '<span>hello word</span></br>'
                            +'<span>hello word</span>'    );
        document.body.appendChild( dom );
View Code

6、 假如传入的是dom对象,要给其添加一个appenTo方法,现在问题来了,在哪个原型中添加该方法,并且不能影响其他内置对象成员。

思路:给dom对象提供一个包装对象,在这个返回的包装对象中提供一个自定义appendTo方法

        var parseDom = function (html){
                var docfrag = document.createDocumentFragment();
                var div = document.createElement('div');
                div.innerHTML = html;
                while(div.firstChild){
                    docfrag.appendChild(div.firstChild);
                }
                return {
                    element: docfrag,
                    appendTo: function(dom){
                        dom.appendChild(this.element);
                    }
                };
            };
View Code
  • DOM框架的基本实现

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="UTF-8">
  5         <title></title>
  6         <script>
  7             // 构造函数
  8             var YY = function ( selector ) {
  9                 return new YY.fn.init( selector );//返回init方法的一个实例对象,一个构造函数的原型属性上的函数init的原型链和YY原型链是不同的
 10             };
 11             //原型继承分别为
 12             //YY->YY.prototype->object.prototype->null
 13             //init->init.prototype->object.prototype->null
 14             // 核心原型
 15             YY.fn = YY.prototype = {
 16                 constructor: YY,
 17                 selector: null,
 18                 init: function ( selector ) {
 19                     // 字符串: 选择器, html
 20                     if ( typeof selector == 'string' ) {
 21                         if ( selector.charAt( 0 ) === '<' ) {
 22                             this.elements = parseHTML( selector );
 23                         } else {
 24                             this.elements = select( selector );
 25                         }
 26                     }
 27                     this.selector = selector;//可以判断出,只要有这个属性的对象,就是YY对象
 28                 }
 29             };
 30             YY.fn.init.prototype = YY.prototype;
 31             
 32             // 可扩展
 33             YY.extend = YY.fn.extend = function ( obj ) {
 34                 // 将 obj 的成员加到 this 上
 35                 var k;
 36                 for ( k in obj ) {
 37                     this[ k ] = obj[ k ];
 38                 }
 39             };
 40             
 41             //选择器方法,暂时只考虑基本选择器
 42             var select = function ( selector ) {
 43                 var first = selector.charAt( 0 ), arr = [];
 44                 if ( first === '#' ) {
 45                     arr.push.call( arr, document.getElementById( selector.slice( 1 ) ) )
 46                 } else if ( first === '.' ) {
 47                     arr.push.apply( arr, document.getElementsByClassName( selector.slice( 1 ) ) )
 48                 } else {
 49                     arr.push.apply( arr, document.getElementsByTagName( selector ) );
 50                 }
 51                 return arr;
 52             };
 53             
 54             var parseHTML = function ( html ) {
 55                 var div = document.createElement( 'div' ),
 56                     arr = [], i;
 57                 div.innerHTML = html;
 58                 for ( i = 0; i < div.childNodes.length; i++ ) {
 59                     arr.push( div.childNodes[ i ] );
 60                 }
 61                 return arr;
 62             };
 63             
 64             // 基本的工具方法
 65             YY.extend({
 66                 each: function ( arr, fn ) {
 67                     var i, l = arr.length, 
 68                         isArray = YY.isLikeArray( arr );//先判断是否为数组
 69                     if ( isArray ) {
 70                         // 数组
 71                         for ( i = 0; i < l; i++ ) {
 72                             if ( fn.call( arr[ i ], i, arr[ i ] ) === false ) {
 73                                 break;
 74                             }
 75                         }
 76                     } else {
 77                         // 对象
 78                         for ( i in arr ) {
 79                             if ( fn.call( arr[ i ], i, arr[ i ] ) === false ) {
 80                                 break;
 81                             }
 82                         }
 83                     }
 84                     return arr;
 85                 }
 86             });
 87             
 88             // 判断类型的方法
 89             YY.extend({
 90                 isFunction: function ( obj ) {
 91                     return typeof obj === 'function';//判断是否为function
 92                 },
 93                 isString: function ( obj ) {
 94                     return typeof obj === 'string';//判断是否为字符串
 95                 },
 96                 isLikeArray: function ( obj ) {
 97                     return obj && obj.length && obj.length >= 0;//判断是否为数组
 98                 },
 99                 isYY: function ( obj ) {
100                     return !!obj.selector;//判断是否为YY,给其原型属性加个属性,默认为空
101                 },
102                 isDOM: function ( obj ) {
103                     return !!obj.nodeType;
104                 }
105             });
106             
107             
108             // 基本的 DOM 操作,此处假设selector是DOM对象
109             YY.fn.extend({
110                 appendTo: function ( selector ) {
111                     // 将 this.elements 加入到 selector 中
112                     YY.each( this.elements, function () {
113                         selector.appendChild( this );
114                     } );
115                 }
116             });
117             
118             
119         </script>
120         
121         <script type="text/javascript">
122             onload = function () {
123                 YY( '<div>1</div><div>2</div><div>3</div><div>4</div>' )
124                     .appendTo( document.body );
125             }
126         </script>
127     </head>
128     <body>
129     </body>
130 </html>

假如selector是id选择器,那么如何实现appendTo方法呢

//YY( selector )返回结果为对象,YY( selector ).elements是一个数组
            YY.fn.extend({
                appendTo: function ( selector ) {                    
                    YY.each( this.elements, function () {
                        YY( selector ).elements[ 0 ].appendChild( this );
                    } );
                }
            });

假如selector是标签选择器,那么如何实现appendTo方法呢

YY.fn.extend({
                appendTo: function ( selector ) {    
                    var _this = this;
                    var objs = YY( selector ).elements;
                    YY.each( objs, function ( i1, v1 ) {
                        var that = this;
                        YY.each( _this.elements, function ( i2, v2 ) {
                            // this 当前元素, 要加到 that 上
                            that.appendChild( i1 == objs.length - 1?
                                                this :
                                                this.cloneNode( true ) );
                            // 判断如果是最后一个就无须克隆
                        });
                    });
                }
            });


 本人文笔有限,才疏学浅,文中若有不正之处,万望告知,不胜感激!

原文地址:https://www.cnblogs.com/goweb/p/DOM.html