我尝试使用 v-if 在页面上的不同容器中渲染 2 个按钮,具体取决于屏幕尺寸 有没有办法如何更改 @media 中项目的父项或如何在 v-if 条件下使用屏幕尺寸?
我试过了
<div v-if="window.innerWidth < 860">
<!-- Some code -->
</div>
但它抛出了我“TypeError:无法读取未定义的属性(读取'innerWidth')”
(当我只使用媒体查询时,无线电 btns 会出现错误,当它们需要点击 2 次才能获取:检查样式时) 当我尝试@media 时,实际上有 4 个按钮,绑定到 2 个变量
<!-- button code -->
<label>
<input type="radio" name="month-season" id="month" value="month" v-model="monthSeason">
<null-button>
<img src="../assets/green-smile.png" alt="#" id="month-icon">
text
</null-button>
</label>
<!-- null-button -->
<div class="parent">
<div class="container">
<slot></slot>
</div>
<div>
<!-- styles for button -->
<style>
.month-season {
text-align: right;
label {
.container {
color: rgba(45, 206, 137, 1);
background: white;
img {
margin: 0 4px 0 0;
}
}
input:checked + .parent .container {
background: rgba(45, 206, 137, 1);
color: white;
img {
filter: brightness(1000%);
}
}
input {
appearance: none;
}
}
}
</style>
使用时出现错误信息
window.innerWidth
您可以使用 useWindowSize (或 useElementSize)。
<script>
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
</script>
<template>
<div v-if="width < 860">
<!-- Some code -->
</div>
<div v-if="width >= 860">
<!-- Some other code -->
</div>
</template>
您在模板中使用的所有 JS 表达式都在所谓的模板上下文中执行。它包含组件中声明的所有内容,并且不包含 JS 全局变量(如
window
)及其 props(如 alert
)。因此,您应该在模板之外使用 window
或添加到 app.config.globalProperties
。
但是将
window
添加到上下文并不能解决你的问题,因为使用它的 JS 表达式不是响应式的,并且你的代码只能在初始组件渲染时工作。
所以你应该在这里做出反应。常见的 Vue3 方法是在这里使用可组合项。
matchMedia
或 window.innerWidth
。
使用
matchMedia
,您可以使用任何您喜欢的 CSS 媒体查询。
因此,在这两种情况下,您都会侦听适当的事件并更新
ref
,以便在模板中进一步使用。
如果您监听
window
,请不要忘记在卸载组件时删除监听器,否则您将遇到幽灵事件处理程序的问题。
所以你的
matchMedia
可组合项:
import {ref} from 'vue';
export function useMatchMedia(query){
const match = window.matchMedia(query);
const isMatching = ref(match.matches);
match.addEventListener('change', e => isMatching.value = e.matches);
return isMatching;
}
您的
window.innerWidth
可组合项:
import {ref, onUnmounted} from 'vue';
export function useInnerWidth(){
const width = ref(window.innerWidth);
const syncWidth = () => width.value = window.innerWidth;
window.addEventListener('resize', syncWidth);
onUnmounted(() => window.removeEventListener('resize', syncWidth));
return width;
}
用法:
<script setup>
import { useMatchMedia } from './useMatchMedia';
const smallScreen = useMatchMedia('(max-width: 859px)');
import { useInnerWidth } from './useInnerWidth';
const innerWidth = useInnerWidth();
</script>
<template>
<h1 v-if="smallScreen">I'm a smaller screen</h1>
<h1 v-else>I'm a bigger screen</h1>
<p v-if="innerWidth < 860">Smaller screen width: {{innerWidth}}</p>
<p v-else>Bigger screen width: {{innerWidth}}</p>
</template>