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

问题描述 投票:0回答:3

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

例如,这是布局文件夹中的 default.vue

<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 真假。

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

如何解决这个问题

nuxt.js vuejs3 nuxtjs3
3个回答
1
投票

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

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

毕竟:

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

安装

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

用法:

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

0
投票

我认为这也可以做到:https://vueuse.org/core/useMediaQuery/

引用他们的演示页面:

import { useMediaQuery } from '@vueuse/core'

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

如果浏览器使用指定的媒体查询,则变量“isLargeScreen”将为真。您可以对移动设备执行相同的操作并基于此检测 iphones 和 android。

vueuse 可以与 nuxt3/vue3 一起使用,它们的大多数组件都非常简单易用。到目前为止,我正在使用它和 RXJS,没有明显的错误,而且效果很好。


0
投票

上面的方案解决了我的问题,我的项目是nuxt3,但是有一个小问题,就是在通过浏览器调试项目的时候,不能识别手机,这个很好理解。但是跳转路线不识别,只是刷新整个页面。

© www.soinside.com 2019 - 2024. All rights reserved.