我开始在Vanilla JS中编写jQuery并且我的选择器工作但是当我在HTML元素上调用我的append函数时,我得到一个“不是函数”错误。
var $ = function(){
this.select = function(input) {
if (input.split("")[0] == "#") {
input = input.slice(1, input.length)
return document.getElementById(input)
}
else if (input.split("")[0] == ".") {
input = input.slice(1, input.length)
return document.getElementsByClassName(input)
}
else {
return document.getElementsByTagName(input)
}
},
this.append = function(text) {
return this.innerhtml = this.innerhtml + text
}
};
我的控制台尝试:
var myQuery = new $();
返回undefined
myQuery.select("#testspan")
在此处返回我的span
标记
myQuery.select("#testspan").append("hellohello")
返回错误
VM2207:1未捕获TypeError:myQuery.select(...)。append不是函数(...)
答案 0 :(得分:2)
从您的代码段返回每个select
方法返回一个DOM元素(或集合)。您真正想要做的是调用Chaining
,其中方法的结果返回原始对象。因此,您可以继续在同一个对象上调用其他方法。
现在,在您的示例中,您将需要一个元素集合(nodes
),然后对象可以再次访问。这是一个简单的例子。
var $ = function () {
this.nodes = [];
this.select = function (input) {
var self = this;
if (input.split("")[0] == "#") {
input = input.slice(1, input.length)
var node = document.getElementById(input);
if (node)
this.nodes.push(node);
}
else if (input.split("")[0] == ".") {
input = input.slice(1, input.length)
Array.prototype.slice.call(document.getElementsByClassName(input), 0).forEach(function (node) {
self.nodes.push(node);
});
}
else {
Array.prototype.slice.call(document.getElementsByTagName(input), 0).forEach(function (node) {
self.nodes.push(node);
});
}
return this;
},
this.append = function (text) {
this.nodes.forEach(function (i) {
i.innerHTML += text;
});
return this;
}
};
示例Html:
<p id="test">This is test </p>
<p>This is number to</p>
控制台(Chrome):
$ = new $()
$ {nodes: Array[0]}
$.select('p').append('hi')
现在这里的一个小问题是你(在控制台中)设置$ = new $()
,它有效地覆盖了在同一个脚本中再次调用new $()
的能力。我在下面提供了一个小提琴,将其重命名为myQuery
。每次调用select时也会更改,清除node
数组。
修:
var myQuery = function () {
this.nodes = [];
this.select = function (input) {
this.nodes = [];
var self = this;
if (input.split("")[0] == "#") {
input = input.slice(1, input.length)
var node = document.getElementById(input);
if (node)
this.nodes.push(node);
}
else if (input.split("")[0] == ".") {
input = input.slice(1, input.length)
Array.prototype.slice.call(document.getElementsByClassName(input), 0).forEach(function (node) {
self.nodes.push(node);
});
}
else {
Array.prototype.slice.call(document.getElementsByTagName(input), 0).forEach(function (node) {
self.nodes.push(node);
});
}
return this;
},
this.append = function (text) {
this.nodes.forEach(function (i) {
i.innerHTML += text;
});
return this;
}
};
$ = new myQuery();
$.select('p').append(' test selection by tag name ');
$ = new myQuery();
$.select('.p1').append(' test selection by class ');
$ = new myQuery();
$.select('#p1').append(' test selection by id ');
$ = new myQuery();
$.select('#p2').append(' test selection by id ').append('and then chanined').select('.p2').append(' still chaining');
答案 1 :(得分:1)
你需要改变一下你的方法。您希望存储结果并在其上调用方法。您只能调用该特定对象具有的方法。你要返回的那个对象,原始的html元素,没有那个方法。你想要做的是存储html元素,然后返回一个对存储的内容执行操作的OBJECT。你可以使用闭包来完成这个。例如:
function miniQuery(input){
function elementIterate(collection, action){
for (var i = elements.length -1; i >= 0; i-- ){
collection[i].style.display = action;
}
}
var isCollection = function(element){
if(element instanceof HTMLCollection){
return true
} else{
return false
}
}
function findElement(element){
if (element.startsWith("#")) {
// id element selector
return document.getElementById(element.substring(1));
} else if (element.startsWith(".")) {
// class element selector
return document.getElementsByClassName(element.substring(1));
} else {
// tag element selector
return document.getElementsByTagName(element);
};
}
if (input != undefined) {
var _this = this;
this.element = findElement(input);
var elements = findElement(input);
}
return {
append: function(content, position = 'beforeend'){
var elements = _this.element;
if (isCollection(elements)) {
for(var i = elements.length -1; i >= 0; i--){
elements[i].insertAdjacentHTML(position, content)
}
}else{
elements.insertAdjacentHTML(position, content);
}
}
}
}
function $(input){
return selector(input);
}
function selector(input){
var query = new miniQuery(input);
return query;
}