programing

모바일 브라우저의 다양한 Vuejs 컴포넌트 표시

lovecodes 2022. 7. 27. 23:56
반응형

모바일 브라우저의 다양한 Vuejs 컴포넌트 표시

Vue 2.0을 사용하여 SPA를 개발 중입니다.지금까지 개발된 컴포넌트는 "데스크탑" 브라우저용입니다.예를 들어,

Main.vue, Product List.vue, Product Detail.vue,

Main Mobile과 같은 모바일 브라우저용 컴포넌트 세트를 원합니다.vue, Product List Mobile.vue, Product Detail Mobile.vue,

궁금한 점은 모바일브라우저로 표시할 때 SPA에서 컴포넌트의 모바일버전을 렌더링하려면 어디서 어떻게 해야 하나요?

컴포넌트가 반응하지 않도록 주의해 주십시오.두 가지 버전으로 나눠서 보관하고 싶어요.

고마워요.

Vue.js를 위한 간단한 솔루션이 있습니다.

<div v-if="!isMobile()">
  <desktop>
  </desktop>
</div>
<div v-else>
  <mobile>
  </mobile>
</div>

방법:

methods: {
 isMobile() {
   if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
     return true
   } else {
     return false
   }
 }
}

브라우저가 모바일 또는 데스크톱에서 열려 있는지 여부를 검출하는 믹스인을 사용하는 것이 좋습니다( 답변의 js 코드 예).v-if를 사용합니다. 예:

<production-list v-if="!isMobile()"></production-list>
<production-list-mobile v-else></production-list-mobile>

여기 https://jsfiddle.net/Ldku0xec/의 예가 있습니다.

같은 문제가 있었는데 모바일과 데스크톱에서 접근할 수 있는 레이아웃이 없는 중립 vue 파일(Init.vue)을 사용하여 해결했습니다.이 파일은 올바른 파일로 리다이렉트 됩니다.

메인호가 있다고 가정해 봅시다.vue 및 Main Mobile.vue. Init을 추가합니다.리다이렉트되는 vue.라우터/index.js는 다음과 같습니다.

import Router from 'vue-router'
import Vue from 'vue'
import Main from '@/components/Main'
import MainMobile from '@/components/MainMobile'
import Init from '@/components/Init'

Vue.use(Router)

export default new Router({
  routes: [
     {
        path: '/',
        name: 'Root',
        component: Init
     },
    {
      path: '/Main',
      name: 'Main',
      component: Main
    },
    {
      path: '/MainMobile',
      name: 'MainMobile',
      component: MainMobile
    },
  ]
})

초기 단계에서vue 파일, 모바일/패키지 검출이 실행됩니다.

<template>
</template>
<script>
    export default {
        name: 'Init',
        methods: {
            isMobile() {
                if( screen.width <= 760 ) {
                    return true;
                }
                else {
                    return false;
                }
            }
        },
        created() {
            if (this.isMobile()) {
                this.$router.push('/MainMobile');
            }
            else {
                this.$router.push('/Main');
            }
        }
    }
</script>
<style scoped>
</style>

사용되는 isMobile() 함수는 매우 단순하며 다른 함수로 변경할 수 있습니다.

이에 대한 솔루션을 찾고 있었는데 필요한 솔루션을 찾을 수 없었습니다.

  1. 뷰포트에 따라 필요한 것만 번들에 로드하기 위한 비동기 Import.
  2. 레이아웃의 크기가 변경된 경우 다른 레이아웃을 사용할 수 있습니다.

저는 온라인에서 읽은 몇 가지 내용(여기 답변 포함)을 혼합하여 매칭했습니다.그래서 다시 돌아와서 제가 배운 모든 것을 한 가지 함수에 담아서 다른 사람들이 볼 수 있도록 하겠습니다.

/**
 * Breakpoint configuration to be in line with element-ui's standards
 * @type {{LABELS: string[], VALUES: number[]}}
 */
const BREAKPOINTS = {
    LABELS: ['xs', 'sm', 'md', 'lg', 'xl'],
    VALUES: [0, 768, 992, 1200, 1920, Infinity]
};


/**
 * @typedef ViewFactory
 * @type function
 * A function which returns a promise which resolves to a view. Used to dynamically fetch a view file on the fly during
 * run time on a need basis
 */


/**
 * A helper to get a responsive route factory which renders different views based on the current view point
 * @param {{xs:[ViewFactory],sm:[ViewFactory],md:[ViewFactory],lg:[ViewFactory]}} map - A map of breakpoint key to a ViewFactory
 * @returns {ViewFactory} - A view factory which invokes and returns an item supplied in the map based on the current viewport size
 */
export default function responsiveRoute(map) {
    return function getResponsiveView() {
        const screenWidth = document.documentElement.clientWidth;

        // Find the matching index for the current screen width
        const matchIndex = BREAKPOINTS.VALUES.findIndex((item, idx) => {
            if (idx === 0) {
                return false;
            }
            return screenWidth >= BREAKPOINTS.VALUES[idx - 1] && screenWidth < BREAKPOINTS.VALUES[idx];
        }) - 1;


        if (map[BREAKPOINTS.LABELS[matchIndex]]) {
            // Perfect match, use it
            return map[BREAKPOINTS.LABELS[matchIndex]]();
        } else {
            // Go down the responsive break points list until a match is found
            let counter = matchIndex;
            while (counter-- > 0) {
                if (map[BREAKPOINTS.LABELS[counter]]) {
                    return map[BREAKPOINTS.LABELS[counter]]();
                }
            }
            return Promise.reject({
                code: 500,
                info: 'No component matched the breakpoint - probably a configuration error'
            });
        }
    };
} 

사용방법:

const router = new Router({
    mode: 'history',
    base: process.env.BASE_URL,
    routes:[{
      path: '/login',
      name: 'login',
      component: responsiveRoute({
          // route level code-splitting
          // this generates a separate chunk (login-xs.[hash].js) for this route
          // which is lazy-loaded when the route is visited.
          xs: () => import(/* webpackChunkName: "login-xs" */ './views/Login/Login-xs.vue'),
          // sm key is missing, it falls back to xs
          md: () => import(/* webpackChunkName: "login-md" */ './views/Login/Login-md.vue')
          // lg, xl keys are missing falls back to md
      }) 
  }]
}); 

구조:

뷰 로이터 통신은 뷰 Router는 뷰 Router의 정의를 지원합니다를 지원합니다.component키는 약속 async 노선을 지원하기 위해 returns 함수로.key는 비동기약속을 반환하는 함수입니다 지원한다는 루트를.가장 흔한 방법은webpack 가장 일반적인을 사용하는 것인팩을 사용하는 것입니다 웹 방법은.import()는 약속 returns 기능.약속을 반환하는 함수입니다.그 경로가 우리가 게으른 우리의 components약속을 반환하는 함수는 컴포넌트를 느리게 로드할 수 있도록 루트가 렌더링될 때만 호출됩니다를 로드할 수 있는지 확인하여 제출해 그 약속을 반환하는 기능만 호출됩니다.

responsiveRoute기능괄 때 호출된 검사 정확한 약속 공장 및 반환의 약속을 그것에 의해 반환을 호출합니다 사용 가능한 뷰 포트 크기와 혜택을 주기 위한 기능을 반환합니다 이러한 기능들의 키 다른 중단점을 설정된 지도를 사용합니다.

주의:

이 방법은 애플리케이션 아키텍처나 루트 설정을 특정 방식으로 할 필요가 없기 때문에 마음에 듭니다.Vue Router 기능을 사용하면 즉시 사용할 수 있습니다.또한 모든 브레이크 포인트와 루트의 조합에 대해 뷰를 정의하도록 강제하지는 않습니다.이 루트는 문제없이 사용하는 다른 루트에 따라 정상적으로 정의할 수 있습니다(Lazy Loaded 여부).

이 메서드지만 의 이용 가능한 폭을 사용하여 사용자 에이전트를 흡입을 사용하지 않습니다.document.documentElement대신.나는 권장하는 것을 볼 다른 방법.window.screen.width어떤 관계 없이 창문 크기나 더 강력한의 정확한 장치 화면 크기를 준다.window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth. 섞어 준 짝으로 필요하다.

저의 브레이크 포인트는 (숫자와 그 값)이 엘리먼트-의 브레이크 포인트에 근거하고 있기 때문에, 통상의 반응 설계에 사용되었습니다.이는 상단의 상수를 변경하여 필요에 따라 다시 구성할 수 있습니다.

그러기엔 조금 늦었지만 뷰포트 크기를 위해 와치터를 바인드하거나 페이지가 로드될 때마다 체크하는 경우가 있습니다.쓰기에는 많은 양의 보일러 플레이트가 사용되지만, 소규모 애플리케이션에 유용합니다.

export default {
  data: () => ({
    isMobile: false
  }),

  beforeDestroy () {
    if (typeof window !== 'undefined') {
      window.removeEventListener('resize', this.onResize, { passive: true })
    }
  },

  mounted () {
    this.onResize()
    window.addEventListener('resize', this.onResize, { passive: true })
  },

  methods: {
    onResize () {
      this.isMobile = window.innerWidth < 600
    }
  }
}

vuetify 사용자의 경우 동적 구성 요소 로딩과 함께 중단점을 사용할 수 있습니다.DesktopLayout이라는 두 가지 컴포넌트가 있다고 가정합니다.vue 및 MobileLayout.vue. 다른 레이아웃을 로드하는 페이지에서 다음과 같은 동적 구성요소를 정의합니다.

<component :is="currentComponent"></component>

current Component라는 계산 속성을 추가합니다.

computed: {
    currentComponent() {
        return this.$vuetify.breakpoint.xsOnly
            ? "MobileLayout"
            : "DesktopLayout";
    }
}

this.$vuetify.breakpoint.xsOnly여분의 작은 화면에만 사용"MobileLayout" 이룰 수 있을까.많은 중단점 vuetify에 정의되어 있다.예를 들어 중간 사이즈에"mdAndDown"을 사용하여 화면 아래에 의한 범위를 선택할 수 있다.

Beaudinn Greves의 확장 버전은 다음과 같습니다.

  • 명명된 라우터 뷰 사용
  • 창 크기를 조정하여 isMobile true로 설정합니다(너비가 xy보다 작으면).
  • router.model에서는 "컴포넌트"가 아닌 "컴포넌트"를 사용하여 데스크톱 및 모바일컴포넌트를 Import합니다(필요한 컴포넌트를 사용할 수 있습니다).

App.vue:

<template>
  <div id="app" class="container grid-lg">
    <router-view v-if="!store.app.isMobile"/>
    <router-view v-else name="mobile"/>
  </div>
</template>
...
name: "app",
  data: function() {
  return {
    store: this.$store.state
  };
},
mounted () {
  this.onResize()
  window.addEventListener('resize', this.onResize, { passive: true })
},
methods: {
  onResize () {
    this.store.app.isMobile = window.innerWidth < 600
  }
},
beforeDestroy () {
  if (typeof window !== 'undefined') {
    window.removeEventListener('resize', this.onResize, { passive: true })
  }
}

router.syslog:

routes: [
  {
    path: '/',
    name: 'home',
    components: {
      default: Home,
      mobile: HomeMobile
    }
  }
]

조금 늦은 감이 있지만, 혹시 찾으시는 분이 계시다면 이렇게 처리 방법은 다음과 같습니다.라우터에 메타를 추가했습니다.

const router = new Router({
     routes: [{
      path: '/main-view
      name: 'mainView',
      component: MainView,
      meta: {
        'hasMobileView': true
      }
     },
    {
     path: '/mobile-view',
      name: 'mobileView',
      component: mobileView,
      meta: {
        'hasDesktopView': true
      }
     },
    }]
})

then on beforeeach function 

router.beforeEach((to, from, next) => {
  const hasMobileView = to.matched.some((route) => route.meta.hasMobileView)
  if (hasMobileView) {
    if (navigator.userAgent.match(/Android/i) ||
      navigator.userAgent.match(/webOS/i) ||
      navigator.userAgent.match(/iPhone/i) ||
      navigator.userAgent.match(/iPad/i) ||
      navigator.userAgent.match(/iPod/i) ||
      navigator.userAgent.match(/BlackBerry/i) ||
      navigator.userAgent.match(/Windows Phone/i)) {
      next('/mobile-view')
    } else {
      next()
    }
  }
})`

내게 더 좋은 해결책이 있어src/main.js의 경우:

 if (condition) {
    require('./pc/main)
 }else {
    require('./mobile/main')
}

사용자 에이전트를 가져와 해석하기만 하면 변수 is Mobile이 됩니다.이 답변에 이 컴포넌트(데스크탑과 모바일)를 Import 할 때 중요한 점을 언급하고 싶습니다.사용자가 페이지를 방문하면 양쪽 컴포넌트 모두 다운로드 됩니다.

솔루션은 다음과 같습니다.

<template>
 <component :is="headerInstance" />
</template>

<script>
export default {
computed: {
    headerInstance() {
      const component = this.isMobile
        ? '/HeaderMobile'
        : '/HeaderDesktop'
      return () => import(`@/components/Layouts/Header${component}`)
    }
}
}
</script>

리소스/js/컴포넌트/옵션.표시하다

<template>
    <div class="text-right mt-6 ml-16 fixed">
        <div v-if="isMobile()" class="px-0.5 py-0.5 hidden portrait:block">
            {/* ... */}
        </div>
        <div v-else class="px-0.5 py-0.5">
            {/* ... */}
        </div>
    </div>
</template>

<script>
    export default {
        methods: {
            isMobile() {
                if ('maxTouchPoints' in navigator) return navigator.maxTouchPoints > 0 ? true : false
                else return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
            }
        }
    }
</script>

tailwind.config.syslog

module.exports = {
    purge: [],
    theme: {
        extend: {
            screens: {
                'portrait': {'raw': '(orientation: portrait)'},
            }
        }
    },
    variants: {
        extend: {}
    },
    plugins: []
}

데스크톱 전체

데스크톱 전체

소형 데스크톱

소형 데스크톱

모바일 초상화

모바일 초상화

모바일 환경

모바일 환경

가 모바일인지 확인해야 합니다.

const isMobile=() =>( window.innerWidth <= 760 )

언급URL : https://stackoverflow.com/questions/48515023/display-different-vuejs-components-for-mobile-browsers

반응형