无法在HTML元素上调用函数

时间:2016-08-17 04:05:32

标签: javascript html

我开始在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不是函数(...)

2 个答案:

答案 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');

小提琴:https://jsfiddle.net/kxwt9gmg/

答案 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;
}
相关问题