首页 > 解决方案 > 通过选择按钮更改自键入文本无法正常工作

问题描述

https://jsfiddle.net/AlexThunders/k8s79zL5/18/

当我单击选择中的选项时,我正在尝试将自输入文本从英语更改为俄语:

  let engType = [
    'Never give up. ',
     'You can win. '
  ]
  
  let rusType = [
    'Никогда не сдавайся. ',
    'Ты можешь победить. '
  ]

页面已加载,此功能逐渐键入字母:

  function typeCharacters(phrases) {
    if(phrases[count] !== undefined && phrases[count] !== null && phrases[count] !== "") {
      let allLength  = phrases[count].length
      setInterval(() => {
        if(phrases[count] !== undefined && typePar !== null) {
          character = phrases[count].slice(ind,ind+1)
          txt = document.createTextNode(character)
          typePar.appendChild(txt)
          ind++
          let typeLength = typePar.textContent.length
          if(typeLength === allLength) {
            count++
            ind = 0
            if(phrases[count] !== undefined) {
              allLength += phrases[count].length
            }
          } 
        }
      },100)
    }
  }
  typeCharacters(engType)

有用。但是,当我只是触摸选择按钮而不选择语言时,我会在同一段落中得到一种或两种语言中混合字母的废话段落:


  function searchLang(choosenLang) {
    //if choosen language coincides with one in Object:
    if(languages[choosenLang]) {
      allDataElements.forEach(element => {
        //every property of choosen object/language
        for(let x in languages[choosenLang]) {
          //compare with element's data attribute
          if(element.getAttribute('data') === x) {
            //the same attribute changes iinerText in accordance with object
            element.innerText = languages[choosenLang][x]
            if(languages[choosenLang].changePhrases !== undefined) {
              languages[choosenLang].changePhrases(choosenLang)
            }
          }
        }
      })
    }
  }
  
  select.addEventListener('click', () => {
    allLangOptions.forEach(option => {
      if(option.selected === true) {
        let lang = option.value
        searchLang(lang)
      }
    })
  })

结果:

Никeгда не сд.вайся. Тыuможешь по едить. OR

Никогда нe up. айс

但是,对于其他 html 元素,选择按钮可以正常工作:仅当我选择选项而不是单击选择本身时。

我在对象中使用 changePhrases 函数来更改键入段落的语言:

let languages = {
    en: {
        mPheadLIabout: 'About',
        mPheadLIprojects: 'Projects',
        mPheadLIcontacts: 'Contacts',
        changePhrases: function() {
          if(typePar !== null) {
            typePar.textContent = "";
            count = 0
            ind = 0
            typeCharacters(engType)
          }
        }
      },
    ru: {
        mPheadLIabout: 'О сайте',
        mPheadLIprojects: 'Проекты',
        mPheadLIcontacts: 'Контакты',
        changePhrases: function() {
          if(typePar !== null) {
            typePar.textContent = "";
            count = 0
            ind = 0
            typeCharacters(rusType)
          }
        }
      }
  }

在第一段清除自身,并从第一个字符开始输入,如上所示。

我尝试使用变量重置来停止调用输入英文字符,但没有成功。

此外,我使用 setTimeout 应用了不同的变体,并承诺在段落被清除后才运行函数 typeCharacters(rusType)。仍然无法正常工作,并且控制台中没有错误。

和我用英语得到的结果相同。

看起来当我单击选择按钮(不是选项)时,它再次触发输入文本的功能,而不是等到我使用选项。当我单击选项时,它会同时触发多次。

这是整个代码和奇怪的结果:

https://jsfiddle.net/AlexThunders/k8s79zL5/18/

标签: javascripthtml-select

解决方案


不应将事件处理程序绑定到事件,而应仅在用户更改元素click的选定选项时触发回调。select所以事件类型应该是change

select.addEventListener('change', () => {
  allLangOptions.forEach((option) => {
    if (option.selected === true) {
      let lang = option.value;
      searchLang(lang);
    }
  });
});

这样,您还可以使用键盘更改选项。尽管键盘用户可以更改语言选项,因为这不是鼠标点击,但您的click事件不会触发,您内部的回调addEventListener也不会运行。确保始终挂钩到元素的change事件。select

另一个问题是您永远不会取消间隔。当您选择一种语言时,它只会启动另一个计时器,这只会搞砸一切。看起来效果会加快,随着不同字符的混合,文本会变得乱七八糟,等等。

为避免这种情况,您需要保存从返回的间隔 IDwindow.setInterval()并在运行时将其取消typeCharacters()

// ...
let reset = false;
// create a variable in an outer scope
let activeInterval = null;

function typeCharacters(phrases) {
  // clear running interval
  clearInterval(activeInterval);

  if (reset) return;
  if(phrases[count] !== undefined
    && phrases[count] !== null
    && phrases[count] !== "") {
    let allLength  = phrases[count].length

    // save the interval ID
    activeInterval = setInterval(() => {
      if(phrases[count] !== undefined && typePar !== null) {
      // ... rest of your code

推荐阅读