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

欢迎关注前端小讴的github,阅读更多原创技术文章

【自适应】向来是前端工程师需要解决的一大问题——即便作为当今非常火热的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'
            })
        })()
    }
},

最终实现效果如下:

图片描述

208 声望
16 粉丝
0 条评论
推荐阅读
Promise源码渐进式解读(五)
Promise源码解读系列的最后 1 篇,详解Promise构造函数的最后几个方法及.finally,封装isArray判断对象是否为数组:

小讴阅读 688

Vue中的diff算法
diff算法是一种通过同层的树节点进行比较的高效算法,避免了对树进行逐层搜索遍历,所以时间复杂度只有 O(n)。diff算法的在很多场景下都有应用,例如在 vue 虚拟 dom 渲染成真实 dom 的新旧 VNode 节点比较更新时...

款冬27阅读 14.1k评论 7

【已结束】SegmentFault 思否写作挑战赛!
SegmentFault 思否写作挑战赛 是思否社区新上线的系列社区活动在 2 月 8 日 正式面向社区所有用户开启;挑战赛中包含多个可供作者选择的热门技术方向,根据挑战难度分为多个等级,快来参与挑战,向更好的自己前进!

SegmentFault思否20阅读 5k评论 10

封面图
vue-property-decorator使用手册
@Component 装饰器可以接收一个对象作为参数,可以在对象中声明 components ,filters,directives等未提供装饰器的选项,也可以声明computed,watch等

似曾相识17阅读 29.6k评论 7

前端开发工具
前端教程阿西河前端教程丨一个助你成为全栈开发的网站前端高手进阶JavaScript利用js实现表单的校验KeyCode 查询表现代 JavaScript 教程时间戳(Unix timestamp)转换工具HTML minifierJavaScript代码压缩-js代码压...

寒青14阅读 2.6k

万字长文~vue+express+mysql带你彻底搞懂项目中的权限控制(附所有源码)
所谓的权限,其实指的就是:用户是否能看到,以及是否允许其对数据进行增删改查的操作,因为现在开发项目的主流方式是前后端分离,所以整个项目的权限是后端权限控制搭配前端权限控制共同实现的

水冗水孚11阅读 1.5k

[译]Vue.js + Astro 比 Vue SPA 更好吗?
在本文中,我将向您展示如何使用 Astro 构建基于 Vue 的应用程序,我们将了解其独特的架构如何带来比单页应用程序 (SPA) 更好的性能。

杭州程序员张张7阅读 4.1k评论 3

208 声望
16 粉丝
宣传栏