将 Jquery 代码转换为 vanilla JS,选项值选择和 'one' 方法不起作用

Converting Jquery code to vanilla JS, option value selction and 'one' method not working

我想将一个 Jquery 函数转换为 JS,但我在实现它时遇到了问题。 Jquery 代码被注释掉了,它可以正常工作。 主函数使用 select 菜单中的 selected 选项作为参数(确保选择 LeftAndZoom 选项),然后将所选动画应用于容器。

这是主要功能,我实在想不通怎么把它转成JS。

$('#imageContainer').removeClass().addClass(x + ' animation').one
('webkitAnimationEnd mozAnimationEnd MSAnimationEnd 
oanimationend    animationend', function(){
  $(this).removeClass();
});

这是我目前拥有的 JS,我尝试了很多东西,但都无济于事。

function testAnim(x) {
var container = document.getElementById("imageContainer").
container.className = "";
container.classList.add(x + ' animation');
this.container.className = "";
}

我知道这可能行不通,但它仍然比我试过的要好。

这是伴随函数,从选项列表中提取参数值:

$(document).ready(function(){
$('.triggerAnimation').click(function(e){
  e.preventDefault();
  var anim = $('.jsanimations').val();
  testAnim(anim);
});

$('.js--animations').change(function(){
  var anim = $(this).val();
  testAnim(anim);
});
});

我的 JS 是:

var trigger = document.querySelector(".triggerAnimation");
var JSanimation = document.querySelector(".js--animations");

trigger.addEventListener('click', function(e){
e.preventDefault();
var anim = JSanimation.options[this.selectedIndex].innerText;
testAnim(anim);
JSanimation.addEventListener("change", function(){
 var anim = this.options[this.selectedIndex].innerText;
});   

});

这里的主要问题是,我不知道如何实现 JS 等效的 'one' 方法,如何保持 "this" 上下文以及如何向 'one' 添加回调方法

最重要的是,我收到一个错误 "Uncaught TypeError: Cannot read property 'options' of null"

看起来选项值的 selection 也不起作用。

Link 转笔:

http://codepen.io/damianocel/pen/KdobyK

至于制作 "one" 类型的函数,这是一种方法:

function bindOne(el, evtTypes, callback, captures) {
  var allEvents = evtTypes.trim().split(/\s+/)

  allEvents.forEach(function(evtType) {
    el.addEventListener(evtType, function boundFn() {
      this.removeEventListener(evtType, boundFn, captures)

      callback.call(this, event)
    }, captures)
  })
}

函数定义了4个参数...

  • el是要绑定的元素
  • evtTypes 是要绑定的 space 分隔的事件类型字符串
  • callback 是您的事件处理程序
  • captures 表示是否要为该事件冒泡或捕获。你通常可以把那个关掉。

它不是直接绑定您的回调,而是绑定一个函数,该函数在第一个事件上立即解除绑定,然后手动调用您的原始回调。

它保持正确 this 值的方式是它使用 .call() 调用您的回调,这让您可以在被调用的函数中手动设置 this 的值。

那么你可以这样使用它:

function testAnim(x) {
  var el = document.querySelector("#imageContainer")
  el.className = ""
  el.classList.add(x + ' animation')

  bindOne(el, 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd' + 
                                  ' oanimationend animationend', function() {
    this.className = ""
  });
}

你的TypeError只是因为你的HTML里没有js--animationsclass。应该是 jsanimations.


此外,我可能会让您的 bindOne 为您处理浏览器前缀。这样你只需要传递'animationend',你的函数也可以解除它们的绑定。

var needsPrefixes = {
  animationend: true
  // can add others as needed
}

var prefixes = ["webkit", "moz", "ms", "o"]

function bindOne(el, evtTypes, callback, captures) {
  var allEvents = evtTypes.trim().split(/\s+/)

  allEvents.forEach(function(evtType) {
    var doPrefixes = needsPrefixes[evtType.toLowerCase()]

    if (doPrefixes) {
      prefixes.forEach(function(prefix) {
        el.addEventListener(prefix + evtType, boundFn, captures)
      })
    }

    el.addEventListener(evtType, boundFn, captures)

    function boundFn() {
      if (doPrefixes) {
        prefixes.forEach(function(prefix) {
          this.removeEventListener(prefix + evtType, boundFn, captures)
        }, this)
      }

      this.removeEventListener(evtType, boundFn, captures)

      callback.call(this, event)
    }
  })
}