处理多个页面上的事件侦听器

时间:2019-03-25 23:04:18

标签: javascript

我写了一个javascript文件,其中包含一些事件侦听器,用于处理选项卡,手风琴等。但是,并不是每个页面都存在这些元素,因此它正在寻找不存在的元素并将整个js丢掉。

我知道我可以通过使用多个if语句来解决它,但这听起来并不正确。

// Accordion
const accordions = document.querySelectorAll('.accordion li');

accordions.forEach(accordion =>{
    accordion.addEventListener('click', (e) => {
        e.preventDefault();
        accordion.classList.toggle('open');
    })
});

// Inline toggle
const inlineToggle = document.getElementById('inline-toggle');

inlineToggle.addEventListener('click', () => {
    inlineToggle.nextElementSibling.classList.toggle('active');
});

const inlineToggleOptions = document.querySelectorAll('.inline-toggle-options button');
inlineToggleOptions.forEach(option => {
    option.addEventListener('click', (e) => {
        // Prevent default
        e.preventDefault();
        // Update sentence text
        inlineToggle.innerHTML = option.dataset.payType;
        // Remove selected class from options
        inlineToggleOptions.forEach(option => {
            option.classList.remove('selected');
        });
        // Add selected class to chosen option
        option.classList.add('selected');
        // Close dialog
        inlineToggle.nextElementSibling.classList.remove('active');
    })
});

// Cover bubbles

// Create the slidepanel
const placeholder = document.getElementById('slidepanel');

// Find all buttons
const button = document.querySelectorAll('.trigger-aside');

button.forEach((button => {

    // Listen for clicks on buttons
    button.addEventListener('click',(e) => {

        // Prevent default
        e.preventDefault();

        // Get the target
        const target = button.dataset.target;
        console.log(target);

        // Call the API
        fetch(`http://****.****.uk/****/****/****/${target}`)
            .then((res) => res.json())
            .then(function(res) {

                // Load HTML into slider panel
                placeholder.innerHTML = res.object.content;

                // Stop body overflow
                document.body.classList.add('overflow-hidden');

                // Create overlay and append
                const overlay = document.querySelector('.overlay');
                overlay.classList.add('active');
                document.body.appendChild(overlay);

                // Show the panel
                placeholder.classList.add('active');
                document.body.appendChild(placeholder);

                // Listen for close
                overlay.addEventListener('click', (e) =>{
                    // Close requested
                    document.body.classList.remove('overflow-hidden');
                    placeholder.classList.remove('active');
                    overlay.classList.remove('active');
                });

            })
            .catch(function(err) {
                // Log error
                console.log(err);
            });

    })
}));

其他人通常如何解决这个问题?任何指导表示赞赏!

2 个答案:

答案 0 :(得分:0)

我通常建议首先考虑代码组织,其次考虑效率。我同意StevenB.的建议和Luke Tubby的回答,以最小的努力来充分利用当前的状况。

有关更详尽的解决方案,我建议您熟悉构建/打包工具(例如Webpack),该工具为您提供了在所选文件和目录中构造代码(和资产)并创建页面的方法。特定的小型包装。
解决该问题(提高效率和代码组织)的另一种(完全不同且独立的)方法是构建single page application ...

答案 1 :(得分:0)

事件委托模式

如果您将这些UI元素归为所有页面(如div包装器)共有的父元素,则可以尝试使用Event Delegation pattern。本质上,您可以将click事件分配给该父元素,并利用函数仅在返回所需元素(即您的按钮)时才采取措施。它会像...

const parent = document.querySelector('div.wrapper'); //Change selector to suit a common parent
const buttons = [...document.querySelectorAll('.inline-toggle-options button')]; // convert to array to make it easier to work with
const elementsToChange = document.querySelectorAll('.elements .to .change');

parent.addEventListener('click', toggleOptions);

function getEventTarget(e) {
  e = e || window.event;
  return e.target || e.srcElement; // For IE compatibility
}

function toggleOptions {
  let target = getEventTarget(e);
  if(buttons.includes(target)) {
    // Trigger options on UI elements if any of the buttons are among the clicked elements
    // Target refers to the buttons in particular, not the UI elements you want to change
  }
}

您希望采用哪种方式重构代码以对特定元素采取措施。您可以按特定功能将按钮分组到不同的数组中。如果您有2或3个数组,则只需从条件语句中编写2或3个选项。

为此,您还可以使用这种模式节省内存,因为您只分配了一个事件处理程序,并让子处理元素bubble up上的子事件由该单个处理程序处理。另外,由于初始事件处理程序已分配给所有页面上通用的父元素,因此您也不会遇到错误。

一些警告

来自上面链接的指南:

  

并非所有事件都会冒泡。没有模糊,聚焦,加载和卸载事件   像其他事件一样冒泡。模糊和聚焦事件实际上可以是   使用捕获阶段(在IE以外的浏览器中)访问   冒泡的阶段,但这又是一个故事。

     

在管理某些鼠标事件时,您需要小心。如果您的代码是   处理mousemove事件时,您很有可能创建一个   性能瓶颈,因为触发了mousemove事件,因此   经常。 mouseout事件具有古怪的行为,很难   通过事件委托进行管理。