v-if - 基于屏幕尺寸的条件

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

我尝试使用 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
when using window.innerWidth

javascript html css vue.js vuejs3
2个回答
1
投票

您可以使用 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>

0
投票

Vue3 SFC 游乐场

您在模板中使用的所有 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>
© www.soinside.com 2019 - 2024. All rights reserved.