Script in Vue.js component isn't executed

Viewed 155

I created a component for my navigation bar, which I load in my header component. It is rendered and works as expected. The only problem I have is that the script, e.g. the mounted function isn't executed. That is really weird, because in the other components that works properly.

Nav component

<template>
  <div id="header-top">
    <img id="logo" src="../assets/img/logo.png" alt="Logo" draggable="false" />
    <div id="nav">
      <router-link to="/">Home</router-link>
      <router-link to="/abc">abc</router-link>
      <router-link to="/cba">cba</router-link>
      <router-link to="/def">edf</router-link>
    </div>
  </div>
</template>

<script>
export default {
  mounted() {
    let headerTop;

    window.addEventListener("scroll", function() {
      if (!headerTop) headerTop = document.getElementById("header-top");

      if (window.scrollY !== 0 && headerTop) {
        headerTop.classList.add("header-top-home-scrolled", "header-scrolled");
      } else if (headerTop) {
        headerTop.classList.remove("header-top-home-scrolled");
      }
    });
  }
}
</script>

Header (where I import and use the navigation)

<template>
    <header id="header-home">
      <Nav/>
      <div id="header-home-content">
        <h1>Lorem ipsum</h1>
      </div>
    </header>
</template>

<script>
import Nav from '@/components/Nav'

export default {
  components: {
    Nav
  }
}
</script>

If you can spot a mistake, please tell me. Thanks in advance.

1 Answers

I'm unable to see why it's not working, I replicated the code on codepen, and it worked fine.

It's not recommended to manually manipulate the DOM, and try to avoid it wherever you can. Here's an alternate way to write that component:

<template>
  <div :class="headerClass">
    <img id="logo" src="../assets/img/logo.png" alt="Logo" draggable="false" />
    <div id="nav">
      <router-link to="/">Home</router-link>
      <router-link to="/abc">abc</router-link>
      <router-link to="/cba">cba</router-link>
      <router-link to="/def">edf</router-link>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      hasBodyScrolled: false
    }
  },
  mounted() {
    window.addEventListener('scroll', this.onScroll, { passive: true });
  },
  destroyed() {
    window.removeEventListener('scroll', this.onScroll)
  },
  computed: {
    headerClass() {
      return {
        'header-top-home-scrolled': true,
        'header-scrolled': this.hasBodyScrolled
      }
    }
  },
  methods: {
    onScroll() {
      this.hasBodyScrolled = window.scrollY !== 0;
    }
  }
}
</script>

Here we are simply using a computed property to determine the class of the header. It depends on the hasBodyScrolled data property. The method onScroll will change the value of hasBodyScrolled to a boolean. And in the template we simply use the computed property as class name for our header. Learn more about class and style bindings.

Related