我尝试使用vanilla javascript创建链接函数,如果只是链接它的工作,但如果在其他函数内它停止工作。
var doc = document,
M$ = function(el) {
var expr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/;
var m = expr.exec(el);
if(m[1]) {
return doc.getElementById(m[1]);
} else if(m[2]) {
return doc.getElementsByTagName(m[2]);
} else if(m[3]) {
return doc.getElementsByClassName(m[3]);
}
},
$ = function (el) {
this.el = M$(el);
// event function
this.event = function(type,fn) {
this.el.addEventListener(type,fn,false);
return this;
}
// forEach function
this.forEach = function(fn,val) {
for(var i = this.el.length - 1; i >= 0; i--) {
fn.call(val, i, this.el[i]);
}
return this;
}
if(this instanceof $) {
return this.$;
} else {
return new $(el);
}
};
//use
$("button").forEach(function(index, el)
// when i use function event, its not work
el.event("click", function() {
alert("hello");
});
// if i'm using addEventListener its work, but i want use event function
});
我的问题是,如何在forEach函数中使用事件函数? 谢谢你的帮助!
答案 0 :(得分:1)
首先,您遗失$("button").forEach(function(index, el)
之后代码中的括号会出现问题{
;
然后问题是,当你尝试在元素(按钮)上调用click-callback时,事实上,由于this
问题,元素(按钮)没有event()
属性。自this.el = M$(el);
走出forEach()
以来,它们甚至都没有定义。我调整并清理了一些你的代码,检查出来。我想现在它可以做你想要的:
var doc = document,
M$ = function(el) {
var expr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/;
var m = expr.exec(el);
if(m[1]) return doc.getElementById(m[1]); else if(m[2]) return doc.getElementsByTagName(m[2]); else if(m[3]) return doc.getElementsByClassName(m[3]);
},
$ = function(el) {
this.forEach = function(fn,val) {
// assign this.el and this.el[i].event inside forEach(), not outside
this.el = M$(el);
for(var i = this.el.length - 1; i >= 0; i--) {
this.el[i].event = function(type,fn) { this.addEventListener(type,fn,false); };
fn.call(val, i, this.el[i]);
}
}
return this;
};
$("button").forEach(function(index, el) {
el.event("click", function() { alert("hello, " + this.textContent); });
});
<button>btn1</button>
<button>btn2</button>
<强>更新强>
虽然之前的解决方案适用于在按钮上设置点击处理程序的特定目的,但我认为您真正想要的是模拟Jquery和链函数调用。我以这种方式改进了你的尝试:
var doc = document,
M$ = function(el) {
var expr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/;
var m = expr.exec(el);
if(m[1]) return doc.getElementById(m[1]);else if(m[2]) return doc.getElementsByTagName(m[2]); else if(m[3]) return doc.getElementsByClassName(m[3]);
},
$ = function (el) { //console.log(this);
this.el = M$(el);
this.event = function(type,fn) {
for(var i = this.el.length - 1; i >= 0; i--) this.el[i].addEventListener(type,fn,false);
}
this.forEach = function(fn) {
fn.call(this);
}
return this;
};
$("button").forEach(function() {
this.event("click", function() {
alert("hello, " + this.textContent);
});
});
<button>btn1</button>
<button>btn2</button>
理解这一点的关键是您的this
对象应始终等于$ {el: HTMLCollection(2), event: function, forEach: function}
。所以,
$("button")
您最初将其设置为$ {el: HTMLCollection(2), event: function, forEach: function}
; $("button").forEach(fn)
,使forEach
的上下文等于上一步中的this
; fn.call(this);
内拨打forEach()
您拨打回拨fn
并将相同的this
传递给它; fn
的回调this.event()
中 - 它有效,因为您的this
始终是第一步中的那个。this.event()
只是$.event()
我们只是遍历我们的HTMLCollection并为按钮上的click事件设置处理程序。内部$.event()
this
将等同于一个按钮元素,因为我们在点击事件的上下文中调用它,因此,this.textContent
会获取按钮的内容。谢谢,非常好的问题!
答案 1 :(得分:0)
首先要做的事情。
1
this.el = M$(el);
M$ = function(el) {
var expr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/;
var m = expr.exec(el);
if(m[1]) {
return doc.getElementById(m[1]);
} else if(m[2]) {
return doc.getElementsByTagName(m[2]);
} else if(m[3]) {
return doc.getElementsByClassName(m[3]);
}
}
当您定义M $时,如果按标签名称或类名获取元素,则可以使用HtmlCollection,如果按ID获取元素,则只需要一个元素。
然后你假设你的el可以是一个集合。
this.event = function(type,fn) {
this.el.addEventListener(type,fn,false);
return this;
}
如果您尝试获取所有按钮,则可能会收到一个集合。
2
如果您尝试运行已发布的代码,则会收到意外的标识符错误,因为您错过了{forEach(function(index, el)
之后。
3
如果你把那个{放在那里,你会收到一个el.event
并不是一个功能错误,因为你没有el
上的事件功能,但你有{{1} }}。
4
如果您将代码更改为:
$(el)
您将收到错误,因为您没有处理多个元素。见1个问题。
答案 2 :(得分:0)
看看这个。
var doc = document,
M$ = function(el) {
var expr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/;
var m = expr.exec(el);
if(m[1]) {
return Array.apply([],[doc.getElementById(m[1])]);
} else if(m[2]) {
return Array.apply([],doc.getElementsByTagName(m[2]));
} else if(m[3]) {
return Array.apply([],doc.getElementsByClassName(m[3]));
}
},
$ = function (el) {
if(! (this instanceof $)) {
return new $(el);
}
this.els = M$(el);
// event function
this.event = function(type,fn) {
this.forEach(function(index, el){
el.addEventListener(type,fn,false);
});
return this;
}
// forEach function
this.forEach = function(fn,val) {
for(var i = this.els.length - 1; i >= 0; i--) {
fn.call(val, i, this.els[i]);
}
return this;
}
return this;
};
//use
$("button").event("click", function() {
alert("hello");
});
M$ function
返回一个数组以保持一致。$().event
函数已更改为迭代this.els
中的所有元素。$("button").event
函数而不是$("button").forEach
函数来注册事件侦听器。参考:Demo 这个有效。但是,这是你想要的吗?我不确定。