Reputation: 409
I am working on Nuxt3 project. i want to use different layout for Desktop & Mobile version. on some pages some different components or block depending on device.
For Example this is default.vue in layouts folder
<template>
<!-- Mobile Layout -->
<div v-if="$isMobile()">
<TopMenu />
<NuxtChild />
<Footer />
</div>
<!-- Mobile Layout End -->
<!-- Desktop Layout -->
<a-layout has-sider v-else>
<a-layout-sider
:style="{
background: '#ffffff',
overflow: 'auto',
height: '100vh',
position: 'fixed',
left: 0,
top: 0,
bottom: 0,
}"
:class="`ttc-invisible sm:ttc-visible`"
>
<MainMenu />
</a-layout-sider>
<a-layout :style="{ marginLeft: '202px', background: '#ffffff' }">
<a-layout-header
:class="`ttc-container ttc-mx-auto`"
:style="{
background: '#ffffff',
padding: 0,
position: 'fixed',
zIndex: 1,
width: '100%',
padding: '5px 25px!important',
}"
>
<TopMenu />
</a-layout-header>
<a-layout-content
:style="{
margin: '24px 16px 0',
overflow: 'initial',
padding: '50px 0px 35px 0px',
}"
>
<NuxtChild />
</a-layout-content>
<a-layout-footer
:style="{ padding: '24px 0px 0px 0px', background: '#ffffff' }"
>
<Footer />
</a-layout-footer>
</a-layout>
</a-layout>
<!-- Desktop Layout End -->
</template>
I am trying to learn to write custom plugins in Nuxt3. here what i tried to create using mobile-detect library.
device.js inside plugins folder
import { defineNuxtPlugin } from '#app';
import MobileDetect from 'mobile-detect';
export default defineNuxtPlugin(() => {
let headers = useRequestHeaders()
const md = new MobileDetect(headers['user-agent'])
const isMobile = md.phone() !== null || md.mobile() === 'UnknownMobile'
const isTablet = md.tablet() !== null || md.mobile() === 'UnknownTablet'
const isDesktop = !isMobile && !isTablet
return {
provide: {
isMobile: () => isMobile,
isTablet: () => isTablet,
isDesktop: () => isDesktop
},
};
})
I am getting this error.
runtime-core.esm-bundler.js:571 TypeError: _ctx.$isMobile is not a function
at Proxy._sfc_render (default.vue?import&t=1656113644025:25:16)
at renderComponentRoot (runtime-core.esm-bundler.js:896:44)
at ReactiveEffect.componentUpdateFn [as fn] (runtime-core.esm-bundler.js:5651:34)
at ReactiveEffect.run (reactivity.esm-bundler.js:185:25)
at instance.update (runtime-core.esm-bundler.js:5694:56)
at runtime-core.esm-bundler.js:493:18
at Array.forEach (<anonymous>)
at rerender (runtime-core.esm-bundler.js:485:27)
at Object.rerender (runtime-core.esm-bundler.js:568:20)
at default.vue?import&t=1656113612067:98:25
update
Suddenly Errors are gone and i can check the responses of $isMobile, $isDesktop in true and false.
but when i browse in mobile, first it loads mobile layout and then suddenly it goes back to desktop layout.
How to resolve this problem
Upvotes: 7
Views: 11029
Reputation: 1
I think it could be done with this too : https://vueuse.org/core/useMediaQuery/
quoting their demo page:
import { useMediaQuery } from '@vueuse/core'
const isLargeScreen = useMediaQuery('(min-width: 1024px)')
const isPreferredDark = useMediaQuery('(prefers-color-scheme: dark)')
The var "isLargeScreen" will be true if the browser uses the media query specified. You can do the same for mobile and detect iphones, android too based on that.
vueuse is made to work with nuxt3/vue3 most of their components are pretty straight forward and easy to use. So far im using that and RXJS without noticeable bugs and it works pretty well.
Upvotes: 0
Reputation: 121
Solved the problem. In plugins/device.js the key was:
const md = process.server ? new MobileDetect(headers['user-agent']) : new MobileDetect(navigator.userAgent)
After all:
In order to handle mobile/desktop layouts in Nuxt3 (SSR) we can define browser type using userAgent and then define device type with mobile-detect library (https://www.npmjs.com/package/mobile-detect)
install npm i mobile-detect
yourApp/plugins/device.js:
import {defineNuxtPlugin, useRequestHeaders} from '#app';
import MobileDetect from 'mobile-detect';
export default defineNuxtPlugin(() => {
let headers = useRequestHeaders()
const md = process.server ? new MobileDetect(headers['user-agent']) : new MobileDetect(navigator.userAgent)
const isMobile = md.phone() !== null || md.mobile() === 'UnknownMobile'
const isTablet = md.tablet() !== null || md.mobile() === 'UnknownTablet'
const isDesktop = !isMobile && !isTablet
return {
provide: {
isMobile: () => isMobile,
isTablet: () => isTablet,
isDesktop: () => isDesktop
},
};
})
usage:
<template>
<div v-if="$isMobile()" > show on mobile </div>
</template>
Upvotes: 7