四、 根据jquery学架构思想

57 阅读1分钟

实现下面功能:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .blue {
            color: blue
        }
    </style>
    <script src="./test.js"></script>
</head>

<body>
    <div class="p-con">
        <p>111</p>
        <p>222</p>
        <p>333</p>
        <p class="p4">444</p>
    </div>
    <script>
        $('.p4').addClass('blue')  
        $('p').setText('hello world')      
    </script>
</body>

</html>

初级版:

// 匿名自执行函数
// 1 自执行
// 2 防止变量污染 (涉及到AO,函数自执行完后会被销毁)
(function (window) {
    window.$ = jquery = function (nodeSelector) {
        // 1 判断传入的是不是string
        const nodes = {}
        if (typeof nodeSelector !== 'string') {
            throw new Error('必须输入字符串')
        }
        let temp = document.querySelectorAll(nodeSelector)
        for (let i = 0; i < temp.length; i++) {
            nodes[i] = temp[i]
        }
        nodes.length = temp.length

        // 添加方法
        nodes.addClass = function(classes) {
            let className = classes.split(' ')
            className.forEach(value => {
                for (let i = 0; i < nodes.length; i++) {
                    nodes[i].classList.add(value)
                }
            })
        }

        // 修改text
        nodes.setText = function(text) {
            for (let i = 0; i < nodes.length; i++) {
                nodes[i].textContent = text
            }
        }
        return nodes
    }
}) (window)

进阶版:

// 优化一: 优化外部结构的调用
// 优化二: 方法太散漫
// 优化三: for循环封装
const $ = jQuery = (function(){
    const JqFn = function(nodeSelector) {
        this.nodes = document.querySelectorAll(nodeSelector)
    }
    JqFn.prototype = {
        each: function(callback) {
            for (let i = 0; i < this.nodes.length; i++) {
                callback.call(this, this.nodes[i], i)
            }
        },
        addClass: function(classes) {
            const classNameArray = classes.split(' ')
            classNameArray.forEach(value => {
                this.each((item, index) => {
                    item.classList.add(value)
                })
            })
        },
        setText: function(text) {
            this.each((item, index)=> {
                item.textContent = text
            })
        }
    }
    return function(selector) {
        return new JqFn(selector)
    }
})()

终极版:(还没学明白)

调用:

let pCon = $('.p-con')
        pCon.find('p').eq(1).remove()  

        let aa = function() {
        }
        console.log($.isFunction(aa))

实现:

let $ = jQuery = (function(window) {
    // dom存储
    function Query (dom, selector) {
        let i, len = dom ? dom.length : 0
        for (i = 0; i < len; i++) this[i] = dom[i]
        this.length = len
        this.selector = selector || ''
        return this
    }
    // 生成jquery对象
    function Z (elements, selector) {
        return Query.call(this, elements, selector)
    }
    // 具体dom查找
    function qsa(element, selector) {
        return element.querySelectorAll(selector)
    }
    
    Z.prototype = {
        each(callback) {
            [].every.call(this,function(el, index) {
                return callback.call(el, index, el) !== false
            })
        },
        find(selector) {
            let doms = []
            this.each(function(index, el) {
                let childs = this.querySelectorAll(selector)
                doms.push(...childs)
            })
            return new Z(doms, selector)
        },
        eq(i) {
            let doms = []
            this.each(function(index, el) {
                if (i === index) {
                    doms.push(this)
                }
            })
            return new Z(doms, this.selector)
        },
        remove() {
            this.each(function(index, el) {
                this.remove()
            })
        }
    }
    function isFunction(value) {
        return typeof value == 'function'
    }
    function $(nodeSelector) {
        let doms = qsa(document, nodeSelector)
        return new Z(doms, nodeSelector)
    }
    $.isFunction = isFunction
    return $
})()