我正在创建一个迷你库,试图至少部分地重建jQuery
用于学习目的的方式,并更好地理解面向对象编程的工作原理。
我已经重新创建了jQuery
种方法click
和addClass
,但当我将它们称为:
$(".class1").click(function() {
$(".class1").addClass("class2"); // Works, but it adds class2 to all elements
this.addClass("class2"); // Doesn't work
});
我得到Uncaught Error
说this.addClass
不是函数,这是正常的,因为我不能访问其他对象的方法。
jQuery中$(this)
如何表示触发事件的DOM元素,因此在我的情况下我可以使用它仅将class2
添加到元素单击而不是所有具有类class1
的元素?
P.S:我试过阅读jQuery文件,但我觉得这些水域对我来说太深了。
修改:
我一直很感谢Stack Overflow提供的所有答案和帮助,但告诉我使用$(this)
代替this
并不能解决我的问题,因为{{1}我的代码中不存在。我正在努力学习如何创建类似jQuery的$(this)
&它背后的逻辑是什么。
$(this)
方法定义如下:
click
答案 0 :(得分:2)
您需要使用call
,apply
,bind
或其中某些组合来设置回调的上下文到DOM节点。这是jquery的each
方法的一个人为设想的例子,它使用call
设置回调的上下文:
var $ = {
each: function(selector, callback) {
var collection = Array.from(document.querySelectorAll(selector));
collection.forEach(function(element, index) {
// the magic...
callback.call(element, index, element);
});
}
}
$.each('.foo', function(idx, el) {
console.log(this.textContent);
});
答案 1 :(得分:1)
this
是本机JavaScript元素,仅公开本机API。您需要将它传递给jQuery构造函数才能访问jQuery的API
$(this).addClass("class2"); // This will work
答案 2 :(得分:0)
一种可能的方式(只接受选择器):
$ = function(selector) {
this.elements = '';//Select the element(s) based on your selector
this.addClass = function(klass) {
//apply your klass to you element(s)
return this;
};
this.click= function(handler) {
//Attach click event to your element(s)
return this;
};
return this;
};
请记住,这只是一个例子。
修改1:
在click
方法中,您在错误的范围内调用处理程序(匿名函数范围)。您需要使用外部范围:
$.prototype = {
click: function(callback) {
console.log(this.length);
var _self = this;
for (var i = 0; i < this.length; i++) {
this[i].onclick = function(event) {
//this here presents the anonymous function scope
//You need to call the handler in the outer scope
callback.call(_self, event);
//If you want to call the handler in the Element scope:
//callback.call(_self[i], event);
}
}
}
}
注意:在您的示例中,this.addClass("class2");
不起作用,因为jQuery调用Element
范围而不是jQuery
范围内的Click处理程序。因此,this
显示Element
没有addClass
方法;
答案 3 :(得分:0)
好的,我现在明白你的问题。让我试着再次帮助你。
当你将它提供给选择器时,jQuery不知道你使用什么DOM元素。它不解析它或其他东西。只需将其保存到内部属性即可。
非常简化的代码:
$ = function(e) {
// finding object. For example "this" is object
if (typeof e !== 'object' || typeof e.className === 'undefined') {
if (typeof e == 'string') {
if (e[0] == '#') {
e = document.getElementById(e.substring(1));
} else if (e[0] == '.') {
e = document.getElementsByClassName(e.substring(1))[0];
} else {
// ... etc
}
}
// ... etc
}
var manager = {
elem: e,
addClass: function(newClass) {
manager.elem.className = manager.elem.className + ' ' + newClass;
return manager;
},
click: function(callback) {
// here is just simple way without queues
manager.elem.onclick = function(event) {
callback.call(manager, event);
}
}
}
return manager;
}
答案 4 :(得分:0)
凭借额外1。5年的经验,这个问题变得相当容易。
$
,这样除了字符串选择器外,它还可以接受HTML
元素。HTML
元素的对象的新实例。addClass
作为上下文调用。<强>代码:强>
;(function() {
/* The object constructor. */
function ElementList(arg) {
/* Cache the context. */
var that = this;
/* Save the length of the object. */
this.length = 0;
/* Check whether the argument is a string. */
if (typeof arg == "string") {
/* Fetch the elements matching the selector and inject them in 'this'. */
[].forEach.call(document.querySelectorAll(arg), function(element, index) {
that[index] = element;
that.length++;
});
}
/* Check whether the argument is an HTML element and inject it into 'this'. */
else if (arg instanceof Element) {
this[0] = arg;
this.length = 1;
}
}
/* The 'click' method of the prototype. */
ElementList.prototype.click = function(callback) {
/* Iterate over every element and set the 'click' event. */
[].forEach.call(this, function(element) {
element.addEventListener("click", function(event) {
callback.call(this, event);
});
});
}
/* The 'addClass' method of the prototype. */
ElementList.prototype.addClass = function(className) {
/* Iterate over every element. */
[].forEach.call(this, function(element) {
/* Cache the classList of the element. */
var list = element.classList;
/* Add the specified className, if it doesn't already exist. */
if (!list.contains(className)) list.add(className);
});
}
/* The global callable. */
window.$ = function(arg) {
return new ElementList(arg);
}
})();
/* Example */
$("#b1").click(function() {
$(this).addClass("clicked");
console.log(this);
});
<button id="b1">Click</button>