无法在自定义插件中触发单击功能

时间:2017-04-09 09:43:49

标签: javascript function events javascript-events addeventlistener

我正在尝试编写自己的自定义纯JavaScript插件

这是我的示例插件代码:

(function() {
    var pMethods = {
        append: function(text) {
            var node = this.node;
            node.innerHTML += text;
        },
        click: function(fn) {
            if (this.node instanceof Array) {
                this.node.forEach(function(e) {
                    e.addEventListener('click', function() {
                        fn();
                    });
                }, this);
            } else {
                this.node.addEventListener('click', function(e) {
                    fn(e);
                });
            }
        }
    };
    myPlugin = function(selector) {
        this.node = document.querySelectorAll(selector);
        if (this.node.length === 1) {
            this.node = this.node[0];
        }
        return this.node;
    };
    myPlugin.prototype = pMethods;

    this.r = function(selector) {
        return new myPlugin(selector);
    };
}());

只有两个函数追加并单击

这是我的HTML

 <div class="close"></div>

现在我尝试在close div上添加click事件,如下所示:

r('.close').click(function() {
    alert('Hi')
});

但它没有按预期工作我不知道我在这里失踪

2 个答案:

答案 0 :(得分:1)

您的代码无效,因为您明确检查了元素集合是否为Array。返回的任何元素集合都是NodeList,它是一个类似于object的数组,但不是数组。

if (this.node instanceof Array)

应该是

if (this.node instanceof NodeList)

或者您可以使用Array.prototype.sliceNodeList转换为Array

this.node = Array.prototype.slice.call(
  document.querySelectorAll(selector)
)

以下是一些优化措施。

(function() {
  var pMethods = {
    append: function(text) {
      // iterate over the collection
      this.nodes.forEach(function(node) {
        node.innerHTML += text;
      })
      // return this for chaining
      return this
    },
    click: function(fn) {
      // iterate over the collection
      this.nodes.forEach(function(e) {
        e.addEventListener('click', fn);
      });
      // return this for chaining
      return this
    },
    find: function(selector) {
      return new myPlugin(
        // flat map over each of the nodes in the collection
        this.nodes.reduce(function(nodes, node) {
          return [].concat.apply(nodes, node.querySelectorAll(selector))
        }, [])
      )
    }
  };
  myPlugin = function(nodes) {
    // changed constructor to recievea array of elemnets only
    // it's private so won't affect anything else
    this.nodes = nodes
  };
  myPlugin.prototype = pMethods;

  this.r = function(selector) {
    var nodes = null
    // handle creating the object with normal elements
    if (selector instanceof HTMLElement) {
      nodes = [selector]
    }
    else {
      nodes = [].slice.call(
        document.querySelectorAll(selector)
      );
    }
    return new myPlugin(nodes);
  };
}());

r('.close')
  .click(function(e) {
    console.log('alerts suck! ' + e.target.textContent)
    r(e.target).find('.child').append(' appended child!')
  })
  .append(' append works!')
<div class="close">
  close
  <div class="child">this is the child</div>
</div>

答案 1 :(得分:0)

您的构造函数(例如myPlugin = function(selector) {)应该返回this而不是this.node