0

在输入 $("div")类似的数组时,它会[<div>1</div><div>2</div><div>3</div>]从中
获取一堆方法jQuery.fn,我对模拟它很感兴趣,但我不能让它“顺利”
,我参考了 zepto.js:

  zepto.Z = 函数(dom,选择器){
    dom = dom || []
    dom.__proto__ = arguments.callee.prototype
    dom.selector = 选择器 || ''
    返回域
  }

但由于它不是跨浏览器,我写了一些片段如下:

var query=function(selector){    
  return new query.init(selector);    
};
query.init=function(selector){
   var found=document.querySelectorAll(selector);
   this.length=found.length;
   for(var i=0,len=this.length;i<len;i++){
     this[i]=found[i];
    }
  return this;
};
query.init.prototype={
  method1:function(){},
  method2:function(){}
} 

打字时query("#id"),虽然它可以在功能上进行操作,但它看起来还不够好,
在此处输入图像描述
如您所见,如何编写一个看起来像 jQuery 的查询函数?谢谢

4

1 回答 1

1

您可能想从简单的事情开始,例如:

function MaterObject(selector) {
  this.selector = selector;
  this.elements = document.querySelectorAll(selector);
}

现在通过 MasterObject.prototype 添加功能:

MasterObject.prototype = {
  getLength: function() {
    return this.elements.length;
  },

  refresh: function() {
    this.elements = document.querySelectorAll(this.selector);
    return this;
   },

  addMore: function(selector) {
    this.selector = this.selector + ',' + selector;
    this.refresh();
    return this;
   }
}

等等。要启动它:

function $(selector) {
  return new MasterObject(selector);
}

以上缺乏功能测试,因此很脆弱。

请注意,大部分 jQuery 都是重载的,因此它需要测试给出的内容,然后决定处理结果(想到著名的“isArray”案例)。调用方法可能会对选择器选择的所有元素或仅第一个元素执行某些操作。向方法传递字符串、对象或任何内容都可能完全改变方法的作用。

请注意,函数可以返回this,因此可以链接方法。但问题是(对于库设计者和用户来说)是确定哪些应该是可链接的,哪些不应该,例如

var $x = $('div');

// addMore is chainable, getLength isn't
$x.addMore('p').getLength();

编辑

如果您希望您的“jQuery”对象成为一个数组,那么您必须将所有要继承的方法添加到 Array.prototype,这不是一个好主意。没有其他办法,你不能创建一个数组对象并将你自己的原型对象插入到它的[[Prototype]]链中,一个数组实例将直接继承自 Array.prototype。

您可以做的最好的是将元素 NodeList 转换为数组(就像您在 OP 中所做的那样)并在其上调用类似数组的方法(注意,因此,选择器可能不代表元素数组的内容):

function MasterObject(selector) {
  this.selector = selector;
  this.elements = [];
}

MasterObject.prototype = {
  ...

  refresh: function() {
    this.elements = [];
    var els = document.querySelectorAll(this.selector);
    for (var i=0, iLen=els.length; i<iLen; i++) {
      this.elements[i] = els[i];
    }
    return this;
  },

  pop: function() {
    return this.elements.pop();
  },

此类更改可能会反映在 DOM 中(在这种情况下,选择器应该与内容同步,而不必通过 qSA 再次选择它):

  popElement: function() {
    var el = this.elements.pop();
    el.parentNode.removeChild(el);
    return el;
  },

  ...
};

function $(selector) {
  var newObj = new MasterObject(selector); 
  newObj.refresh();
  return newObj;
}
于 2012-06-25T02:47:57.463 回答