• jQuery分析(2)


    前言

    从这节进入jQuery的世界,首先从jQuery的入口函数开始了解jQuery()或$是如何运作的,这里我给出了一个最小的例子来分析。

    回忆

    在进入分析代码前我们回想下jQuery的使用方法有哪些呢?

    • selector,[context]
      • selector:用来查找的字符串
      • context:作为待查找的 DOM 元素集、文档或 jQuery 对象。
    • element
      • 一个用于封装成jQuery对象的DOM元素
    • object
      • 一个用于封装成jQuery对象
    • elementArray
      • 一个用于封装成jQuery对象的DOM元素数组。
    • jQuery object
      • 一个用于克隆的jQuery对象。
    • jQuery()
      • 返回一个空的jQuery对象。

    大家知道$函数等于jQuery函数,在调用完$函数后它会选择出传递第一个参数对应的元素或创建一个新元素,如果给定了第二个参数(context)那就是从context这个上下文向下查找。实现原理并不难,复杂的是涉及的逻辑相对多和兼容性问题。接下来是我整理的一个jQuery最小框架,我们一起来看看jQuery如何实现$('div').width()神奇的方法。

    jQuery库本质的实现原理(对象模拟数组)源码 官方完整源码地址 / 简化版源码地址

    (function() {
        var jQuery = function(selector) {
            return new jQuery.fn.init(selector);
        };
        jQuery.fn = jQuery.prototype = {
            selector: "",
            length: 0,
            constructor: jQuery,
            find: function(selector) {
                var ret = [];
                ret.push(document.getElementById(selector));
                ret = this.pushStack(ret);
                ret.selector = selector;
                return ret;
            },
            pushStack: function(elems) {
                var ret = this.constructor();
                for(var i = 0, il = elems.length; i < il; i++) {
                    ret[i] = elems[i];
                }
                ret.length = i;
                ret.prevObject = this;
                ret.context = this.context;
                return ret;
            },
            msg: function() {
                console.log('test function');
            }
        };
    
        var init = jQuery.fn.init = function(selector) {
            if(!selector) {
                return this;
            }
            if(typeof selector == 'string') {
                return rootjQuery.find(selector);
                //return document.getElementById(selector);
            } else if(selector.nodeType) {
                this.context = this[0] = selector;
                this.length = 1;
                return this;
            }
        };
        init.prototype = jQuery.fn;
        var rootjQuery = jQuery(document);
        window.$ = jQuery;
    })();
    

    上面的代码是我在抛开了jQuery的其他逻辑后整理出来它的架构的基础,接着一步一步来仔细看看他是如何运行的。

    jQuery框架核心步骤

    • 对于一个jQuery对象的调用分2种:
      • 新选择一个元素或者创建一个元素(在jQuery函数中new一个jQuery.fn.init构造函数)
      • 执行一个jQuery对象方法(执行jQuery在原型链上的方法)
    • 对传入的selector进行不同操作解析(不传入任何参数将返回一个空的jQuery对象实例)
    • 对于传入一个选择器参数进行find查找元素,对于传入字符串参数进行DOM解析创建元素
    • 创建一个新的jQuery对象,将以上选择好的元素或者创建好的DOM节点用数组的方式合并到新的jQuery对象中并返回

    $('div') 方法调用顺序图

    框架代码关键点

    • jQuery.fn = jQuery.prototype
    • jQuery.fn.init
    • pushStack

    jQuery.fn = jQuery.prototype 这个对象是jQuery对象的原型链当使用 $('div') 创建出来的jQuery对象便拥有改对象的所有方法

    jQuery.fn.init 函数对传入的参数selector进行不同类型的解析,如果selector是一个字符串则找到他的id的元素。

    jQuery.fn.init = function(selector) {
        if (!selector) {
            return this;
        }
        if (typeof selector == 'string') {
            // 是字符串则找到这个字符串id的元素
            return rootjQuery.find(selector);
        } else if (selector.nodeType) {
            // 如果是dom元素直接赋值和修正length,最后返回this
            this.context = this[0] = selector;
            this.length = 1;
            return this;
        }
    };
    

    pushStack首先创建一个空的jQuery对象,然后把查找到的元素合并到空对象中并进行length修正,最后修改prevObject以便最上次操作的元素进行跟踪(详细请见end()函数)

    pushStack: function(elems) {
        // 创建一个空的jQuery对象
        var ret = this.constructor();
        // 把找到的元素放入ret空对象中
        for (var i = 0, il = elems.length; i < il; i++) {
            ret[i] = elems[i];
        }
        // 修正length
        ret.length = i;
        // 跟踪上次更改元素操作
        ret.prevObject = this;
        // 修正上下文
        ret.context = this.context;
        // 返回装好元素的jQuery对象
        return ret;
    }
    

    调用jQuery.prototype原型链上的msg函数示例

    var elem = $('div');
    elem.msg();    // test function
    

    总结

    分析jQuery或$函数执行流程,用简化版例子分析jQuery从入口函数到返回jQuery对象过程中都做了什么事情并且对 $('div').msg() 调用方法进行了分析。通过这个简化版例子了解jQuery的基础架构。这对于以后的学习是必要。

    如有疏忽、遗漏、错误请狠狠批评谢谢。

  • 相关阅读:
    C语言得到当前系统时间
    【solr这四个主题】在Tomcat 部署Solr4.x
    MySQL 一般查询日志(General Query Log)
    iOS7 UIKit动力学-碰撞特性UICollisionBehavior 上
    Java Persistence with MyBatis 3(中国版) 第五章 与Spring集成
    Kaggle入门——使用scikit-learn解决DigitRecognition问题
    Effective C++:规定34:区分接口继承和实现继承
    Critical thinking and Thoughtful writing
    我的时间,GTD做主
    jquery自己主动旋转的登录界面的背景代码登录页背景图
  • 原文地址:https://www.cnblogs.com/monsterooo/p/5479642.html
Copyright © 2020-2023  润新知