经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » jQuery » 查看文章
jQuery(三)之 选择器(基础版)
来源:cnblogs  作者:xy2370  时间:2019/9/10 10:54:13  对本文有异议

对于jQuery的调用,我们一般都会传入参数

  1. html: <div></div>
  2. js: console.log($('<a />'));
  3. console.log($('div'));

Image text

一、前置(DOM对象和jQuery对象)

  1. DOM对象,
    关于这个,应该是前端的基础知识了,在文档对象模型中,每个部分都是节点。
  2. jQuery对象
    这个是指通过jQuery构造函数创建出来的对象,可以通过jQuery选择器获取到,并以类数组的形式保存在jQuery中

二、实践

仔细观察返回的jQuery对象,感觉像是对DOM节点进行封装,并将其保存在jQuery上

一、实现一个基本的创建选择器
  1. 获取到传入参数,判断是创建一个jquery节点,还是查询节点,
  2. 创建新节点,传入的是一个html标签,以此进行判断
  1. //获取到传入的参数
  2. var jQuery = function(selector, content) {
  3. return new jQuery.prototype.init(selector, content);
  4. }
  5. jQuery.prototype = {
  6. length: 0,
  7. init: function(selector, content) {
  8. content = content || document;
  9. var match; //match 用来保存selector;
  10. if(typeof selector === 'string') {
  11. // 判断selector传入的是一个html标签;
  12. if(selector.charAt(0) === '<' && selector.charAt(selector.length-1) === '>' && selector.length >= 3 ) {
  13. match = [selector];
  14. }
  15. if (match) {
  16. //创建一个jQuery对象。
  17. }
  18. }
  19. }
  20. }
  1. 确定好是需要创建一个节点之后,我们就需要思考需要进行什么操作。需要将标签名解析出来,然后利用createElement创建节点,并保存。
    • 定义一个html解析函数
    1. var reg = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
    2. jQuery.extend({
    3. parseHtml: function(data, content) {
    4. if (!data && typeof data != 'string') {
    5. return null;
    6. }
    7. var parse = reg.exec(data);
    8. return [content.createElement(parse[1])] //ok,这里是将创建的一整个DOM节点保存在了数组中。
    9. }
    10. })
    • 已经可以获取到创建的节点了,下面将节点挂载在jQuery上就可以了。
    1. if(match) {
    2. for(; i < match.length; i++) {
    3. var opt = match[i]
    4. this[i]=jQuery.parseHtml(opt, content)[i]
    5. }
    6. }

    好了,现在我们就可以看下代码的执行结果了。
    image text
    ok,勉强可以实现,但好像还是有点不对的样子, 让我们来看下jQuery的源码。
    image text
    可以看出是调用了merge方法。跳转到merge方法查看一下,一般来说,merge用于合并两个数组, 也可以用于将数组合并在有length属性的对象上。

    1. // push.apply(_, arraylike) throws on ancient WebKit
    2. merge: function (first, second) {
    3. var len = +second.length,
    4. j = 0,
    5. i = first.length;
    6. for (; j < len; j++) {
    7. first[i++] = second[j];
    8. }
    9. first.length = i;
    10. return first;
    11. }
    了解的区别后,我们来优化代码吧,
  2. 优化

二、实现一个基本的标签选择器
  1. DOM原生节点查询
    • document.querySelector
    • document.querySelectorAll //返回一个NodeList
  2. 实践
    利用document原生查取节点的方式,获得结果,再将其每一个放在jQuery上
  1. var ele, i = 0;
  2. if(match) {}
  3. else {
  4. ele = document.querySelectorALL(selector);
  5. for(; i < ele.length; i++) {
  6. this[i] = ele[i]
  7. }
  8. this.length = ele.length;
  9. }
三、关于传入一个方法的选择器
  1. 首先看下init中是如何处理的:
  1. var rootjQuery;
  2. init = jQuery.fn.init = function(selector, context, root) {
  3. ...
  4. root = root || rootjQuery;
  5. if(typeof selector === 'string') {
  6. ...
  7. } else if (isFunction(selector)) {
  8. return root.ready !== undefined ? root.ready(selector) : selector(jQuery);
  9. }
  10. }
  11. rootjQuery = jQuery(document);

代码可以看出,其实js是可以传递三个参数的,且root默认为document,如果root.ready没有初始话的话就立刻执行传入的方法,否则调用root.ready方法。关于root,从代码可以看出,是个全局,那么root.ready == jQuery.ready。

  1. 在看ready方法前,需要明确一个问题,jquery传入方法的处理是在文档加载之后执行,所以首先应该对文档是否加载完毕进行判断。
  1. function completed() {
  2. document.removeEventListener('DOMContentLoaded',completed);
  3. window.removeEventListener('load', completed);
  4. jQuery.ready();
  5. }
  6. if(document.readyState === 'complete' || (document.readyState !== "loading" && !document.documentElement.doScroll)) {
  7. window.setTimeout(jQuery.ready);
  8. } else {
  9. //dom加载完毕后,调用complate移除监听事件。
  10. document.addEventListener('DOMContentLoaded', complete);
  11. window.addEventListener('load', completed);
  12. }
  1. 可以看下jQuery.ready方法了。
  1. jQuery.extend({
  2. // DOM是否已经准备好要使用了,发生更改,则修改为true;
  3. isReady: false,
  4. //跟踪就绪事件触发前要等待的项目数计数器
  5. readyWait: 1,
  6. ready: function(wait) {
  7. if(wait === true ? --jQuery.readyWait : jQuery.isReady) {
  8. return ;
  9. }
  10. //DOM节点已经准备好了
  11. jQuery.isReady = true;
  12. if(wait !== true && --jQuery.readyWait > 0) {
  13. return
  14. }
  15. //如果有函数绑定,立即执行。
  16. readyList.resolveWidth(document, [jQuery])
  17. }
  18. })

从2.的时候可以看出,在DOM节点加载完的时候,调用了一次ready,此时没有传入wait,ready中第一个判断直接跳过,记录jQuery.isReady = true,然后再看下一句执行,调用readyList.resolveWidth方法,此时DOM节点已经加载完毕,可以执行绑定的函数了,
关于这个readyList是什么,我们在代码中找一下看下,

  1. var readyList = jQuery.Deferred();
  2. jQuery.fn.ready = function(fn) {
  3. ready.then(fn).catch(error) {
  4. jQuery.readyException(error);
  5. }
  6. return this;
  7. }

从以上代码可以看出,readyList是Deferred函数的返回值,且从下面的调用,可以推测Defferred函数应该是个promise对象。对于Defferred函数,下次再仔细研究一下。
现在让我们来回顾整个函数流程:
Image text
上面的内容只是我自己的理解,如果有什么不对的地方,希望大家帮忙指出啊!

原文链接:http://www.cnblogs.com/xya-b/p/11492181.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号