嗨,我有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>
下面是jquery的例子,有3个调用,但工作完美
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>
你应该移动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>
所以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>