A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小鲁哥哥 于 2018-4-13 14:07 编辑

【济南校区】前端就业班笔记框架封装(三)

DOM 操作
实际上, 在 DOM 操作中使用的最多的是 增加数据( 增加 DOM 节点 ), 删除数据( 删除节点等 ),修改数据( 修改属性, 修改样式 ), 查询( 获得元素, 找寻节点对象 ).
-> parseHTML 方法
     传统与 jq 中创建标签的办法
      1) document.createElement( 'div' )
      2) $( '<div></div>' )
现在需要提供一个字符串, 然后将其转换成 HTML 标签( DOM 对象 )
     1> 如何判断用户输入的是标签格式的字符串
          思考: 选择器的字符串结构与 HTML 字符串结构有何不同???
          在 HTML 中必须有 尖括号, 而且一定在两端,但是选择器中, 尖括号只会出现在选择器中间, 表示子代元素
         
          if ( str.charAt( 0 ) === '<' && str.charAt( str.length - 1 ) === '>' )
            这就是说明了 它是一个 html 格式的字符串
      2> 如何解析这个字符串???
          -> 字符串解析( 正则表达式 )
              常用 html 格式有两种形态
                1) 单标签形态: 例如 <br /> <input type="text"> 等
                    这个标签满足格式 /<.+\/>/ 或者: /<\S+.*?\/>/
                2) 复杂的标签形态: 例如: <div><img /></div>
                    如果使用格式: /<(.+)>.*<\/\1>/
                    无法处理: <div><div></div></div>
            -> 将解析的工作交给 浏览器来完成
                思考, 在 HTML 的方法中有没有一个 将 HTML 格式字符串转换为 DOM 的办法,很显然, innerHTML
            注意: 该方法使用 的是 div 作为容器, 因此在内部不能够直接创建 tr, td 等元素
[JavaScript] 纯文本查看 复制代码
    function parseHTML ( htmlStr ) {
        var rest = [], i,
            div = document.createElement( 'div' ); 
        div.innerHTML = htmlStr; 
        for ( i = 0; i < div.childNodes.length; i++ ) {
            rest.push( div.childNodes[ i ] );
        }
        return rest
    }


    // 有一组数据
    var datas = [
        { name: 'jim1', age: 19, gender: '男' },
        { name: 'jim2', age: 9, gender: '女' },
        { name: 'jim3', age: 29, gender: '男' },
        { name: 'jim4', age: 39, gender: '女' },
        { name: 'jim5', age: 49, gender: '女' }
    ];

    // 生成一个 table 表格
    // 只需要保证 table 中有 tr 即可, 不考虑 thead 等数据
    parseHTML( '<table border="1" width="400">' + datas.map(function ( v ) {
        // v 就是每一项数据, 即每一行数据
        var rest = [];
        for( var k in v ) {
            // 此时 k 就是 对应的 name, age, 和 gender
            rest.push( '<td>' + v[ k ] + '</td>' );
        }
        return '<tr>' + rest.join( '' ) + '</tr>';
    }).join( '' ) + '</table>' ).forEach( function ( v ) {
        document.body.appendChild( v );
    });

引入到框架
        1> 修改构造方法, 使得可以处理其他数据
        2> 将 parseHTML 方法挂载到 构造函数上
        3> 如何组织代码
            今天的前端开发已经不再是以前的切切图就可以解决的了
            现在的前端, 有大量的代码需要编写, 可以非常注重项目结构化.
            因此需要将代码分解到不同的文件中.
            按照功能进行分解: 核心模块, DOM 操作模块, 事件模块, 属性样式模块, 其他模块
[JavaScript] 纯文本查看 复制代码
(function ( window ) {

var arr = [],
    push = arr.push,
    slice = arr.slice;

function Itcast( selector ) {
    return new Itcast.fn.init( selector );
}

Itcast.fn = Itcast.prototype = {
    constructor: Itcast,

    length: 0,

    init: function ( selector ) {
        // 需要判断, 根据传入的数据不同而实现不同的功能
        if ( !selector ) return this;



        if ( typeof selector == 'string' ) {
            // 判断是选择器 还是 html 字符串
            if ( selector.charAt( 0 ) == '<' && selector.charAt( selector.length - 1 ) == '>' ) {
                // HTML 标签
                push.apply( this, Itcast.parseHTML( selector ) );
                return this;
            } else {
                // 选择器
                push.apply( this, Itcast.select( selector ) ); 
                return this;
            }
        }

    },
    each: function ( callback ) {
        return Itcast.each( this, callback );
    },
    map: function ( callback ) {
        return Itcast.map( this, callback );
    },
    toArray: function () {

        return slice.call( this );
    }, 
    get: function ( index ) {
        // arguments.length == 0 
        if ( index === undefined ) {
            // 没有传参
            return this.toArray();
        } else {
            // 传入了参数
            if ( index >= 0 ) {
                return this[ index ];
            } else if ( index < 0 ) {
                return this[ this.length + index ];
            }
        }

        return this; // 如果传入的既不是正数, 也不是负数, 也不是没有传参
    }
};

Itcast.fn.init.prototype = Itcast.fn;



Itcast.isArrayLike = function ( array ) {  
    var length = array && array.length;

    return typeof length === 'number' && length >= 0;

}
Itcast.each = function ( array, callback ) {
    var i, k;
    if ( Itcast.isArrayLike( array ) ) {
        // 使用 for 循环
        for ( i= 0; i < array.length; i++ ) {
            if( callback.call( array[ i ], i, array[ i ] ) === false ) break;
        }
    } else {
        // 使用 for-in 循环
        for ( k in array ) {
            if( callback.call( array[ i ], k , array[ k ] ) === false ) break;
        }
    }
    return array; 
}


Itcast.map = function ( array, callback ) {
    var i, k,
        res = [],
        tmp;
    if ( Itcast.isArrayLike( array ) ) {
        // 使用 for 循环
        for ( i= 0; i < array.length; i++ ) {
            tmp = callback( array[ i ], i );
            if ( tmp !== undefined ) {
                res.push( tmp );
            }
        }
    } else {
        // 使用 for-in 循环
        for ( k in array ) {
            tmp = callback( array[ k ], k );
            if ( tmp !== undefined ) {
                res.push( tmp );
            }
        }
    }
    return res; 
}
Itcast.select = function ( selector ) {
    return document.querySelectorAll( selector );
}



Itcast.extend = Itcast.fn.extend = function ( obj ) {
    for ( var k in obj ) {
        this[ k ] = obj[ k ];
    }
};


// DOM 处理
function parseHTML ( htmlStr ) {
    var rest = [], i,
        div = document.createElement( 'div' ); 
    div.innerHTML = htmlStr; 
    for ( i = 0; i < div.childNodes.length; i++ ) {
        rest.push( div.childNodes[ i ] );
    }
    return rest
}
Itcast.parseHTML = parseHTML;

window.Itcast = window.I = Itcast; // 在 全局范围内 引入两个变量

})( window );
    // 创建一个 div 加到页面中
    I( 'body' ).get( 0 ).appendChild(
        I( '<div id="dv" style="border: 1px solid red; width: 200px; height: 70px;">123</div>' ).get( 0 )
    );


    // 修改 刚刚加入的 div
    I( '#dv' ).each(function (){
        this.style.border = '1px dashed blue';
    })

基本 DOM 方法
        -> 什么是 DOM 操作
            所谓的 DOM 操作就是在操作 DOM.
            1) 增加 DOM 元素
                创建元素: $( ... )
                加入:   $( ... ).appendTo( ... )
                       $( ... ).append( ... )
                       ...
            2) 删除 DOM 元素
                $( ... ).remove()
            3) 修改 DOM 元素
                所谓的修改就是 修改属性, 修改样式, 实际上将原有移除, 新加一个即可
        -> appendTo
            在 jq 中该方法的含义是 将 前面的 jq 对象中包含 DOM 元素, 全部加到 后面的 元素中
            $( '<div>1</div>' ).appendTo( 'body' )
            新建一个 div 标签, 然后将其追加到 body 中.
            关于 appendTo 的参数
                $( ... ).appendTo( 'body' )        参数是一个选择器
                $( ... ).appendTo( $( 'body' ) )   参数是一个 jq 对象
                $( ... ).appendTo( document.body ) 参数是一个 dom 对象
            转化: 如果一个函数可以传入三种参数, 而且这三种参数的处理逻辑不太相同
            一般来说结构就可以写成
[JavaScript] 纯文本查看 复制代码
                function xxx ( args ) {
                    if ( typeof args == 'string' ) {
                        ...
                    } else if ( args.nodeType ) {
                        ...
                    } else if ( args 是 Itcast 对象 ) {
                        ...
                    }
                } 

            划归: 将一个问题转化成一个已经解决的问题
                可以将所有的情况转化成 处理 数组的 模型中
                1) 字符串 -> Itcast 对象 -> 数组
                2) DOM 元素 -> Itcast 对象 -> 数组
                3) Itcast 对象 -> 数组
            
            思考:  jq 中, $ 函数可以处理什么参数
                $( '选择器' ), $( dom ), $( $( ... ) ), $( fn ), ...

            如果 我们的 Itcast 构造函数可以将 各种数据 转化成 Itcast 对象( 即数组 )   
[JavaScript] 纯文本查看 复制代码
            Itcast.fn.appendTo = function ( selector ) {
                var iObj = Itcast( selector ); // 数组

                return this.each(function () {

                    for ( var i = 0; i < iObj.length; i++ ) {
                        iObj[ i ].appendChild( i == iObj.length - 1 
                                                    ? this 
                                                    : this.cloneNode( true ) );
                    }

                }); 
            };

        -> 构造函数
            在 jq 中 构造函数参数的用法
            1) 允许传入选择: string
            2) 允许传入 html 字符串: string
            3) 允许传入 dom 元素: object, 如何判断??? nodeType 属性
            4) 允许传入 jQuery 对象: object, 如何判断??? .constructor
                在 jquery 中原型上有一个属性 selector, 该属性用于记录选择器.
                jquery 使用的就是该属性来判断的.
            5) 允许传入 函数: function 相当于 onload 事件.
            6) 数组等
        -> 考虑 返回值
            每次需要 克隆 DOM 对象, 因此准备一个数组, 然后将数组加载完成以后生成一个新的 Itcast 对象即可

        -> 记录下链破坏之前原来对象
            iNewObj.prevObj = this
            每次链破坏的时候, 都可以记录下来, 那么只要调用 end 方法就将原来的数据取出来即可
        -> append
        -> prepend
        -> prependTo
        -> insertAfter
        -> insertBefore
        -> after
        -> before

    -> 成员访问方法
        就是在访问相关的元素( 访问亲属元素 )
        -> .parent()
        -> .prev()
        -> .prevAll()
        -> .next()
        -> .nextAll()
        -> .sblings()
如果你想了解更多黑马课程请点击这里,如果你想加入黑马这个大家庭学习先进技术,广交天下好友!
黑马程序员济南中心联系电话:0531-55696830


1 个回复

倒序浏览
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马