如何将 属性 添加到我的自定义元素并能够对其值更改触发操作

How can I add a property to my custom element and be able to fire an action on its value change

事实上,标题并没有完全涵盖我所追求的。我创建了自己的 select 元素。它由一些 div、ul/li 和隐藏输入 elements.It 组成,当然还有标记和 javascript 部分。这是 html:

<div id="ddlCars" class="ma-select" style="width:350px;">
        <div class="ma-select-box"><input class="ma-select-box-filter" type="text"></div>
        <div class="ma-select-options">
            <ul class="ma-select-ul">
                <li class="ma-select-li ma-visible-option" optvalue="7">MERCEDES</li>
                <li class="ma-select-li ma-visible-option" optvalue="10">BMW</li>
                <li class="ma-select-li ma-visible-option" optvalue="14">AUDI</li>
                <li class="ma-select-li ma-visible-option" optvalue="3">VOLKSWAGEN</li>
            </ul>
        </div>
        <input class="ma-select-hidden"  type="hidden">
    </div>

javascript 代码只是一堆函数,它们捕获点击、悬停、键盘弹起等事件,并在 ready 方法上绑定到上述元素(通过 class)。我还没有为此自定义 select.

声明任何类型

使用普通的 DOM select 元素我可以做到这一点:

 document.getElementById("mySelect").selectedIndex=0;

现在我想实现类似的东西。我可以通过 ID 或 class 名称找到包装器 div。但是有什么方法可以做这样的事情吗?

$('#ddlCars').selectedIndex=1;

所以不知何故,我需要向我的自定义 select 添加一个 属性 并捕捉它的变化以将选择的值设置为相应的 li 元素。

恐怕 .selectedIndex 只适用于 <select> 元素。如果你真的想使用类似的东西,试试

$('ul li').live('click', function() 
{
    var index =  $(this).index();
});

如果您使用 jQuery 1.9+,请使用 .delegate 而不是 .live,因为它已被弃用。

要获得与 select 元素相同的行为,您可能需要像对普通 class 一样扩展该元素。也许使用像 Polymer、github.com/richardanaya/webblock 或 github.com/SaulDoesCode/Crafter.js 这样的库来设计您的自定义元素。

否则您应该使用 getter 和 setter 手动实现它。
您将不得不使用 Object.defineProperty 在元素上使用 getter 和 setter 创建此类自定义行为。

这里有一个漂亮的小函数可以让这更容易

   function newGetSet(element ,key, get, set) {
         Object.defineProperty(element, key, {
           set: set,
           get: get
         });
   }
   // then use it - just a rough example 
   newGetSet( myElement , 'selectedIndex' , index => {
      // perhaps then apply a class or something to make it active
      document.querySelectorAll('ul > li')[index].classList.add('active');
   }, () => {
      let active_index = 0;
      Array.from(document.querySelectorAll('ul > li')).forEach((item,index) => {
          if(item.classList.contains('active')) active_index = index;
      });
      return active_index;
   });

当然,正如另一个答案所提到的,要对自定义 select 列表中的项目产生预期效果,可以附加 en EventListener。

考虑到 属性 "selectedIndex" 已在父元素上定义,因此您可以简单地添加将更新父元素的侦听器。

[...document.querySelectorAll('ul > li')].forEach((item,index) => {
    item.addEventListener('click',evt => {
       item.parentNode.selectedIndex = index;
    });
});