1
votes

The idea is to have 'isActive' boolean array in the Vue instance in order to update it every time the navbar gets loaded, i.e using the current page name taken from the URL as an index in the array and set it's value to true; and 'onbeforeunload' setting it to false.

Navbar.vue

<template>
  <div class="navbar">
    <nav>
      <ul>
        <li v-bind:class="{ active: isActive['login'] }">
          <a href="/login">Log in</a>
        </li>
        <li v-bind:class="{ active: isActive['signup'] }">
          <a href="/signup">Sign up</a>
        </li>
      </ul>
    </nav>
  </div>
</template>

<script>    
  import Vue from 'Vue'

  var navbarOpts = {
    name: 'navbar',
    data {
      return {
        isActive: []
      }
    }
  })
  module.exports = navbar

  function pageName(pathname) {} // Returns no-spaced string

  var currentPage = pageName(window.location.pathname)

  if (currentPage !== '') { // If not in home page
    navbar.data().isActive[currentPage] = true
    window.onbeforeunload = function () {
      navbar.data().isActive[currentPage] = false
    }
  }
</script>

Here I would reactively update the current page index (example: 'login') in the array to true, and as new pages get visited (example: 'signup') they will get added as indexes and set to true; and set to false before unloading resources.

Maybe I should use Vue.set(vm.isActive, currentPage, false) so a new property is reactively added to vm.isActive if it doesn't exist or updated. The problem is there is no point in me creating a Vue instance since I can't export it. And if I modify the navbarOpts and export it like I did, navbarOpts gets created everytime Navbar.vue is rendered and everything it holded gets lost.

3
If StackOverflow doesn't help, you may also want to try the Gitter chat: gitter.im/vuejs/vue ; they're super helpful there.Christopher Shroba

3 Answers

0
votes

You don't use the single file component format correctly. You create a component instance and export that, where you should only export the options object used to create a component ( the object that you pass to new Vue({... This object })

0
votes

I finally solved it using another approach I think is more correct.

Navbar.vue

<template>
  <div class="navbar">
    <nav>
      <ul>
        <li v-bind:class="{ active: isActive('login') }">
          <a href="/login">Log in</a>
        </li>
        <li v-bind:class="{ active: isActive('signup') }">
          <a href="/signup">Sign up</a>
        </li>
      </ul>
    </nav>
  </div>
</template>

<script>
  export default {
    name: 'navbar',
    data () {
      return {
        path: window.location.pathname
      }
    },
    methods: {
      isActive (page) {
        return this.currentPage === page
      }
    },
    computed: {
      currentPage () {
        if (this.path.length === 1) return ''
        const endIndex = this.path.indexOf('/', 1)
        return (endIndex === -1)
          ? this.path.substring(1)
          : this.path.substring(1, endIndex)
      }
    }
  }
</script>
0
votes

You can make use of the route's path property, check out the doc here...

<template>
 <div class="sidebar sidebar-main sidebar-fixed">
   <div class="sidebar-content">
      <div class="sidebar-category sidebar-category-visible">
       <div class="category-content no-padding">
        <ul class="navigation navigation-main navigation-accordion">
         <li :class="{ active: isActive('dashboard') }">
          <router-link to="/dashboard">Dashboard</router-link>
         </li>    

         <li :class="{ active: isActive('profile') }">
          <router-link to="/dashboard">Profile</router-link>
         </li>    
        </ul>
       </div>
      </div>
     </div>
    </div>
</template>

<script>
 export default {
  name: 'SideBar',      
  methods: {
   isActive(page) {
     return this.$route.path.indexOf(page) !== -1;
   }
  }
 }
</script>