Solving Common Vue Problems — List Filtering, Global Libraries, Vuex, and More

John Au-Yeung - Jan 26 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

Vue.js makes developing front end apps easy. However, there are still chances that we’ll run into problems.

In this article, we’ll look at some common issues and see how to solve them.

Filtering Lists in Vue Components

The proper way to filter lists is to use a computed property.

This is because computed properties return a value before v-for is run.

For instance, we can write:

computed: {
  filteredItems() {
    return this.items.filter(item => item.type.toLowerCase().includes(this.search.toLowerCase()))
  }
}
Enter fullscreen mode Exit fullscreen mode

We put our filtering logic in the filterItems computed properties.

Then we can loop through the computed properties by writing:

<div v-for="item of filteredItems" >
  <p>{{item.name}}</p>
</div>
Enter fullscreen mode Exit fullscreen mode

We just pass in the filteredItems computed property as a variable into our template.

Making HTTP Calls in Vue Components

We can make HTTP calls in Vue components with the Fetch API or a 3rd party HTTP client library like Axios.

For example, we can write:

methods: {
  async getData(){
    const res = await fetch('/some/url')
    const data = await res.json();
    this.data = data;
  }
}
Enter fullscreen mode Exit fullscreen mode

fetch returns a promise so we can use async and await with it.

Remove the Hash from a URL

We can remove hashes from URLs generated by Vue Router by using history mode.

To enable it, we can write:

const router = new VueRouter({
  mode: 'history'
})
Enter fullscreen mode Exit fullscreen mode

We set the mode to 'history' so that we can remove the hash.

Listening to Props Changes

We can listen to props changes by using the watchers.

To add a watcher for a prop, we can add a method to the watch property.

For instance, we can write:

{
  ...
  `props: ['myProp'],
  watch: {
    myProp(newVal, oldVal) {
      console.log(newVal, oldVal)
    }
  }
  ...
`}
Enter fullscreen mode Exit fullscreen mode

We have the watch property and the myProp prop as indicated by the props property’s value.

We just make a method with the same name as the prop with a signature that takes the new and old values respectively.

Then we get the newVal value to get the new value, and the oldVal value to get the old value.

To start watching immediately when the prop value is set, we can add the immediate property and set it to true .

For example, we can write:

watch: {
  myProp: {
    immediate: true,
    handler (val, oldVal) {
      // ...
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Communication Across Any Components

We can communicate between any components with the this.$dispatch method to dispatch an event that’s propagated to all components.

Then we can use this.$on to listen to the event that’s dispatched by this.$dispatch .

For example, we can write the following in one component:

export default {
  ...
  `created() {
    this.$dispatch('child-created', this)
  }
  ...
}`
Enter fullscreen mode Exit fullscreen mode

Then in another component, we can write:

export default {
  ...
  `created() {
    this.$on('child-created', (child) => {
      console.log(child)
    })
  }
  ...
}`
Enter fullscreen mode Exit fullscreen mode

We emit the event in the created hook so the event is emitted when the component is created but DOM content isn’t loaded yet.

In the 2nd component, we add the event listener in the created hook so that we can listen to events as soon as the component code is loaded.

child-created is the event name.

The child parameter has the event data in the 2nd argument of $dispatch .

Using Axios Globally in a Vue App

To make Axios available globally, we can set it as the property of Vue.prototype before we create the Vue instance.

This way, it’ll be returned with the Vue instance if we create the Vue instance.

For example, we can write:

import Axios from 'axios'

Vue.prototype.$http = Axios;
Enter fullscreen mode Exit fullscreen mode

Then in our components, we can access it by using the this.$http variable.

For instance, if we want to make a get request, we can write:

this.$http.get('https://example.com')
Enter fullscreen mode Exit fullscreen mode

Vuex Action vs Mutations

Vuex mutations are synchronous code that takes a name and a handler.

It’s used to update a state.

For instance, we can write:

import Vuex from 'vuex'

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment(state) {
      state.count++
    }
  }
})
Enter fullscreen mode Exit fullscreen mode

Then state.count++ updates the count state when we dispatch the 'increment' action.

An action is like a mutation, but it can dispatch multiple mutations.

It can also be async.

For example, we can write:

incrementBy({ dispatch }, amount) {
  dispatch('INCREMENT', amount)
}
Enter fullscreen mode Exit fullscreen mode

The dispatch function is a function to dispatch mutations.

Conclusion

There are differences between Vuex actions and mutations.

To filter items, we should do them in computed properties.

We can put things in Vue.prototype to make them available globally.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .