jQuery源码仿写

虽然现代前端已经是MVVM框架的天下,但是在jQuery中的一些设计模式和思想还是值得我们借鉴和学习的。本文主要分实现了一些开发中使用比较频繁的方法和函数。由于能力有限,如有不妥的地方还请多多指教。

class Jq {
    constructor(arg, root) {
        if (typeof root === 'undefined') {
            this['prevObject'] = [document];
        } else {
            this['prevObject'] = root;
        }
        // $(function(){console.log('解决')})
        if (typeof arg === 'function') {
            this.ready(arg)
        } else if (typeof arg === 'string') {
            // console.log($('li'))
            const ele = document.querySelectorAll(arg);
            this.addELement(ele)
        } else {
            //传入js原生节点;
            // console.dir(arg)
            if (typeof arg.length === 'undefined') {
                // 一个对象节点;
                // $(document.querySelectorAll('#wrap'))
                this[0] = arg;
                this.length = 1;
            } else {
                // 多个对象节点
                // $(document.querySelectorAll('ul li'))
                this.addELement(arg);
            }
        }
    }
    // 返回上一次的prevObject
    end() {
        return this['prevObject']
    }
    // 注意链式调用
    eq(index) {
        return new Jq(this[index], this)
    }
    // 添加元素
    addELement(ele) {
        // 处理HtmlCollectionList
        ele = Array.from(ele);
        ele.forEach((el, i) => {
            this[i] = el;
        })
        this.length = ele.length;
    }
    // dom结构加载完毕执行代码
    ready(cb) {
        window.addEventListener('DOMContentLoaded', cb, false)
    }
    // 注册点击事件
    click(cb) {
        for (let i = 0; i < this.length; i++) {
            this[i].addEventListener("click", cb, false)
        }
    }
    // on函数注册事件
    on(eventSource, cb) {
        const reg = /\s+/g;
        eventSource = eventSource.replace(reg, ',');
        const eventSourceArray = eventSource.split(',');
        for (let i = 0, len = this.length; i < len; i++) {
            for (let j = 0, length = eventSourceArray.length; j < length; j++) {
                this[i].addEventListener(eventSourceArray[j], cb, false);
            }
        }
    }
    css(...arg) {
        if (arg.length === 1) {
            if (typeof arg[0] === 'string') {
                if(arg[0] in $.cssHooks) {
                    // 只获取第一个
                    return $.cssHooks[arg[0]].get(this[0])
                }
                // css('background') 只获取this[0]的样式
                return this.getStyle(this[0], arg[0])
            } else {
                // css({'width':'200px','height':'200px'}))
                console.log(arg) // [{'width':'200px','height':'200px'}]
                for (let i = 0, len = this.length; i < len; i++) {
                    for (let j in arg[0]) {
                        this.setStyle(this[i], j, arg[0][j])
                    }
                }
            }
        } else {
            console.log(arg) // ["width", "200px"]
            for (let i = 0, len = this.length; i < len; i++) {
                this.setStyle(this[i], arg[0], arg[1])
            }
        }
    }
    setStyle(ele, attr, value) {
        // 处理需要加单位的属性
        if (typeof value === 'number' && !(attr in $.cssNumber)) {
            value = value + 'px';
        }
        // 增加cssHooks判断
        if (attr in $.cssHooks) {
            $.cssHooks[attr].set(ele, value)
        } else {

            ele.style[attr] = value
        }
    }
    getStyle(ele, styleName) {
        return window.getComputedStyle(ele, null)[styleName]
    }
}

function $(arg) {
    return new Jq(arg)
}
// 以下属性都不需要加单位
$.cssNumber = {
    animationIterationCount: true,
    columnCount: true,
    fillOpacity: true,
    flexGrow: true,
    flexShrink: true,
    fontWeight: true,
    gridArea: true,
    gridColumn: true,
    gridColumnEnd: true,
    gridColumnStart: true,
    gridRow: true,
    gridRowEnd: true,
    gridRowStart: true,
    lineHeight: true,
    opacity: true,
    order: true,
    orphans: true,
    widows: true,
    zIndex: true,
    zoom: true
}
// cssHooks
$.cssHooks = {}

以上只是自己看了源码之后的仿写,可能实现不是太优雅。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值