vue项目如何监听窗口变化,达到页面自适应?

本文介绍如何在Vue项目中实现自适应布局,通过监听窗口变化调整屏幕宽度,并根据宽度变化实时更新div或img元素的高度,确保在不同屏幕尺寸下保持良好的视觉效果。

【自适应】向来是前端工程师需要解决的一大问题——即便作为当今非常火热的vue框架,也无法摆脱——虽然elementui、iview等开源UI组件库层出不穷,但官方库毕竟不可能满足全部需求,因此我们可以通过【监听窗口变化】达到想要的绝大部分自适应效果。

获取窗口宽度:document.body.clientWidth
监听窗口变化:window.onresize

同时回顾一下JS里这些方法:
网页可见区域宽:document.body.clientWidth
网页可见区域高:document.body.clientHeight
网页可见区域宽:document.body.offsetWidth (包括边线的宽)
网页可见区域高:document.body.offsetHeight (包括边线的宽)

我们将document.body.clientWidth赋值给data中自定义的变量:

data:{
    screenWidth: document.body.clientWidth
}

在页面mounted时,挂载window.onresize方法:

mounted () {
    const that = this
    window.onresize = () => {
        return (() => {
            window.screenWidth = document.body.clientWidth
            that.screenWidth = window.screenWidth
        })()
    }
}

监听screenWidth属性值的变化,打印并观察screenWidth发生变化的值:

watch:{
    screenWidth(val){
        // 为了避免频繁触发resize函数导致页面卡顿,使用定时器
        if(!this.timer){
            // 一旦监听到的screenWidth值改变,就将其重新赋给data里的screenWidth
            this.screenWidth = val
            this.timer = true
            let that = this
            setTimeout(function(){
                // 打印screenWidth变化的值
                console.log(that.screenWidth)
                that.timer = false
            },400)
        }
    }
}

好!既然可以监听到窗口screenWidth值的变化,就可以根据这个值设定不同的自适应方案了!

 

【举个例子:div或img图片高度随宽度自适应】

div或img的宽度自适应很简单——设定css里width属性为百分比即可——但是高度呢?父级元素的高度并不是固定的(通常都是子级元素撑开的)

如上图,一个类似【图片库】的功能,当屏幕放大缩小时,我们可以设置外层边框(也就是灰色框框)的宽度为100%,以达到自适应——但高度无法设置,因此我们需要:

  1. 数据加载完后,获取图片(或外层框)的宽度
  2. 根据这个宽度,设置外层框的高度(如:宽度的60%)
  3. 监听窗口screenWidth值的变化,每次变化都重新获取宽度,并重新设置高度

所以,我们只需在前文代码的基础上,添加以下代码,以确保屏幕缩放时,每次监听宽度变化

mounted() {
    // 1、数据首次加载完后 → 获取图片(或外层框)宽度,并设置其高度
    this.$nextTick(() => {
        // 获取图片(或外层框)
        let imgBox = this.$refs.imgBox
        // 获取其宽度
        let wImgbox = imgBox[0].getBoundingClientRect().width
        // 设置其高度(以宽度的60%为例)
        this.imgBox.height = 0.6 * wImgbox + 'px'
    })
    // 2、挂载 reisze 事件 → 屏幕缩放时监听宽度变化
    const that = this
    window.onresize = () => {
        return (() => {
            // window.screenWidth = document.body.clientWidth
            // that.screenWidth = window.screenWidth
            // console.log(that.screenWidth)
            this.$nextTick(() => {
                let imgBox = this.$refs.imgBox
                let wImgbox = imgBox[0].getBoundingClientRect().width
                this.imgBox.height = 0.6 * wImgbox + 'px'
            })
        })()
    }
},

最终实现效果如下:

### Vue 实现页面自适应方法 #### 使用 `getPageSize` 方法获取页面尺寸信息并动态调整布局 为了使页面能够根据不同的设备类型(移动端、平板端或桌面端)自动调整布局,可以通过编写一个名为 `getPageSize` 的函数来计算当前窗口的宽度和高度,并判断属于哪种类型的设备。此方法返回的对象不仅包含具体的尺寸数值还带有标识符以便于后续逻辑处理[^1]。 ```javascript function getPageSize() { const width = document.documentElement.clientWidth; const height = document.documentElement.clientHeight; let deviceType; if (width >= 768 && width < 992) { deviceType = "tablet"; } else if (width >= 992) { deviceType = "desktop"; } else { deviceType = "mobile"; } return { width, height, ratio: width / height, isMobile: deviceType === "mobile", isTablet: deviceType === "tablet", isDesktop: deviceType === "desktop" }; } ``` #### 利用视窗单位 vw/vh 进行响应式设计 除了通过 JavaScript 来检测屏幕大小外,在 CSS 中采用视窗单位也是一种有效的手段。vw 和 vh 分别表示相对于整个视窗宽度与高度的比例值,这允许开发者创建更加灵活且易于维护的设计方案[^5]。 ```css .container { padding: 3vh; /* 上下内边距为视窗高度的3% */ } .item { font-size: 2vw; /* 字体大小随视窗宽度变化而改变 */ } ``` #### 结合 Vuex 存储状态管理工具同步屏幕宽度至全局状态树 对于复杂的单页应用来说,可能涉及到多个组件间共享同一份关于屏幕尺寸的信息。此时可以借助 Vuex 将此类公共数据集中存储起来并通过 mutation 或 action 更新它;同时利用 Vue 提供的原型链扩展机制注册一个全局事件总线用于跨组件通信[^3]。 ```javascript // src/store/index.js import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export default new Vuex.Store({ state: { screenWidth: window.innerWidth }, mutations: { SET_SCREEN_WIDTH(state, payload) { state.screenWidth = payload.width; } }, actions: { updateScreenWidth({ commit }) { commit('SET_SCREEN_WIDTH', { width: window.innerWidth }); } } }); Vue.prototype.$bus = new Vue(); ``` 当监听窗口发生重绘时触发相应的更新动作: ```javascript window.addEventListener('resize', () => store.dispatch('updateScreenWidth')); ``` #### 应用 rem 单位适配多分辨率下的字体显示效果 考虑到不同平台上的默认字体渲染差异较大,推荐使用基于 HTML 文档根节点设置的基础字号作为参照系——即 rem ——来进行进一步细化控制。这种方式有助于保持整体风格的一致性和可读性,尤其是在面对多种规格的设计稿时尤为有用[^4]。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <title>Document</title> <style> :root { --base-font-size: 16px; } @media screen and (max-width: 767px){ :root{ --base-font-size: 14px; } } body { font-size: var(--base-font-size); } </style> </head> <body> <script type="text/javascript"> document.querySelector(':root').style.setProperty('--base-font-size', `${Math.min(document.documentElement.clientWidth / 19.2, 50)}px`); </script> </body> </html> ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值