资讯专栏INFORMATION COLUMN

VQuery-封装自己的JQuery

EdwardUp / 2892人阅读

摘要:无参数当前当前文档中其所在在位置从开始工具函数函数函数包装器可以不用了工具函数通过类名来选取元素父级对象类名获取到的节点数组事件添加函数需要绑定事件的对象事件类型事件触发执行的函数标准修改下指向的问题最后选择

VQuery-封装自己的JQuery

标签(空格分隔): JS

封装自己的jQuery--vQuery vQurey选择器 VQuery类

elements属性,存储选择的元素

参数

typeof的使用判断传入参数的类型

字符串

class/id/tagname

函数

事件绑定-

对象

直接插入

//VQuery选择器
 function VQuery(vArg) {
    //用来保存选择的元素
    this.elements = [];
    switch (typeof vArg) {
        //当传入函数时.
    case "function":
        myAddEvent(window, "load", vArg);
        break;
    case "string":
        //传入字符串时.
        switch (vArg.charAt(0)) {
        case "#": //id
            var obj = document.getElementById(vArg.substring(1));
            this.elements.push(obj);
            break;
        case ".": //class
            this.elements = getByClassName(document, vArg.substring(1));
            break;
        default: //tagName
            this.elements = document.getElementsByTagName(vArg);
        }
        break;
    case "object":
        this.elements.push(vArg);
        break;
    }
}
VQuery事件 绑定事件 click方法.绑定点击事件
/**
 * 元素点击方法
 * @param {Function} fn 点击后执行的函数
 */
VQuery.prototype.click = function (fn) {
    for (var i = 0, len = this.elements.length; i < len; i++) {
        myAddEvent(this.elements[i], "click", fn);
    }
};
显示隐藏方法.hide/show.改变display属性
 /**
 * 显示元素,display:block
 */
VQuery.prototype.show = function () {
    for (var i = 0, len = this.elements.length; i < len; i++) {
        this.elements[i].style.display = "block";
    }
};
/**
 * 隐藏元素,display:none
 */
VQuery.prototype.hide = function () {
    for (var i = 0, len = this.elements.length; i < len; i++) {
        this.elements[i].style.display = "none";
    }
};
hover方法.鼠标移入移出时
/**
 * 鼠标移入移出方法
 * @param {Function} fnOver 鼠标移入执行的函数
 * @param {Function} fnOut  鼠标移出执行的函数
 */
VQuery.prototype.hover = function (fnOver, fnOut) {
    for (var i = 0, len = this.elements.length; i < len; i++) {
        myAddEvent(this.elements[i], "mouseover", fnOver);
        myAddEvent(this.elements[i], "mouseout", fnOut);
    }
};

解决函数中的this问题

call/apply可以动态修改对象的this指向.

知乎如何理解和熟练运用js中的call及apply?

toggle方法.切换

点击记数

 //使用匿名函数包装器来给每个对象创建局部变量
(function (obj) {
    var count = 0;
    myAddEvent(obj, "click", function () {
        alert(count++);
    });
})(this.elements[i]);

arguments的使用

toggle方法,切换,接收任意个参数,不断在参数间循环.例:点击显示隐藏
*/
VQuery.prototype.toggle = function () {
var _arguments = arguments;
for (var i = 0, len = this.elements.length; i < len; i++) {

   addToggle(this.elements[i]);

}

function addToggle(obj) {

   var count = 0;
   myAddEvent(obj, "click", function () {
       _arguments[count++ % _arguments.length].call(obj);
   });

}
};

css方法, 设置或者获取样式

简单形式 -- 设置/获取

获取计算后的样式

/**
 * 设置与获取元素样式的方法:
 * 接受1个或者2个参数(1个参数时:返回传入属性名对应的的样式值,两个参数:为传入的样式名为设置样式值)
 * @param {String} attr  设置或获取的样式名
 * @param {String} value 样式值(可选)
 */
VQuery.prototype.css = function (attr, value) {
    if (arguments.length == 2) {
        for (var i = 0, len = this.elements.length; i < len; i++) {
            this.elements[i].style[attr] = value;
        }
    } else {
        //1个参数时返回获取到的样式
        return getStyle(this.elements[0], attr);

    }
};
attr方法,设置或获取属性
 /**
 * 属性设置与获取方法,与css方法基本一致.
 * @param   {String} attr  设置或获取的属性名
 * @param   {String} value 属性值(可选)
 * @returns {String} 一个参数时,返回对应的属性值
 */
VQuery.prototype.attr = function (attr, value) {
    if (arguments.length == 2) {
        for (var i = 0, len = this.elements.length; i < len; i++) {
            this.elements[i][attr] = value;
        }
    } else {
        return this.elements[0][attr];
    }

}
eq方法-减少匹配元素的集合为指定的索引的哪一个元素。
/**取其中的第n个对象-方法-减少匹配元素的集合为指定的索引的哪一个元素。
 * @param   {Number} n 需要的第几个元素
 * @returns {Object} 返回获取到的vquery元素
 */
VQuery.prototype.eq = function (n) {
    //必须使用$包装.使返回的节点从普通对象变得vquery的元素(普通对象没有vQuery方法)

    return $(this.elements[n]);
};
find方法-查找当前对象的后代元素.
/**
 * 把arr2内的元素添加到arr1
 * 把类数组对象或数组转变为数组.(不需要类数组元素支持Array的方法)
 * @param {Array}  arr1 转变后的数组
 * @param {Object} arr2 类数组对象或数组
 */
function appendArr(arr1, arr2) {
    for (var i = 0, len = arr2.length; i < len; i++) {
        arr1.push(arr2[i]);
    }
}
/**
 * 查找当前对象的后代元素.
 * @param   {String} str class名或标签名
 * @returns {Object} 获取到的对象集合
 */
 
VQuery.prototype.find = function (str) {
    var aResult = [];

    for (var i = 0, len = this.elements.length; i < len; i++) {
        switch (str.charAt(0)) {
        case ".": //class
            var aEle = getByClassName(this.elements[i], str.substring(1));
            appendArr(aResult, aEle);

            break;
        default: //标签
            var aEle = this.elements[i].getElementsByTagName(str);
            //            aResult = aResult.concat[aEle];//这样做会出错,因为aEle并不是一个真正的数组,必须使用下面的方法
            appendArr(aResult, aEle);
        }
    }
    //必须这么做,因为不这样做返回的是节点集合,不具有VQuery的方法和属性
    var newVquery = $();
    newVquery.elements = aResult;
    return newVquery;
};
index方法--当前元素在其同级元素中的位置
/**
 * 获取当前元素在同辈元素的位置
 * @param   {Object} obj 需要获取的对象
 * @returns {Number} 获取到的索引值
 */
function getIndex(obj) {
    var aBrother = obj.parentNode.children;
    for (var i = 0, len = aBrother.length; i < len; i++) {
        if (aBrother[i] == obj) {
            return i;
        }
    }
}
/**返回相对于它同辈元素的位置的索引值。无参数
 * @returns {Number} 当前当前文档中其所在在位置,从0开始
 */
VQuery.prototype.index = function () {
    return getIndex(this.elements[0]);
};
工具函数. $函数
//函数包装器..可以不用new 了
function $(vArg) {
    return new VQuery(vArg);
}
工具函数
/**通过class类名来选取元素
 * @param   {Object} parent 父级对象,
 * @param   {String} sClass className类名
 * @returns {Array}  获取到的节点数组
 */
function getByClassName(parent, sClass) {
    if (parent.getElementsByClassName) {
        return parent.getElementsByClassName(sClass);
    } else {
        var oEle = parent.getElementsByTagName("*"),
            arr = [],
            reg = new RegExp("" + sClass + "");
        for (var i = 0, len = oEle.length; i < len; i++) {
            if (reg.test(oEle[i].className)) {
                arr.push(oEle[i]);
            }
        }
        return arr;
    }
}
/**
 *事件添加函数
 * @param {Object}   obj  需要绑定事件的对象
 * @param {String}   type 事件类型
 * @param {Function} fn   事件触发执行的函数
 */
function myAddEvent(obj, type, fn) {
    //标准
    if (obj.addEventListener) {
        obj.addEventListener(type, fn, false);
    } else if (obj.attachEvent) {
        //IE
        obj.attachEvent("on" + type, function () {
            //修改ie下this指向window的问题
            fn.call(obj);
        });
    } else {
        //最后选择
        obj["on" + type] = fn;
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86215.html

相关文章

  • task0002(二)- DOM + 事件

    摘要:调用函数,判断是否含有该指定样式,若含有的话删除该。分不同的情况来调用函数,并返回对象。慕课网探索之基础详解篇慕课网事件探秘。参考资料事件代理委托事件代理实现如下事件代理需要进行事件代理的父元素。 转载自我的个人博客 欢迎大家批评指正 DOM 添加class、移除class、是否同级元素、获取元素位置 先来一些简单的,在你的util.js中完成以下任务: // 为element增加...

    chadLi 评论0 收藏0
  • 用原生js写一个"多动症"简历

    摘要:用原生写一个多动症的简历预览地址源码地址最近在知乎上看到方应杭用写了一个会动的简历,觉得挺好玩的,研究一下其实现思路,决定试试用原生来实现。 用原生js写一个多动症的简历 预览地址源码地址 最近在知乎上看到@方应杭用vue写了一个会动的简历,觉得挺好玩的,研究一下其实现思路,决定试试用原生js来实现。 showImg(https://segmentfault.com/img/remot...

    Y3G 评论0 收藏0
  • Ajax设置请求和接收响应、自己封装简易jQuery.Ajax、回调函数

    摘要:设置请求和接收响应自己封装简易这篇文章是承接前几篇博客的是前几篇继续学习包括学习与理解和简化版自己实现等这篇文章只算是我的个人学习笔记内容没有精心排版一些错误请见谅所有代码都在这里从历史可以看到所有代码摆阔一个简易的服务器所有代码在历史里 Ajax设置请求和接收响应、自己封装简易jQuery.Ajax 这篇文章是承接前几篇博客的,是前几篇继续学习包括Ajax学习与理解和简化版自己实现j...

    Harpsichord1207 评论0 收藏0
  • 前后分离模型之封装 Api 调用

    摘要:和异步处理调用访问数据采用的方式,这是一个异步过程,异步过程最基本的处理方式是事件或回调,其实这两种处理方式实现原理差不多,都需要在调用异步过程的时候传入一个在异步过程结束的时候调用的接口。 Ajax 和异步处理 调用 API 访问数据采用的 Ajax 方式,这是一个异步过程,异步过程最基本的处理方式是事件或回调,其实这两种处理方式实现原理差不多,都需要在调用异步过程的时候传入一个在异...

    trilever 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<