Handling Mobile Responsiveness and More Like a Boss in VueJS with VueX

Using Vuex to Handle Mobile Responsiveness Like a Chief That You Are

responsive-image-vue.png

Well, one very interesting thing about Front-end development as a stack remains that the users get to enjoy and vibe to the interfaces and experiences we put in their hands without realizing the amount of patches and magics we do behind the scene especially when mobile responsiveness is concerned.

Mobile responsiveness can be a very soft thing for experienced developers like myself ( the Tech Lead 😆 ) to handle. However, it can be a pain in the ass for newbies, average developers, our backend fellows, sometimes myself and also but not limited to those who don't enjoy relying on libraries to get simple things done.

Today i will be showing you how you can handle mobile responsiveness using Vuex in Vue like a Boss. So, let's dive right in

What you will be needing for this workshop

  1. Node See how to install Node
  2. Vue CLI See how to install Vue CLI
  3. Vuex See how to create Vue project (remember to choose Vuex option)
  4. VS Code (code editor)

We are going to make a lot of assumptions here. This is not a Vue Crash Course class, i am not going to start from the very scratch. If this is your first time using VueJs, i will recommend you take one of these courses: VueMastery Beginner Course or Net Ninja Vue Youtube PlayList

Assumptions

  1. You are already familiar with VueJS and a lil bit of vuex.
  2. You already created a Vue CLI project and you already have a component you are trying to make responsive.
  3. You already opened up your project folder in VS Code and you are ready to go.

Now, let's get to work..

Firstly,

Install vuex in your project if you haven't. If you have, skip this step and continue anywhere you see this: 🚀🚀🚀.

Navigate to your project folder on your terminal and install vuex using the following command:

npm install vuex --save

Then, navigate to your scr folder in your project root folder. Under your src folder, create another folder and name it store. Inside this store, create a file and name it index.js

Open this src/store/index.js file in your code editor and paste the following boiler plate code.

import Vue from 'vue'
import Vuex from 'vuex'  //how you import vuex from the vuex library

Vue.use(Vuex) // let's you use vuex in vue as plugin

// Below is your default vuex store instance, don't get scared.
export default new Vuex.Store({
  modules: {
  },
  state: {
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  }
})

Then, go ahead and import vuex store in your src/main.js file and also add the store to your vue instance for use, like this...

import Vue from 'vue'
import App from './App.vue'
import store from './truestore' // this is how you import the store. It automatically detects your store/index.js file


Vue.config.productionTip = false

new Vue({
  router,
  store, // this is how you add the store to your vue instance
  render: h => h(App)
}).$mount('#app')

You have successfully installed and setup your vuex store, Yipee 👏.

🚀🚀🚀 Hey Chief, you can now continue with us.

Now,

We need to create a separate store module for checking what device a user is currently using and setting a mobile or not mobile state which we will be using later. Go to your src/store folder and create another folder which we will name modules. Inside this modules folder, create a file and name it checkDeviceState.js.

Open up your checkDeviceState.js file and create a state, getters, mutations, and actions objects. Then you export these objects.

const state = {
}

const getters = {
}

const mutations = {
}

const actions = {
}

export default {
    state,
    getters,
    mutations,
    actions
}

Next,

create a mobile property in your state and set its default value to false

const state = {
    mobile: false
}

Then, create a getter that returns the value of our mobile property in the state.

const getters = {
    mobile: state => {
        return state.mobile
    }
}

.then(

create a property "checkDevice" in your mutations object that checks if the user is on a mobile device or not and updates the mobile property in your state based on that.

const mutations = {
    checkDevice: state => {  // here, we have a function that takes our state as an argument
        if (window.innerWidth <= 410) { 
        // checks if your device width is less than 410 which denotes mobile device. Note, you can set any width you want based on the width you are targeting as mobile device.
            state.mobile = true // sets the mobile property to true if it's a mobile device
        }
        else {
            state.mobile = false // sets the mobile property to false if it's not a mobile device
        }
    }
}

We can now use a lifecycle hook in any of our components or views to trigger this mutation anytime we load a view/page. However, it is generally advisable not to trigger a mutation directly in Vue and some other frameworks especially but not limited to when dealing with asynchronous tasks.

So, we will create an action that will be in charge of triggering the "checkDevice" mutation. Why? This let's us fully trace the mutations and track what user action is changing things in our state. We can then use these information to perform other actions if we like.

Let's create an action called checkMobile

const actions = {
    checkMobile: context => { // a function that takes context as an argument. Context here is literal.
        context.commit('checkDevice') // this piece here commits and triggers the checkDevice mutation. We interact with checkDevice mutation through this action from our components.
    }
}

Now, let's import this store module from our src/modules/checkDeviceState.js file into our store/index.js file, under the modules object.

import Vue from 'vue'
import Vuex from 'vuex'
import deviceCheck from './modules/checkDeviceState'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
      deviceCheck
  },
  state: {
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  }
})

Well done champ, you are almost there 💪🏽💪🏽

Finally,

It's time to utilize this wonderful feature you just wrote in your components or views. Now, pick any component of your choice for experiment here. In your component template, go down to your script scaffold. Its usually something like this:

<script>
export default {
}
</script>

We need to do two (2) simple things here,

  1. We need to create a beforeMount lifecycle to dispatch the checkMobile action in our store. This will trigger the checkDevice function in our mutation, hence change the mobile state to true or false depending on what device the user is currently on, before the component or view is mounted on the browser.
  2. We are also going to use a computed property to access the mobile state.
computed: {
    // this computed property will create a virtual mobile data, like a copy of what our mobile state data is in the store, so we can use it directly from this component. This mobile property also returns true or false.
    mobile () {
      return this.$store.getters.mobile // this is how you access the mobile state in the store
    }
  },
  beforeMount() {
    // this life cycle triggers an action before the component is mounted on the browser.
    this.$store.dispatch('checkMobile') // this is how you dispatch an action in the store, in this case, the checkMobile action.
  }

Another way you can do this is:

Instead of having this setup on all of your components, you can have it in your App.vue file, then pass the mobile computed property as props into all of your components or views or templates.

Very well done. Now that you have acquired all your infinity stones, it's time to flex them.

How would you like to use your mobile computed property?

  • So, let's say you have a template, component, or element you only want to show on mobile or you want to show in other devices except mobile. You just have to use the v-if or v-show directive (anyone you desire) and set the value to mobile or !mobile depending. For example:
<div class="nav" v-if="!mobile"> <!-- this will show only on desktop and not mobile device-->
    <ul>
        <li v-for="items in navItems"></li>
    </ul>
</div>

<br v-if="mobile"> <!--  sometimes you might want to apply a line break to between elements only when on mobile (Especially when you want to achieve a certain look of a long header text). You can handle it like this.-->

<div class="dropdown" v-if="mobile"> <!-- this will show on mobile device only-->
    <ul>
        <li v-for="items in navItems"></li>
    </ul>
</div>
  • You can choose to apply a particular style to a component or an element on mobile device, and apply a different style when on desktop. In essence, it can be used to bind a css class. For example:
<div :class="{'blue-bg': mobile, 'black-bg': !mobile}"> 
<!--this will give this div a blue background on mobile and a black background on desktop or any non mobile device.-->
    <ul>
        <li v-for="items in navItems"></li>
    </ul>
</div>

<style scoped>
.blue-bg{
    background: blue;
}
.balck-bg{
    background: black;
}
</style>
  • You can use it to automatically toggle stuff between mobile and desktop device.

  • You can also use it in your custom methods and functions as values to parameters. Let's say you want to give your users extra bonuses when they login through a mobile device instead of desktop and things like that.

  • Or let's say you want to compute a statistics of what devices your users are using to access your web app, or maybe direct them to use certain pages on desktop instead of a mobile device. Or you want to know if users are switching devices on getting to certain pages. The application is unlimited.

Remember, your creativity is only limited by what you can imagine. Think of more amazing ways to utilize this trick.

Thank you 🙌

Mustapha Abdul-Rasaq's photo

Awesome piece...

Show +1 replies
Adegoke Abdullateef's photo

Adams Abdulhakeem I'm a new developer please between React and Vue which one will you advice to work it.

Adams Abdulhakeem's photo

Hello Adegoke Abdullateef .

I will like to say first that both frameworks are awesome tools on their own, each with it's advantages and disadvantages. However, in the real sense, one will always prevail over the other.

I personally have experimented with React as well as i have with VueJS. And, without bias, will always choose VueJS over React. It has a whole lot of advantages, and it is very beginner friendly as in your own case. It is easy and very powerful at the same time.

Don't take my word for it, you can make your research too. Thank you.

Victor Martins Onuoha's photo

Great post.

However, as much as this is a solution that works, it should not be used for a real-world application.

Show +1 replies
Victor Martins Onuoha's photo

In a real-world application, it would make sense to use this to make decisions; say trigger requests, enable PWA Install, disable features. But in your application here, where you need to show or hide elements based on the device type, CSS can comfortably handle those scenarios. It would be over-engineering - if you decided to use javascript to show and hide elements based on device type.

Adams Abdulhakeem's photo

Basically, the whole idea is to let readers know you can use this methods to perform actions based on user device like i explain close to the end of the article. I used responsiveness cause it will be easier to relate to. Thanks for stating it clearly. Victor Martins Onuoha