如何在NUXT3中检测用户设备并相应地加载UI

发布于 2025-02-10 07:12:22 字数 3214 浏览 0 评论 0原文

我正在从事NUXT3项目。 我想在桌面上使用不同的布局&移动版。在某些页面上,一些不同的组件或块取决于设备。

例如,这是默认值。

<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>

我正在尝试在NUXT3中学习编写自定义插件。 在这里,我尝试使用移动检测库创建的内容。

device.js插件文件夹

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
        },
    };
})

我遇到此错误。

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

更新

突然错误消失了,我可以检查$ ismobile的响应, $ isdesktop在true and false中。

但是,当我在移动中浏览时,首先会加载移动布局,然后突然返回到桌面布局。

如何解决此问题

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

゛时过境迁 2025-02-17 07:12:22

解决了问题。在插件/device.js中,关键是:

const md = process.server ? new MobileDetect(headers['user-agent']) : new MobileDetect(navigator.userAgent)

毕竟:

为了处理NUXT3(SSR)中的移动/桌面布局,我们可以使用UserAgent定义浏览器类型,然后使用移动检测库定义设备类型( https://www.npmjs.coms.coms.com/package/package/mobile-detect

instalm

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
        },
    };
})

用法:

<template>
  <div v-if="$isMobile()" > show on mobile </div>
</template>

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>
时光清浅 2025-02-17 07:12:22

我认为这也可以做到这一点:

引用其演示页面:

import { useMediaQuery } from '@vueuse/core'

const isLargeScreen = useMediaQuery('(min-width: 1024px)')
const isPreferredDark = useMediaQuery('(prefers-color-scheme: dark)')

如果浏览器使用指定的媒体查询,则VAR“ IslargesCreen”将是正确的。您可以根据此操作和检测iPhone,也可以根据此操作。

Vueuse是与NUXT3/VUE3一起工作的,其大多数组件非常简单且易于使用。到目前为止,我正在使用它,而RXJ则没有明显的错误,并且效果很好。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文