zoukankan      html  css  js  c++  java
  • 个人技术博客——vue的响应式布局

    技术描述

    • 这个技术用来干嘛?
      • 响应式布局用于使页面在不同的设备上都能有一个正常的样式显示,支持用户不同显示规格的设备上访问页面且仍有良好体验。
    • 为什么要学这个?
      • 随着移动端的普及,现在的页面最基础也需要达到PC端和手机端的样式能够让人在接受的程度。如果用户手机打开页面整个样式崩溃了,那他也没有理由继续选用你的应用了。
    • 技术难点在哪?
      • 页面的CSS不能再写死了,要使用百分比,或者直接使用flex弹性布局(我自己采用了这种方式)
      • 要多写好多类的样式,搞清楚类的包含关系,这里我推荐可以简单学一下CSS的预处理语言包括.less和.sass,这样写CSS的嵌套关系、参数关系都会更加清楚

    技术详述

    背景以及环境

    • 当前使用方法仅限于vue项目开发时使用(由于vue要求使用webpack所以下面不再赘述)
    • 当前方法是vueCLI4.0版本下使用,vue没有保证完全向前兼容,但是基础的方法应该不会改变。
    • 当前方法写CSS的时候使用了.less的预处理语言,如果查看代码有困难画3-5分钟熟悉一下预处理语言即可看懂。
    • 当前方法使用vuex本地化保存窗口大小,如果你想使用localstorage保存原理是类似的。
    • 当前方法使用了v-bind的绑定样式逻辑编写,如果还有其他实现方法欢迎讨论。

    流程图

    1.基础类的CSS样式

    <div>
        <div :class="personInfoClass">
            <div class="Avatar">
                <el-avatar
                        :size="180"
                        :src="avatarUrl">
                </el-avatar>
            </div>
            
    ……………………
    

    这里只展示一个基础的div。此处将外围DIV的class通过v-bind 动态绑定了一个personInfoClass的类名。此处建议将personInforClass作为computed属性配置,否则每次都重新判断会导致页面效率降低。

    computed:{
      personInfoClass(){
        if(this.windowWidth > 500) {
          return "PersonInfo"
        } else {
          return "mobile_person_info_content"
        }
      },
    }
    

    这里可以看到配置的personInfoClass的类会返回两种情况,一种是在窗口大于500px的时候返回PersonInfo类,一种是在窗口小于500px的时候调用我们移动端的类。那么显然的,在一般情况下都会调用PersonInfo类,所以我们在vue对应组件内使用局部性CSS写好这部分基础类的样式

    <style lang="less" scoped>
        @import "~@/CSS/Common.less";
        .PersonInfo {
            .setSize(925px, 230px);
            padding: 20px 20px;
            background-color: white;
            display: flex;
            justify-content: right;
            .Avatar {
                display: flex;
                flex-direction: column;
                justify-content: center;
            }
            .UserName {
                display: flex;
                font-size: 32px;
            }
        }
    }
    

    这样项目就保证了这个div在窗口>500px的时候使用该类的样式。

    2.编写其他情况的CSS样式

    那么另一个移动端的CSS样式写在哪里呢?

    我们新建一个CSS文件下存放我们的mobile状态的CSS,命名为mobile.less(我这里还有小窗的样式,所以还有smallWIndow.less)

    我们刚才命名的小窗下的类名为mobile_person_info_content,所以我们这里直接写一个对应的类样式

    .mobile_person_info_content {
       calc(100% - 20px);
      margin: 20px auto;
      background-color: white;
      display: flex;
      flex-direction: column;
      justify-content: center;
      .Avatar{
        display: flex;
        justify-content: center;
        flex-direction: row;
      }
      .UserName {
        display: flex;
        justify-content: center;
        flex-direction: row;
        font-size: 32px;
      }
    }
    

    在你的需要引用的地方引入这个.less文件即可,我这里由于整个程序都需要适应配置,所以全局引入在了最顶端的根组件CSS内。当然既然是全局引入,这里不需要加scoped限定范围。

    <style lang="less">
        @import "~@/CSS/mobile.less";
        @import "~@/CSS/smallWindow.less";
        #app {
            font-family: Avenir, Helvetica, Arial, sans-serif;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
            text-align: center;
        }
    }
    

    这样在全局范围内的vue就可以使用我们在这两个文件内写的类样式了。

    3.监控窗口大小

    当我们完成了类的配置之后,我们需要监控窗口大小,让computed属性中的类可以进行切换,来使得div的绑定类切换,进而通过改变类的样式实现不同情况下的样式显示。

    首先在vuex中增加窗口大小的state。(关于vuex的引入和属性的操作不做说明了)

    const state = {
      screenWidth:document.documentElement.clientWidth, //屏幕宽度
      screenHeight:document.documentElement.clientHeight, //屏幕高度
    }
    

    与上面类似的,如果需要局部引入则在对应的组件内使用下述方法即可,如果要全局引入,按部就班就行。

    在最顶层的根组件下使用mounted生命周期函数,用dom原生的window.onresize监听窗口的大小变化。(为什么全局只在根组件引入呢?因为整个程序周期中只允许一个window.onresize监听,此外多余的都是没有反应的,所以如果你在多个组件重复引入window.onresize是没有作用的,只能通过根目录的监听使得整个项目都能监听到窗口大小)

    mounted() {
      let that = this;
      window.onresize=function() {
        that.$store.state.screenWidth = document.documentElement.clientWidth; //窗口宽度
        that.$store.state.screenHeight = document.documentElement.clientHeight; //窗口高度
      }
    }
    

    随后的,就需要监听这个vuex里的窗口大小参数了,在需要的组件内使用watch函数监听参数,比如我这里就是刚才的div组件中。这里的windowWidth已经定义在data中,这里不做演示了

    watch: {
      '$store.state.screenWidth': function (val) { //监听屏幕宽度变化
        this.windowWidth = val;
      }
    },
    

    可能会遇到的问题

    1. 窗口一打开样式不正确

    可能是因为你在data中的windowWidth没有赋初值,需要在窗口建立的时候就让它获得初始的窗口大小数值,否则无法进入判断循环。

    data() {
      return {
        windowWidth:document.documentElement.clientWidth
      }
    }
    
    1. 切换时只有一部分样式切换了,另一部分样式没有切换

    要注意你的样式的嵌套,有可能切换的时候只有被嵌套包含的部分完成了切换,而在嵌套外的没有完成。

    .mobile_person_info_content {
       calc(100% - 20px);
      margin: 20px auto;
      background-color: white;
      display: flex;
      flex-direction: column;
      justify-content: center;
      .Avatar{
        display: flex;
        justify-content: center;
        flex-direction: row;
      }
    }
    .UserName {
        display: flex;
        justify-content: center;
        flex-direction: row;
        font-size: 32px;
      }
    

    比如上文的样式如果写成这样。则.UserName的类的样式是不会改变的,因为优先级的原因,vue会优先使用局部的同名CSS样式。类似的,如果你还有其他的全局.CSS样式,你也需要保证把所有要修改样式的类都嵌套进去。否则全局的样式也会被局部的同名CSS样式覆盖。

    3.样式完全没有改变

    不要用严格的属性比如px来限定窗口,使用百分比属性或者相对属性来进行样式编写。尽量使用flex的弹性布局,它本身就包含相对的布局。如果使用了px来进行限定也不要影响到相对的布局。

    总结

    最终响应式配置的逻辑链就形成了,根组件事实监听窗口大小->将窗口大小保存在本地->组件监听本地的窗口大小数据变化->赋值给组件参数->组件参数变化,进入切换类的判断->根据判断决定返回的类名->通过类名在CSS中找到对应的样式->样式改变。

    参考博客

    怎样能在大小不同的屏幕上显示不同的样式?

    概述:简单介绍了一下如何显示样式的理论知识。

    如何在vue中监听窗口大小?

    概述:实际操作了vue中监听窗口大小的方法,包括了局部引入和全局引入

    vue框架响应式布局

    概述:实现时提供了一个思路,按照v-if或者v-show控制,后续经过思考采取了绑定类的方式进行切换。

  • 相关阅读:
    如何复制图文消息封面图片?正文没显示
    微信企业号已开通账号超过10万 日均消息量超过100万条
    微信服务号模板消息接口新增"设置行业"和"添加模板"及细节优化
    张小龙在微信公开课上的演讲
    做微信营销你知道男女用微信的习惯吗?
    微信时代,"邮"你选择 腾讯企业邮箱推新玩法
    亲身体验,不要再拖! 拖! 拖!
    The Promise of Deep Learning
    判断两个数组是否相等
    matlab学习笔记(一)单元数组
  • 原文地址:https://www.cnblogs.com/pcysoushu/p/13130359.html
Copyright © 2011-2022 走看看