x-tag 事件委托:访问根元素

x-tag event delegation: accessing the root element

我需要将 'tap' 事件委托给自定义元素中的关闭按钮,然后调用根元素上的 close() 方法。这是一个例子:

xtag.register('settings-pane', {
  lifecycle: {
    created: function () {
      var tpl = document.getElementById('settings-pane'),
          clone = document.importNode(tpl.content, true);
      
      this.appendChild(clone);
    }
  },
  events: {
    'tap:delegate(button.close)': function (e) {
      rootElement.close(); // <- I don't know the best way to get rootElement
    }
  },
  methods: {
    close: function () {
      this.classList.add('hidden');
    }
  }
});
<template id="settings-pane">
  <button class="close">✖</button>
</template>

在处理了几个月之后,解决这个问题的最佳方法是创建另一个 "pseudo",类似于 :delegate() 伪,但调用回调的方式不同。这将 :descendant() 伪添加到 xtag:

xtag.pseudos.descendant = {
    action: function descendantAction(pseudo, event) {
        var match,
            target = event.target,
            origin = target,
            root = event.currentTarget;
        while (!match && target && target != root) {
            if (target.tagName && xtag.matchSelector(target, pseudo.value)) match = target;
            target = target.parentNode;
        }
        if (!match && root.tagName && xtag.matchSelector(root, pseudo.value)) match = root;
        return match ? pseudo.listener = pseudo.listener.bind({component: this, target: match, origin: origin}) : null;
    }
};

您可以像 :delegate() 一样使用它,但是 this 将引用一个对象,该对象又将引用目标元素(与 CSS 选择器匹配的元素,例如 button.close)、来源(接收事件的元素)和组件(自定义元素本身)。使用示例:

xtag.register('settings-pane', {
    methods: {
        close: function () {
            this.classList.add('hidden');
        }
    },
    events: {
        'tap:descendant(button.close)': function (e) {
            this.origin;    // <button> or some descendant thereof that was tapped
            this.target;    // <button> element
            this.component; // <settings-pane> element

            this.component.close(); 
        }
    }
});

嘿,这是图书馆的作者,让我澄清一下:

对于您在 DOM、X-Tag 或 vanilla JS 中设置的任何侦听器,您始终可以使用标准 属性 e.currentTarget 来访问侦听器所在的节点附于。对于 X-Tag,无论您是否使用 delegate 伪元素,e.currentTarget 将始终引用您的自定义元素:

xtag.register('x-foo', {
  content: '<input /><span></span>',
  events: {
    focus: function(e){
      // e.currentTarget === your x-foo element
    },
    'tap:delegate(span)': function(e){
      // e.currentTarget still === your x-foo element
      // 'this' reference set to matched span element
    }
  }
});

请记住,这是一个标准 API,用于访问附加了事件侦听器的元素,更多信息请参见:https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget