我现在使用的获取屏幕尺寸的方法是:
export const state = () => ({
deviceType: window.innerWidth <= 600 ? 'mobile' : 'desktop',
})
export const getters = {
getDeviceType(state) {
return state.deviceType
}
}
这个问题是我的网站需要刷新才能看到更改我设置的应该只出现在移动设备上。
我读过有关使用window.addEventListener..
能够解决此问题的内容,因为它在屏幕调整大小时不断触发功能。但我正在寻找一种更直接的方法,最好使用
compulated 或 watcher 。我认为这不是一个好方法,使用 window.innerWidth,因此任何推荐的方法将不胜感激。
提前致谢!
<template>
<h1>{{ type + ": " + width }}</h1>
</template>
<script setup>
import { computed, onMounted, onUnmounted, ref } from "vue"
function useBreakpoints() {
let windowWidth = ref(window.innerWidth)
const onWidthChange = () => windowWidth.value = window.innerWidth
onMounted(() => window.addEventListener('resize', onWidthChange))
onUnmounted(() => window.removeEventListener('resize', onWidthChange))
const type = computed(() => {
if (windowWidth.value < 550) return 'xs'
if (windowWidth.value >= 550 && windowWidth.value < 1200) return 'md'
if (windowWidth.value >= 1200) return 'lg'
return null; // This is an unreachable line, simply to keep eslint happy.
})
const width = computed(() => windowWidth.value)
return { width, type }
}
const { width, type } = useBreakpoints()
</script>
唯一的问题是您必须手动将 css 中的媒体中断与此处定义的中断对齐。
import { reactive } from 'vue'
export enum DeviceSize { xs, s, m, l, xl }
export type DeviceInfo = {
windowWidth: number,
size: DeviceSize,
}
const calcSize = (width: number): DeviceSize => {
if (width < 640) return DeviceSize.xs
if (width < 1024) return DeviceSize.s
if (width < 1280) return DeviceSize.m
if (width < 2048) return DeviceSize.l
return DeviceSize.xl
}
const deviceInfo = reactive({
windowWidth: window.innerWidth,
size: DeviceSize.xs,
})
deviceInfo.size = calcSize(window.innerWidth)
window.addEventListener('resize', () => {
const width = window.innerWidth
deviceInfo.windowWidth = width
deviceInfo.size = calcSize(width)
})
export const useDevice = (): DeviceInfo => {
return deviceInfo
}
export default useDevice
要在组件中使用它:
<script setup lang="ts">
import { useDevice, DeviceSize } from './useDevice'
const device = useDevice()
</script>
<template>
<div v-if="device.size > DeviceSize.s">Some large screen content</div>
</template>
export enum MediaQuery { xs = 420, sm = 640, md = 768, lg = 1024, xl = 1280, '2xl' = 1440, '3xl' = 1600, '4xl' = 1920 }
export function useBreakpoints() {
const windowWidth = ref(window.innerWidth);
const onWidthChange = () => (windowWidth.value = window.innerWidth);
onMounted(() => window.addEventListener('resize', onWidthChange));
onUnmounted(() => window.removeEventListener('resize', onWidthChange));
const mediaQuery = computed(() => {
for (const query of Object.keys(MediaQuery)) {
if (windowWidth.value < MediaQuery[query]) {
return MediaQuery[query];
}
}
return MediaQuery.xs;
});
const width = computed(() => windowWidth.value);
return { width, mediaQuery };
}
并这样使用它:
const { mediaQuery } = useBreakpoints();
if (mediaQuery.value !== MediaQuery.xs) {
// Do something..
});
if (mediaQuery.value < MediaQuery.lg) {
// Do something..
});