您好,UncleToo欢迎您!  为了更好的浏览本站,请使用高版本浏览器
RSS  Tag     设为首页 | 加入收藏
 您所在的位置:首页 > 前端开发 > XML&DOM

一个非常简单的操作DOM的JS类库

作者:UncleToo  来源:翻译  日期:2014-03-12 8:48:46
收藏  评论:( 0 )  阅读:652

       在WEB应用程序开发过程中,DOM的访问与操作是很常见的,也是必须有的。当我们需要访问或设置页面元素信息时就要用到DOM的知识。虽然有很多JS类库可以很方便的操作DOM,例如jQuery,但是如果我们为了一些很小的操作而去引用一个庞大的类库就不合适了,这里给大家推荐一个自定义的JS类库,它只有100行代码,可以帮助我们轻松的管理DOM元素


API使用

在看完整的类库代码之前,我么首先看看这个类库如何使用。

// 返回DOM元素对象
dom('.selector').el
// 返回元素对象的值
dom('.selector').val()
// 给元素对象赋值
dom('.selector').val('value')

上面例子就是我们平时使用最多的几种DOM元素的操作,是不是很简单呢!这是对单个元素的操作,如果我们需要操作多个元素,也是可以的。

// 创建一个多元素对象集合
dom({
    structure: {
        propA: '.selector',
        propB: '.selector'
    },
    propC: '.selector'
})

一旦集合创建完成后,我们就可以很容易的获取对应的值了。

// 返回集合元素的值
dom({
    structure: {
        propA: '.selector',
        propB: '.selector'
    },
    propC: '.selector'
}).val()

这将使我们可以很容易的将DOM元素转换为JavaScript对象。因此,我们要自定的这个类可以使这样的:

var dom = function(el) {
    var api = { el: null }
    api.val = function(value) {
        // ...
    }
    return api;
}


划定范围

通常我们会使用JS自带的方法访问DOM,如getElementById、querySelector或querySelectorAll方法,例如:

var header = document.querySelector('.header');

有趣的是,例如querySelector方法,它不仅仅是文档对象函数,同时也是其他任何DOM元素的方法。因此,我们可以在特定的上下文中使用它,如:

<header>
    <p>Big</p>
</header>
<footer>
    <p>Small</p>
</footer>
var header = document.querySelector('header');
var footer = document.querySelector('footer');
console.log(header.querySelector('p').textContent); // Big
console.log(footer.querySelector('p').textContent); // Small

也就是说,如果我们指定了父元素,就可以很好的获取该元素的值,因此,我们自定义类中应该存在这样的操作:

var dom = function(el, parent) {
    var api = { el: null }
    api.val = function(value) {
        // ...
    }
    return api;
}


定位DOM元素

上面我们提到的querySelector和querySelectorAll函数可以定位DOM元素,那么我们可以封装一下这两个函数,简化操作。

var qs = function(selector, parent) {
    parent = parent || document;
    return parent.querySelector(selector);
};
var qsa = function(selector, parent) {
    parent = parent || document;
    return parent.querySelectorAll(selector);
};

然后我们需要通过参数的形式传递进去,一般传递的是字符串,也为了丰富操作,我们同时也要考虑传递对象的时候。下面我们就使用switch分别实现这两种参数形式。

switch(typeof el) {
    case 'string':
        parent = parent && typeof parent === 'string' ? qs(parent) : parent;
        api.el = qs(el, parent);
    break;
    case 'object':
        if(typeof el.nodeName != 'undefined') {
            api.el = el;
        } else {
            var loop = function(value, obj) {
                obj = obj || this;
                for(var prop in obj) {
                    if(typeof obj[prop].el != 'undefined') {
                        obj[prop] = obj[prop].val(value);
                    } else if(typeof obj[prop] == 'object') {
                        obj[prop] = loop(value, obj[prop]);
                    }
                }
                delete obj.val;
                return obj;
            }
            var res = { val: loop };
            for(var key in el) {
                res[key] = dom.apply(this, [el[key], parent]);
            }
            return res;
        }
    break;
}

下面我们看几个例子:

<p>text</p>
<header>
    <p>Big</p>
</header>
<footer>
    <p>Small</p>
</footer>

在上面的代码中访问第一个段落(P标记)

dom('p').el

访问的段落标题节点

dom('p', 'header').el

传递DOM元素

dom(document.querySelector('header')).el

传递JavaScript对象

var els = dom({
    footer: 'footer',
    paragraphs: {
        header: 'header p',
        footer: 'footer p'
    }
}))
els.paragraphs.footer.el


获取或设置DOM元素值

表单元素(例如输入框、选择框等)可以很方便的获取到值,但是如果我们需要获取标记元素的属性值时就有点棘手了,如我们需要获取div标签中textContent属性值,此时我们可以考虑如下代码:

api.val = function(value) {
    if(!this.el) return null;
    var set = !!value;
    var useValueProperty = function(value) {
        if(set) { this.el.value = value; return api; }
        else { return this.el.value; }
    }
    switch(this.el.nodeName.toLowerCase()) {
        case 'input':
        break;
        case 'textarea':
        break;
        case 'select':             
        break;
        default:
    }
    return set ? api : null;
}

这看起来是不是太简单了呢,当然不止这些。下面我们还需要判断不同类型的DOM元素。

case 'input':
    var type = this.el.getAttribute('type');
    if(type == 'radio' || type == 'checkbox') {
        var els = qsa('[name="' + this.el.getAttribute('name') + '"]', parent);
        var values = [];
        for(var i=0; i<els.length; i++) {
            if(set && els[i].checked && els[i].value !== value) {
                els[i].removeAttribute('checked');
            } else if(set && els[i].value === value) {
                els[i].setAttribute('checked', 'checked');
                els[i].checked = 'checked';
            } else if(els[i].checked) {
                values.push(els[i].value);
            }
        }
        if(!set) { return type == 'radio' ? values[0] : values; }
    } else {
        return useValueProperty.apply(this, [value]);
    }
break;

对于多行文本元素的操作很简单

case 'textarea':
    return useValueProperty.apply(this, [value]);
break;

下面是下拉元素的操作

case 'select':
    if(set) {
        var options = qsa('option', this.el);
        for(var i=0; i<options.length; i++) {
            if(options[i].getAttribute('value') === value) {
                this.el.selectedIndex = i;
            } else {
                options[i].removeAttribute('selected');
            }
        }
    } else {
        return this.el.value;
    }
break;

其他所有操作

default:
    if(set) {
        this.el.innerHTML = value;
    } else {
        if(typeof this.el.textContent != 'undefined') {
            return this.el.textContent;
        } else if(typeof this.el.innerText != 'undefined') {
            return typeof this.el.innerText;
        } else {
            return this.el.innerHTML;
        }
    }
break;

以上这些判断代码在一起就完成了val方法,下面我们简单测试一下。

<form>
    <input type="text" value="sample text" />
    <input type="radio" name="options" value="A">
    <input type="radio" name="options" checked value="B">
    <select>
        <option value="10"></option>
        <option value="20"></option>
        <option value="30" selected></option>
    </select>
    <footer>version: 0.3</footer>
</form>

有以上HTML代码,执行如下JS

dom({
    name: '[type="text"]',
    data: {
        options: '[type="radio"]',
        count: 'select'
    },
    version: 'footer'
}, 'form').val();

我们将得到

{

   data: {

       count: "30",

       options: "B"

   },

   name: "sample text",

   version: "version: 0.3"

}

这可以帮助我们将HTML表单元素转换为JavaScript对象,也是在开发过程中经常使用的。


最终结果

结合上面说的几种操作,我们最终得到如下完整的DOM管理的JS类库,仅仅只有100行代码。

var dom = function(el, parent) {
    var api = { el: null }
    var qs = function(selector, parent) {
        parent = parent || document;
        return parent.querySelector(selector);
    };
    var qsa = function(selector, parent) {
        parent = parent || document;
        return parent.querySelectorAll(selector);
    };
    switch(typeof el) {
        case 'string':
            parent = parent && typeof parent === 'string' ? qs(parent) : parent;
            api.el = qs(el, parent);
        break;
        case 'object':
            if(typeof el.nodeName != 'undefined') {
                api.el = el;
            } else {
                var loop = function(value, obj) {
                    obj = obj || this;
                    for(var prop in obj) {
                        if(typeof obj[prop].el != 'undefined') {
                            obj[prop] = obj[prop].val(value);
                        } else if(typeof obj[prop] == 'object') {
                            obj[prop] = loop(value, obj[prop]);
                        }
                    }
                    delete obj.val;
                    return obj;
                }
                var res = { val: loop };
                for(var key in el) {
                    res[key] = dom.apply(this, [el[key], parent]);
                }
                return res;
            }
        break;
    }
    api.val = function(value) {
        if(!this.el) return null;
        var set = !!value;
        var useValueProperty = function(value) {
            if(set) { this.el.value = value; return api; }
            else { return this.el.value; }
        }
        switch(this.el.nodeName.toLowerCase()) {
            case 'input':
                var type = this.el.getAttribute('type');
                if(type == 'radio' || type == 'checkbox') {
                    var els = qsa('[name="' + this.el.getAttribute('name') + '"]', parent);
                    var values = [];
                    for(var i=0; i<els.length; i++) {
                        if(set && els[i].checked && els[i].value !== value) {
                            els[i].removeAttribute('checked');
                        } else if(set && els[i].value === value) {
                            els[i].setAttribute('checked', 'checked');
                            els[i].checked = 'checked';
                        } else if(els[i].checked) {
                            values.push(els[i].value);
                        }
                    }
                    if(!set) { return type == 'radio' ? values[0] : values; }
                } else {
                    return useValueProperty.apply(this, [value]);
                }
            break;
            case 'textarea':
                return useValueProperty.apply(this, [value]);
            break;
            case 'select':
                if(set) {
                    var options = qsa('option', this.el);
                    for(var i=0; i<options.length; i++) {
                        if(options[i].getAttribute('value') === value) {
                            this.el.selectedIndex = i;
                        } else {
                            options[i].removeAttribute('selected');
                        }
                    }
                } else {
                    return this.el.value;
                }
            break;
            default:
                if(set) {
                    this.el.innerHTML = value;
                } else {
                    if(typeof this.el.textContent != 'undefined') {
                        return this.el.textContent;
                    } else if(typeof this.el.innerText != 'undefined') {
                        return typeof this.el.innerText;
                    } else {
                        return this.el.innerHTML;
                    }
                }
            break;
        }
        return set ? api : null;
    }
    return api;
}




DOM
 
HTML
 
jQuery
 
除非特别声明,本站所有PHP教程及其他教程/文章均为原创、翻译或网友投稿,版权均归UncleToo中文网所有, 转载请注明作者及出处。
原文网址:http://www.uncletoo.com/html/xmldom/847.html
读完这篇文章后,你是否有所收获? 分享是一种生活的信念!
  • 0
  • 0
我来说两句
更多>>网友评论
UncleToo,一档有态度的PHP中文网

图片教程