关于模拟Jquery选择器方法

时间:2012-06-25 01:51:17

标签: javascript jquery

虽然排除了$("div"),但有一个类似[<div>1</div><div>2</div><div>3</div>]的数组 从jQuery.fn获取了一堆方法,我对模拟它很感兴趣,但我无法做到这一点#34;顺利&#34;
我提到了zepto.js:

  zepto.Z = function(dom, selector) {
    dom = dom || []
    dom.__proto__ = arguments.callee.prototype
    dom.selector = selector || ''
    return dom
  }

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

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")时输入

,但它可以在功能上操作,但它看起来不够好 enter image description here
如你所见,如何编写一个看起来像jQuery的查询函数?谢谢

1 个答案:

答案 0 :(得分: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();
  },

Perphaps这样的更改应该反映在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;
}