在另一个函数中调用一个函数,减少重复代码

Calling a function in another function to reduce repeated code

我有两个函数,一个在 mouseenter 事件上触发,另一个在 mouseleave 上触发。这两个功能都重复三次。

在 mouseenter 上,类列表“active”被添加 5x 并且文本内容被更改。 在 mouseleave 上,classlist active 被移除 5x,文本内容设置为空字符串,并再次显示原始图像。

当触发 mouseenter 事件侦听器时,取决于悬停在哪个图像上(3 个图像)。
添加的文本内容 属性 在三个“Photosnap”“Dine”“Nike”之间各不相同。
以及被触发的背景颜色在“红色”“蓝色”“粉红色”之间变化。

Hover state shown as red left image and normal state shown as right image
- 此处显示的图像是三幅图像之一。它以红色背景和“photosnap”的文本内容显示。
- 另一张为蓝色背景,文字内容为“Dine”。
-第三个也是最后一个,粉红色背景和“耐克”的文字内容。

我希望这能描绘出一幅清晰的图画,我很难将其作为代码片段。

我正在尝试重构此 javascript 以使其不那么重复。我是 javascript 的新手,很难让它像我目前拥有的东西一样工作。我不清楚如何创建一个可以在其他函数内部调用的函数来减少重复代码。或者可能使用“this”关键字?



Javascript--

// //Photosnap Project #1 ---------------------------------------------------------

// Content in project on hover 
let projectTitle = document.querySelector('.projectTitlePhotosnap');
let projectLine = document.querySelector('.hoverLinePhotosnap');
// View live View code text wrapper
let projectRowWrap = document.querySelector('.flexWrapperRowPhotosnap');

// Background color + image
let photosnapBackground = document.querySelector('.photosnapBackground');
let photosnapImg = document.querySelector('.photosnap');

// Mouse in add background color title and links
photosnapBackground.addEventListener('mouseenter', function() {
    photosnapBackground.classList.add('active');
    photosnapImg.classList.add('active');
    projectTitle.textContent = 'Photosnap';

    projectTitle.classList.add('active');
    projectLine.classList.add('active');
    projectRowWrap.classList.add('active');
});

// Mouse out remove all
photosnapBackground.addEventListener('mouseleave', function() {
    photosnapBackground.classList.remove('active');
    photosnapImg.classList.remove('active');

    dineBackground.classList.remove('active');
    dineImg.classList.remove('active');

    projectTitle.textContent = '';
    projectTitle.classList.remove('active');
    projectLine.classList.remove('active');
    projectRowWrap.classList.remove('active');
});

//Dine Project #2 ---------------------------------------------------------------

// Content in project on hover 
let projectTitleDine = document.querySelector('.projectTitleDine');
let projectLineDine = document.querySelector('.hoverLineDine');
// View live View code text wrapper
let projectRowWrapDine = document.querySelector('.flexWrapperRowDine');

// Background color + image
let dineBackground = document.querySelector('.dineBackground');
let dineImg = document.querySelector('.dine');

// Mouse in add background color title and links
dineBackground.addEventListener('mouseenter', function() {
    dineBackground.classList.add('active');
    dineImg.classList.add('active');
    projectTitleDine.textContent = 'Dine';

    projectTitleDine.classList.add('active');
    projectLineDine.classList.add('active');
    projectRowWrapDine.classList.add('active');
});

// Mouse out remove all
dineBackground.addEventListener('mouseleave', function() {
    dineBackground.classList.remove('active');
    dineImg.classList.remove('active');

    projectTitleDine.textContent = '';
    projectTitleDine.classList.remove('active');
    projectLineDine.classList.remove('active');
    projectRowWrapDine.classList.remove('active');
});

//Nike Project #3 ---------------------------------------------------------------

// Content in project on hover 
let projectTitleNike = document.querySelector('.projectTitleNike');
let projectLineNike = document.querySelector('.hoverLineNike');
// View live View Code wrapper
let projectRowWrapNike = document.querySelector('.flexWrapperRowNike'); 

// Background color + image
let nikeBackground = document.querySelector('.nikeBackground');
let nikeImg = document.querySelector('.nike');

// Mouse in add background color title and links
nikeBackground.addEventListener('mouseenter', function() {
    nikeBackground.classList.add('active');
    nikeImg.classList.add('active');
    projectTitleNike.textContent = 'Nike';

    projectTitleNike.classList.add('active');
    projectLineNike.classList.add('active');
    projectRowWrapNike.classList.add('active');
});

// Mouse out remove all
nikeBackground.addEventListener('mouseleave', function() {
    nikeBackground.classList.remove('active');
    nikeImg.classList.remove('active');

    projectTitleNike.textContent = '';
    projectTitleNike.classList.remove('active');
    projectLineNike.classList.remove('active');
    projectRowWrapNike.classList.remove('active');


HTML--

<!-- Projects desktop -->
<div id="horizontalScroll" class="horizontalScroll projectsContainer">
    <!-- Photosnap -->
    <div class="projectsWrapper photosnapBackground">
        <span class="testFunc hoverTitleFont projectTitlePhotosnap"></span>
        <div class="testFunc hoverLine hoverLinePhotosnap"></div>
        <img src="assets/projects/photosnap-desktop-p.jpg" alt="photosnap project" class="photosnap">
        <div class="testFunc flexWrapperRow flexWrapperRowPhotosnap">
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Live</span>
            </a>
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Code</span>
            </a>
        </div>
    </div>
    <!-- Dine -->
    <div class="projectsWrapper dineBackground">
        <span class="testFunc hoverTitleFont projectTitleDine"></span>
        <div class="testFunc hoverLine hoverLineDine"></div>
        <img src="assets/projects/dine-desktop-p.png" alt="dine project" class="dine">
        <div class="testFunc flexWrapperRow flexWrapperRowDine">
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Live</span>
            </a>
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Code</span>
            </a>
        </div>
    </div>
    <!-- Nike -->
    <div class="projectsWrapper nikeBackground">
        <span class="hoverTitleFont projectTitleNike"></span>
        <div class="hoverLine hoverLineNike"></div>
        <img src="assets/projects/nike-desktop-p.png" alt="nike project" class="nike">
        <div class="flexWrapperRow flexWrapperRowNike">
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Live</span>
            </a>
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Code</span>
            </a>
        </div>
    </div>
</div>

是的,您使用了 3 次相同的功能,所以我们肯定可以做得更好。 这是第一个简单的想法,在树元素上做一个循环:

JAVASCRIPT

          let slide = ['Photosnap', 'Dine', 'Nike'] ;
        for (let i = 0; i < slide.length ; i++ ) {
            let lowercaseName =  slide[i].toLowerCase() ;
            let projectTitle = document.querySelector('.projectTitle' + slide[i]);
            let projectLine = document.querySelector('.hoverLine' + slide[i]);
    // View live View code text wrapper
            let projectRowWrap = document.querySelector('.flexWrapperRow'+ slide[i]);
    // Background color + image
            let background = document.querySelector('.'+ lowercaseName+'Background');
            let img = document.querySelector('.'+ lowercaseName);
    // Mouse in add background color title and links
            background.addEventListener('mouseenter', function() {
                background.classList.add('active');
                img.classList.add('active');
                projectTitle.textContent = slide[i];
                projectTitle.classList.add('active');
                projectLine.classList.add('active');
                projectRowWrap.classList.add('active');
            });
    // Mouse out remove all
            background.addEventListener('mouseleave', function() {
                background.classList.remove('active');
                img.classList.remove('active');
                background.classList.remove('active');
                img.classList.remove('active');
                projectTitle.textContent = '';
                projectTitle.classList.remove('active');
                projectLine.classList.remove('active');
                projectRowWrap.classList.remove('active');
            });
        }

另一个方法,或者升级这个解决方案可以使用“data”属性,比如“data-id”或“data-color”,你可以给你想要的名字,并拥有你想要的任意多个“data”属性在 DOM 元素上。 您也可以保存类名,使用 .childNodes 捕获主块的元素的子元素。

我建议在转向 javascript 之前对 html 结构进行一些更新。

我们希望尽可能保持 HTML 结构化。以便于选择相似的元素。

  1. 更容易对项目相关元素进行分组。
  2. 删除不必要的 class 名称。

在必要时添加评论。

<!-- Projects desktop -->
<div id="horizontalScroll" class="horizontalScroll projectsContainer">
    <!-- Photosnap -->
    <div class="projectsWrapper photosnap Background"> <!-- Remove backgound here, if you its needed for class selection in css seperate it -->
        <span class="testFunc hoverTitleFont projectTitle"></span> <!-- Remove photosnap-->
        <div class="testFunc hoverLine"></div> <!-- Remove hoverLinePhotosnap-->
        <img src="assets/projects/photosnap-desktop-p.jpg" alt="photosnap project" class="photosnapImg"> <!-- Since there is only 1 img tag inside photosnap we can select through img tag-->
        <div class="testFunc flexWrapperRow"> <!-- remove flexWrapperRowPhotosnap-->
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Live</span>
            </a>
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Code</span>
            </a>
        </div>
    </div>
    <!-- Dine -->
    <div class="projectsWrapper dine Background"> <!-- seperated background-->
        <span class="testFunc hoverTitleFont projectTitle"></span> <!--remove Dine-->
        <div class="testFunc hoverLine"></div> <!--remove hoverLineDine-->
        <img src="assets/projects/dine-desktop-p.png" alt="dine project" class="dineImg">
        <div class="testFunc flexWrapperRow"> <!--removed flexWrapperRowDine-->
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Live</span>
            </a>
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Code</span>
            </a>
        </div>
    </div>
    <!-- Nike -->
    <div class="projectsWrapper nike Background"> <!--seperated backgound-->
        <span class="hoverTitleFont projectTitle"></span> <!--removed nike-->
        <div class="hoverLine"></div> <!--removed hoverLineNike-->
        <img src="assets/projects/nike-desktop-p.png" alt="nike project" class="nikeImg">
        <div class="flexWrapperRow"> <!--removed flexWrapperRowNike-->
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Live</span>
            </a>
            <a target="_blank" rel="noopener noreferrer" href="">
                <span class="hoverIconFont">View Code</span>
            </a>
        </div>
    </div>
</div>

现在我们有了合适的 html 结构,我们可以转移到 js

  1. 向元素添加class和其他属性的函数
  2. 从元素
  3. 中删除class的函数
// property being an object {textContent: "photosnap", backgroundColor: "red"}
function addProperty(element, property) {
    // I belive there are 4 Elements that need to be selected
    const title = element.querySelector("projectTitle");
    const projectLine = element.querySelector("hoverLine");
    const projectRowWrap = element.querySelector("flexWrapperRow");
    const image = element.querySelector("img");

    // if removing looks like code duplicate elements can be pushed to an array, and iterate over it to add/remove the class
    /*
        const elementList = [];
        elementList.push(element);
        elementList.push(image);
        elementList.push(title);
        elementList.push(projectLine);
        elementList.push(projectRowWrap);
        elementList.forEach(el => {
            el.classList.add("active");
        });
      */
    title.textContent = property.textContent;

    element.classList.add("active");
    image.classList.add("active");
    title.classList.add("active");
    projectLine.classList.add("active");
    projectRowWrap.classList.add("active");


}

function removeProperty(element) {
    const title = element.querySelector("projectTitle");
    const projectLine = element.querySelector("hoverLine");
    const projectRowWrap = element.querySelector("flexWrapperRow");
    const image = element.querySelector("img");
    title.textContent = "";
    element.classList.remove("active");
    image.classList.remove("active");
    title.classList.remove("active");
    projectLine.classList.remove("active");
    projectRowWrap.classList.remove("active");
}

const element = document.querySelector("photosnap");

element.addEventListener("mouseenter", (event) => {
    const eventElement = event.target;
    const property = { textContent: "photosnap" };
    addProperty(eventElement, property);
});

element.addEventListener("mouseleave", (event) => {
    removeProperty(event.target);
});