eventListener 在刷新 JS 之前多次触发

Posted

技术标签:

【中文标题】eventListener 在刷新 JS 之前多次触发【英文标题】:eventListener is firing multiple times before the refresh JS 【发布时间】:2022-01-11 07:03:44 【问题描述】:

我正在为电子邮件表单制作一个简单的提交按钮,当单击提交按钮并且电子邮件有效时,它将按钮的状态从“订阅”更改为取消订阅并隐藏表单。到这里一切都很好,但问题是当我单击提交按钮时,它会执行我需要的操作,但是在我输入有效的电子邮件并更改按钮的状态后,相反的操作没有完成,它继续发送电子邮件到本地存储,而不是删除它。 在这里我添加了一个无效的电子邮件: 在控制台日志中我有这封电子邮件。 在这里我添加了一个有效的电子邮件而不刷新页面:

现在,当我单击取消订阅时,它应该从 localStorage 中删除电子邮件并返回表单和按钮的状态,但相反,它会执行提交操作..:

我该怎么办?我是 JS 新手,在这里我只使用 vanilla js。

使用提交按钮的代码:

document.querySelector('form').addEventListener('submit', function (e) 
e.preventDefault()
console.log(inputForm.value)
localStorage.setItem('Email', inputForm.value)
subscribeEmail(inputForm.value);
 )

下面的代码用于在刷新页面时保持按钮的状态:

    const isSubscribed = localStorage.getItem('isSubscribed')
  if (isSubscribed === 'true') 
    subscribe()
    // document.querySelector('form').addEventListener('click', function (e) 
    //   e.preventDefault()
    //   unsubscribe()
    //   localStorage.removeItem('Email')
    // )
   else 
    unsubscribe()
  

下面是改变按钮状态的代码: 编辑:我修改了下面的代码,现在我可以在不刷新页面的情况下取消订阅,现在的问题是我无法提交另一个值进行验证并在 localStorage 中发送。

  import  validateEmail  from './email-validator.js'


export const subscribe = () => 
    const subscribeBtn = document.getElementById('subscribeButton')
    subscribeBtn.setAttribute('value', 'Unsubscribe')
    document.getElementById('emailForm').style.display = 'none'
    localStorage.setItem('isSubscribed', 'true')


export const unsubscribe = () => 
    const subscribeBtn = document.getElementById('subscribeButton')
    subscribeBtn.setAttribute('value', 'Subscribe')
    document.getElementById('emailForm').style.display = 'block'
    localStorage.setItem('isSubscribed', 'false')



export const subscribeEmail = (email) => 
    if (validateEmail(email) == true) 
        subscribe();
        document.querySelector('form').addEventListener('click', function (e) 
            e.preventDefault()
            unsubscribe()
            localStorage.removeItem('Email')
        )
     else if (validateEmail == false) 
        unsubscribe();
    
;

这里是验证函数:

const VALID_EMAIL_ENDINGS = ['gmail.com', 'outlook.com', 'yandex.ru']

export const validateEmail = (email) => 
  if (VALID_EMAIL_ENDINGS.some(v => email.includes(v))) 
  return true
   else 
  return false
  


export  VALID_EMAIL_ENDINGS as validEnding 

我不明白出了什么问题,或者这通常会发生..它让我有机会在刷新页面后“取消订阅”,但我想订阅和取消订阅多次而不需要刷新。

我应该提一下,创建按钮的部分显示为usign window.onload,因此它是动态创建的。

编辑:

全段创建代码:

import  subscribe, unsubscribe from './subscribe.js'
import  subscribeEmail  from './subscribe.js'

const addSection = () => 
  const sectionFour = createElement('sectionFour', 'section', 'app-section app-section--image-program', 'fourth-section')
  const sectionParent = getElbyID('sectionParent', 'third-section')
  const parentSection = sectionParent.parentNode
  parentSection.insertBefore(sectionFour, sectionParent.nextSibling)

  const heading2 = createElement('heading2', 'h2', 'program-title')
  const heading2Text = document.createTextNode('Join Our Program')
  heading2.append(heading2Text)
  const parent = getElbyID('parent', 'fourth-section')

  const heading3 = createElement('heading3', 'h3', 'program-subtitle')
  const heading3Text = document.createTextNode('Sed do eiusmod tempor incididunt')
  heading3.appendChild(heading3Text)
  const linebreak = createElement('linebreak', 'br')
  heading3.appendChild(linebreak)
  const textAfterBreak = document.createTextNode('ut labore et dolore magna aliqua')
  heading3.appendChild(textAfterBreak)

  const form = createElement('submitFieldWrapper', 'form', 'submitFieldWrapper', 'form')
  parent.append(heading2, heading3, form)

  const emailForm = createElement('emailForm', 'div', 'form-wrapper', 'emailForm')

  const inputForm = createElement('inputForm', 'input', 'form-input', 'submit-info')
  setAttributes(inputForm,
    'type', 'text',
    'placeholder', 'Email')
  if (localStorage.getItem('Email') !== null) 
    inputForm.setAttribute('value', localStorage.getItem('Email'))
   else 
    inputForm.setAttribute('placeholder', 'Email')
  

  emailForm.appendChild(inputForm)

  document.querySelector('form').addEventListener('submit', function (e) 
    e.preventDefault()
    console.log(inputForm.value)
    localStorage.setItem('Email', inputForm.value)
    subscribeEmail(inputForm.value);
  )

  const submitForm = createElement('submitForm', 'input', 'app-section__button submit-btn', 'subscribeButton')
  setAttributes(submitForm,
    'type', 'submit',
    'value', 'Subscribe')
  form.append(emailForm, submitForm)

  const isSubscribed = localStorage.getItem('isSubscribed')
  if (isSubscribed === 'true') 
    subscribe()
    // document.querySelector('form').addEventListener('click', function (e) 
    //   e.preventDefault()
    //   unsubscribe()
    //   localStorage.removeItem('Email')
    // )
   else 
    unsubscribe()
  


const createElement = (elName, htmlEl, elClass, elID) => 
  const elementName = document.createElement(htmlEl)
  elementName.className = elClass
  elementName.id = elID

  return elementName


const getElbyID = (elName, searchedId) => 
  const elementToSearch = document.getElementById(searchedId)

  return elementToSearch


const setAttributes = (elem, ...elemArguments) => 
  for (let i = 0; i < elemArguments.length; i += 2) 
    elem.setAttribute(elemArguments[i], elemArguments[i + 1])
  


export const advancedSection = () => 
  addSection()
  const getHeading = document.getElementById('fourth-section')
  const sectionChildren = getHeading.children
  sectionChildren[0].innerHTML = 'Join Our Advanced Program'
  const getButton = document.getElementById('subscribeButton')
  setAttributes(getButton,
    'type', 'submit',
    'value', 'Subscribe to Advanced Program')
  getButton.className = 'app-section__button submit-btnAdvanced'


export default addSection

还有 main.js

import addSection,  advancedSection  from './join-us-section.js'

class SectionCreator 
  constructor (type) 
    this.type = type
  

  create (type) 
    if (type === 'standard') 
      addSection()
     else if (type === 'advanced') 
      advancedSection()
    
    return type
  

  remove () 
    const sectionToRemove = document.getElementById('fourth-section')
    sectionToRemove.remove()
  


window.onload = new SectionCreator().create('standard')

我设法在不刷新页面的情况下取消订阅,但现在的问题是,如果不刷新我就无法输入另一个输入.. 这就是我在不刷新的情况下取消订阅的方式:

export const subscribeEmail = (email) => 
    if (validateEmail(email) == true) 
        subscribe();
        document.querySelector('form').addEventListener('click', function (e) 
            e.preventDefault()
            unsubscribe()
            localStorage.removeItem('Email')
        )
     else if (validateEmail == false) 
        unsubscribe();
    
;

这个事件监听器在 isSubscribed 函数中,但我把它移到了 subscribeEmail,它在那里检查验证。上面的代码最后可能不同,因为我重命名了变量,从 unsubscribeToggle 到 isSubscribed,从 getUnsubscribe 到 subscribe 和从 getSubscribe退订

【问题讨论】:

【参考方案1】:

我设法在不刷新的情况下取消订阅:

export const subscribeEmail = (email) => 
    if (validateEmail(email) == true) 
        subscribe();
        document.querySelector('form').addEventListener('click', function (e) 
            e.preventDefault()
            unsubscribe()
            localStorage.removeItem('Email')
        )
     else if (validateEmail == false) 
        unsubscribe();
    
;

我只是玩了一些功能,并把它们放在了位置。我修复了我不能订阅和取消订阅很多次的问题。 我应该只删除函数中的 preventDefault 并使用 stopPropagation 进行更改:

export const subscribeEmail = (email) => 
  const isValidEmail = validateEmail(email)
  if (isValidEmail === true) 
    subscribe()
    document.querySelector('form').addEventListener('click', function (e) 
      unsubscribe()
      localStorage.removeItem('Email')
      e.stopPropagation()
    )
   else if (isValidEmail === false) 
    unsubscribe()
  

【讨论】:

【参考方案2】:

如果不查看所有代码,很难在此处修改所有内容,而且 localStoage 在 sn-ps 中不起作用。看看这个例子是否有帮助。它只使用一点代码来管理订阅与取消订阅功能,而无需刷新页面。

// init code
let hasSubscribed = false
let userEmail = ''
let subBtnEl, inputEl, resultEl

window.addEventListener('DOMContentLoaded', () => 
  // userEmail = localStorage.getItem('email') || '';;
  subBtnEl = document.querySelector('button#sub');
  inputEl = document.querySelector('input[name=email]');
  resultEl = document.querySelector('#result');
  subBtnEl.addEventListener('click', e => 
    resultEl.innerText = "";
    doButton()
  )
)

function isValidEmail(email) 
  return true;


function doButton() 
  // check localStorage
  hasSubscribed = userEmail.trim() !== '';
  if (!hasSubscribed) 
    if (!isValidEmail(inputEl.value)) 
      resultEl.innerText = "Invalid Email";
      return
    
    userEmail = inputEl.value;
    inputEl.setAttribute('hidden', true);;
    subBtnEl.innerText = "Unsubscribe";
    resultEl.innerText = "You've been subscribed!";
    // localStorage.setItem('email', subBtnEl.value.trim());
   else 
    // localStorage.setItem('email', '');
    userEmail = '';
    inputEl.removeAttribute('hidden');;
    resultEl.innerText = "You've been unsubscribed";
    subBtnEl.innerText = "Subscribe";
  
<div id='result'></div>
<input type='text' name='email' />
<button id='sub'>Subscribe</button>

【讨论】:

我将 unsubscribeToggle 中的事件监听器添加到 getUnsubscribe 函数中,这样我就可以在不刷新页面的情况下取消订阅。但取消订阅后我无法提交另一个值。如果更容易理解,我添加了创建该部分的整个代码。

以上是关于eventListener 在刷新 JS 之前多次触发的主要内容,如果未能解决你的问题,请参考以下文章

网站首页刷新多次以后页面的js效果都没有了

删除 MovieClip 类会删除其中的 eventListeners 吗?

防止在 Angular 中多次触发令牌刷新请求

JS HTML DOM EventListener

EventListener 在悬停时显示隐藏

Sails.js:新创建的记录在刷新之前不会填充到页面上