Vue.js Device Detection Approaches
Two primary methods exist for device-responsiev content rendering: CSS media queries and the vue-mq library. This implementation utilizes the vue-mq library for device breakpoint mnaagement.
Installing vue-mq
Install the package via npm:
npm install vue-mq
Configure in main.js:
import Vue from 'vue';
import VueMq from 'vue-mq';
Vue.use(VueMq, {
breakpoints: {
phonePortrait: 320,
phoneLandscape: 480,
tabletPortrait: 768,
tabletLandscape: 1024,
desktop: Infinity
}
});
Vuex Integration Setup
Since vue-mq doesn't natively integrate with Vuex, configure the store to track device state:
// store/index.js
export default new Vuex.Store({
state: {
currentDevice: 'desktop'
},
mutations: {
SET_DEVICE_TYPE(state, deviceType) {
state.currentDevice = deviceType;
}
}
});
Implement device detection in the root component:
<!-- App.vue -->
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
mounted() {
window.addEventListener('resize', this.handleResize);
this.determineDeviceType();
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize);
},
methods: {
handleResize() {
this.determineDeviceType();
},
determineDeviceType() {
const width = window.innerWidth;
const isMobileDevice = width <= 768;
this.$store.commit('SET_DEVICE_TYPE', isMobileDevice ? 'mobile' : 'desktop');
}
}
};
</script>
Component Implementation
Access device state in components using Vuex mapping:
<!-- DeviceAwareComponent.vue -->
<template>
<div class="component-container">
<mobile-layout v-if="isMobileView" />
<desktop-layout v-else />
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
computed: {
...mapState(['currentDevice']),
isMobileView() {
return this.currentDevice === 'mobile';
}
}
};
</script>
Alternatively, use vue-mq's direct approach:
<template>
<div class="responsive-component">
<div v-if="$mq === 'desktop'">
<!-- Desktop-specific content -->
</div>
<div v-else-if="['phonePortrait', 'phoneLandscape'].includes($mq)">
<!-- Mobile phone content -->
</div>
<div v-else>
<!-- Tablet and other device content -->
</div>
</div>
</template>