如何使用 javascript 取消注册/取消绑定 Material ui 中的事件

Posted

技术标签:

【中文标题】如何使用 javascript 取消注册/取消绑定 Material ui 中的事件【英文标题】:How to un-register/unbind a event in material ui with javascript 【发布时间】:2021-05-17 02:24:46 【问题描述】:

您好,我对un-registering/unbinding 材料组件有疑问

注意:在我的真实项目中,每次动态加载数据时,我都会调用initializeMaterialComponents

问题:我需要un-registering/unbind之前的事件,使其不会被触发3次(+)提供更好的解决方案

下面是我的问题selection triggered 3 times

function initializeMaterialComponents()
   // console.log(mdc);

    var selectBox = new mdc.select.MDCSelect(document.querySelector('.mdc-select'));

    selectBox.listen('MDCSelect:change', () => 
      alert(`Selected option at index $selectBox.selectedIndex with value "$selectBox.value"`);
    );


initializeMaterialComponents();
initializeMaterialComponents();
initializeMaterialComponents();
<head>
  <link href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet">
    <script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>

</head>


<div class="mdc-select mdc-select--filled demo-width-class">
  <div class="mdc-select__anchor"
       role="button"
       aria-haspopup="listbox"
       aria-expanded="false"
       aria-labelledby="demo-label demo-selected-text">
    <span class="mdc-select__ripple"></span>
    <span id="demo-label" class="mdc-floating-label">Pick a Food Group</span>
    <span class="mdc-select__selected-text-container">
      <span id="demo-selected-text" class="mdc-select__selected-text"></span>
    </span>
    <span class="mdc-select__dropdown-icon">
      <svg
          class="mdc-select__dropdown-icon-graphic"
          viewBox="7 10 10 5" focusable="false">
        <polygon
            class="mdc-select__dropdown-icon-inactive"
            stroke="none"
            fill-rule="evenodd"
            points="7 10 12 15 17 10">
        </polygon>
        <polygon
            class="mdc-select__dropdown-icon-active"
            stroke="none"
            fill-rule="evenodd"
            points="7 15 12 10 17 15">
        </polygon>
      </svg>
    </span>
    <span class="mdc-line-ripple"></span>
  </div>

  <div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
    <ul class="mdc-list" role="listbox" aria-label="Food picker listbox">
      <li class="mdc-list-item mdc-list-item--selected" aria-selected="true" data-value="" role="option">
        <span class="mdc-list-item__ripple"></span>
      </li>
      <li class="mdc-list-item" aria-selected="false" data-value="grains" role="option">
        <span class="mdc-list-item__ripple"></span>
        <span class="mdc-list-item__text">
          Bread, Cereal, Rice, and Pasta
        </span>
      </li>
      <li class="mdc-list-item mdc-list-item--disabled" aria-selected="false" data-value="vegetables" aria-disabled="true" role="option">
        <span class="mdc-list-item__ripple"></span>
        <span class="mdc-list-item__text">
          Vegetables
        </span>
      </li>
      <li class="mdc-list-item" aria-selected="false" data-value="fruit" role="option">
        <span class="mdc-list-item__ripple"></span>
        <span class="mdc-list-item__text">
          Fruit
        </span>
      </li>
    </ul>
  </div>
</div>

下面是 3 个调用的 jquery 示例,但效果很好

function attachEventListernerToSelectbox()
    $('#select').off('change');
    $('#select').on('change',function()
        alert('selected value is :'+ $(this).val());
    );


$(function()
    attachEventListernerToSelectbox();
    attachEventListernerToSelectbox();
    attachEventListernerToSelectbox();
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


<select id="select">
    <option value="---">--select--</option>
    <option value="Banana">Banana</option>
    <option value="Apple">Apple</option>
    <option value="Kiwi">Kiwi</option>
</select>

【问题讨论】:

因为你多次调用initializeMaterialComponents()。动态添加数据时,不要每次都重新创建监听器。 change监听器只需要添加一次。 @RandyCasburn 请进行我的编辑,其中显示了调用 3 次的 jquery 示例 【参考方案1】:

你应该把selectBox初始化移到函数外并创建监听器,然后你可以使用unlisten

var selectBox = new mdc.select.MDCSelect(document.querySelector('.mdc-select'));

var onChangeListener = function(event)
    alert(`Selected option at index $selectBox.selectedIndex with value "$selectBox.value"`);



function initializeMaterialComponents()
    selectBox.unlisten('MDCSelect:change', onChangeListener);
    selectBox.listen('MDCSelect:change', onChangeListener);



initializeMaterialComponents();
initializeMaterialComponents();
initializeMaterialComponents();
<head>
  <link href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet">
    <script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>

</head>


<div class="mdc-select mdc-select--filled demo-width-class">
  <div class="mdc-select__anchor"
       role="button"
       aria-haspopup="listbox"
       aria-expanded="false"
       aria-labelledby="demo-label demo-selected-text">
    <span class="mdc-select__ripple"></span>
    <span id="demo-label" class="mdc-floating-label">Pick a Food Group</span>
    <span class="mdc-select__selected-text-container">
      <span id="demo-selected-text" class="mdc-select__selected-text"></span>
    </span>
    <span class="mdc-select__dropdown-icon">
      <svg
          class="mdc-select__dropdown-icon-graphic"
          viewBox="7 10 10 5" focusable="false">
        <polygon
            class="mdc-select__dropdown-icon-inactive"
            stroke="none"
            fill-rule="evenodd"
            points="7 10 12 15 17 10">
        </polygon>
        <polygon
            class="mdc-select__dropdown-icon-active"
            stroke="none"
            fill-rule="evenodd"
            points="7 15 12 10 17 15">
        </polygon>
      </svg>
    </span>
    <span class="mdc-line-ripple"></span>
  </div>

  <div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
    <ul class="mdc-list" role="listbox" aria-label="Food picker listbox">
      <li class="mdc-list-item mdc-list-item--selected" aria-selected="true" data-value="" role="option">
        <span class="mdc-list-item__ripple"></span>
      </li>
      <li class="mdc-list-item" aria-selected="false" data-value="grains" role="option">
        <span class="mdc-list-item__ripple"></span>
        <span class="mdc-list-item__text">
          Bread, Cereal, Rice, and Pasta
        </span>
      </li>
      <li class="mdc-list-item mdc-list-item--disabled" aria-selected="false" data-value="vegetables" aria-disabled="true" role="option">
        <span class="mdc-list-item__ripple"></span>
        <span class="mdc-list-item__text">
          Vegetables
        </span>
      </li>
      <li class="mdc-list-item" aria-selected="false" data-value="fruit" role="option">
        <span class="mdc-list-item__ripple"></span>
        <span class="mdc-list-item__text">
          Fruit
        </span>
      </li>
    </ul>
  </div>
</div>

【讨论】:

很好的答案,对于多选我们该怎么办?请给我看多选 @EaBengaluru 检查这个答案here【参考方案2】:

所以 jQuery 版本起作用的原因是它在分配新的处理程序之前删除了事件处理程序。 而在您的版本中,您通过var selectBox = new mdc.select.MDCSelect(...); 创建新的 MDCSelect 组件,因此 javascript 无法知道事件是否已附加。

你可以在这里做的一个技巧是添加一个新属性,这样你就可以知道你已经附加了事件处理程序

function initializeMaterialComponents()
    const element = document.querySelector('.mdc-select:not([event-attached=true])');
    if (element) 
      element.setAttribute('event-attached', true);
      var selectBox = new mdc.select.MDCSelect(element);
      selectBox.listen('MDCSelect:change', () => 
         alert(`Selected option at index $selectBox.selectedIndex with value "$selectBox.value"`);
      );
   


initializeMaterialComponents();
initializeMaterialComponents();
initializeMaterialComponents();
<head>
  <link href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet">
    <script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>

</head>


<div class="mdc-select mdc-select--filled demo-width-class">
  <div class="mdc-select__anchor"
       role="button"
       aria-haspopup="listbox"
       aria-expanded="false"
       aria-labelledby="demo-label demo-selected-text">
    <span class="mdc-select__ripple"></span>
    <span id="demo-label" class="mdc-floating-label">Pick a Food Group</span>
    <span class="mdc-select__selected-text-container">
      <span id="demo-selected-text" class="mdc-select__selected-text"></span>
    </span>
    <span class="mdc-select__dropdown-icon">
      <svg
          class="mdc-select__dropdown-icon-graphic"
          viewBox="7 10 10 5" focusable="false">
        <polygon
            class="mdc-select__dropdown-icon-inactive"
            stroke="none"
            fill-rule="evenodd"
            points="7 10 12 15 17 10">
        </polygon>
        <polygon
            class="mdc-select__dropdown-icon-active"
            stroke="none"
            fill-rule="evenodd"
            points="7 15 12 10 17 15">
        </polygon>
      </svg>
    </span>
    <span class="mdc-line-ripple"></span>
  </div>

  <div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
    <ul class="mdc-list" role="listbox" aria-label="Food picker listbox">
      <li class="mdc-list-item mdc-list-item--selected" aria-selected="true" data-value="" role="option">
        <span class="mdc-list-item__ripple"></span>
      </li>
      <li class="mdc-list-item" aria-selected="false" data-value="grains" role="option">
        <span class="mdc-list-item__ripple"></span>
        <span class="mdc-list-item__text">
          Bread, Cereal, Rice, and Pasta
        </span>
      </li>
      <li class="mdc-list-item mdc-list-item--disabled" aria-selected="false" data-value="vegetables" aria-disabled="true" role="option">
        <span class="mdc-list-item__ripple"></span>
        <span class="mdc-list-item__text">
          Vegetables
        </span>
      </li>
      <li class="mdc-list-item" aria-selected="false" data-value="fruit" role="option">
        <span class="mdc-list-item__ripple"></span>
        <span class="mdc-list-item__text">
          Fruit
        </span>
      </li>
    </ul>
  </div>
</div>

【讨论】:

以上是关于如何使用 javascript 取消注册/取消绑定 Material ui 中的事件的主要内容,如果未能解决你的问题,请参考以下文章

Android:取消注册相机按钮

如何取消绑定().hover()而不是.click()?

使用 ACE 编辑器,如何取消绑定事件?

如何在 subGrid 中绑定和取消绑定事件

如何从 jQuery 中的“滚动”事件中取消绑定所有先前添加的事件? [复制]

jquery中取消和绑定hover事件的正确方式