vue前端自适应布局实现教程(一步到位所有自适应)

 更新时间:2024年08月13日 09:47:42   作者:lgx211  
​自适应布局是一种根据不同的设备屏幕分辨率进行布局的方式,它为不同的屏幕分辨率定义了不同的布局,下面这篇文章主要给大家介绍了关于vue前端自适应布局实现的相关资料,需要的朋友可以参考下

页面展示

实现内容

1,左右布局

  • 左侧固定宽带,右侧自适应剩余的宽度。
  • 中间一条分割线,可以拖拉,自适应调整左右侧的宽度。
  • 左侧的高度超长自动出现横向滚动条,左侧宽度超长,自动出现竖向滚动条。

2,上中下布局

  • 最上面的 搜索条件 div 固定占用 100 px 高度,下面的 查询条件 div 固定占用 30 px 高度,最下面的分页固定占用高度,页面剩下的高度自动分配给中间的表格内容。
  • 表格内容高度超过后自动出现竖向滚动条,宽度超出后自动出现横向滚动条。
  • 点击按钮,可以 隐藏/显示 搜索条件 div 里面的内容。
  • 当隐藏 搜索条件 div 里面的内容时,中间表格的高度为:整个页面的高度—操作按钮div的高度—分页div的高度。
  • 当搜索条件 div 里面的内容时,中间表格的高度为:整个页面的高度—搜索条件div的高度—操作按钮div的高度—分页div的高度。
    2,分辨率自适应
  • 加载即动态实时计算高度,宽度

实现代码

vue2 语法实现

<template>
  <div class="app-container">
    <div class="left" :style="{ width: leftWidth + 'px' }">
      <div class="right-center-left">
        左边的内容,可以很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
      </div>
    </div>
    <div class="divider" @mousedown="startDragging"></div>
    <div class="right">
      <div v-if="showDiv1" class="div1">查询条件</div>
      <div class="div2">
        <button @click="toggleDiv1">操作按钮 div1</button>
      </div>
      <div class="div3" :style="{ height: div3Height + 'px' }">
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
      </div>
      <div class="div4">分页</div>
    </div>
  </div>
</template>

<script>
export default {
  name: "AppContainer",
  data() {
    return {
      isDragging: false,
      leftWidth: 200,
      showDiv1: true
    };
  },
  computed: {
    div3Height() {
      const totalHeight = window.innerHeight;
      const div2Height = 30;
      const div4Height = 30;
      const div1Height = this.showDiv1 ? 100 : 0;

      // 计算 div3 的高度
      return totalHeight - div2Height - div4Height - div1Height;
    }
  },
  methods: {
    startDragging(e) {
      this.isDragging = true;
      document.addEventListener("mousemove", this.onDrag);
      document.addEventListener("mouseup", this.stopDragging);
    },
    onDrag(e) {
      if (this.isDragging) {
        const minWidth = 50;
        const maxWidth = window.innerWidth - 50;
        const newLeftWidth = e.clientX;

        if (newLeftWidth > minWidth && newLeftWidth < maxWidth) {
          this.leftWidth = newLeftWidth;
        }
      }
    },
    stopDragging() {
      this.isDragging = false;
      document.removeEventListener("mousemove", this.onDrag);
      document.removeEventListener("mouseup", this.stopDragging);
    },
    toggleDiv1() {
      this.showDiv1 = !this.showDiv1;
    }
  }
};
</script>

<style scoped>
.app-container {
  display: flex;
  height: 100vh;
  overflow: hidden;
}

.left {
  overflow-x: auto;
  overflow-y: auto;
  white-space: nowrap;
  min-width: 90px;
}

.divider {
  width: 5px;
  cursor: ew-resize;
  background-color: #ccc;
}

.right {
  display: flex;
  flex-direction: column;
  height: 100%;
  flex: 1; /* 自动填满剩余宽度 */
}

.div1 {
  height: 100px;
  background-color: #f0f0f0;
}

.div2 {
  height: 30px;
  background-color: #ddd;
}

.div3 {
  overflow-x: auto; /* 添加横向滚动条 */
  overflow-y: auto; /* 添加纵向滚动条 */
  background-color: #f5f5f5;
}

.div4 {
  height: 200px;
  background-color: #ccc;
}
</style>

vue3 语法实现

<template>
  <div class="app-container">
    <div class="left" :style="{ width: leftWidth + 'px' }">
      左边的内容,可以很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长<br />
      1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
      1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
      1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
      1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
      1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
      1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
    </div>
    <div class="divider" @mousedown="startDragging"></div>
    <div class="right">
      <div v-if="showQueryDiv" class="right-query">搜索条件</div>
      <div class="right-button">
        <div class="right-button-left">操作按钮</div>
        <div class="right-button-right">
          <button @click="toggleQueryDiv">隐藏/展示 搜索条件</button>
        </div>
      </div>
      <div class="right-table" :style="{ height: tableHeight + 'px' }">
        表格内容<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
        1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
      </div>
      <div class="right-page">分页内容</div>
    </div>
  </div>
</template>

<script>
import { ref, computed, onMounted, onUnmounted } from 'vue';

export default {
  name: "AppContainer",
  setup() {
    const isDragging = ref(false);
    const leftWidth = ref(200);
    const showQueryDiv = ref(true);

    const tableHeight = computed(() => {
      const totalHeight = window.innerHeight;
      const buttonHeight = 30;
      const pageHeight = 30;
      const queryHeight = showQueryDiv.value ? 100 : 0;
      return totalHeight - buttonHeight - pageHeight - queryHeight;
    });

    const startDragging = (e) => {
      isDragging.value = true;
      document.addEventListener("mousemove", onDrag);
      document.addEventListener("mouseup", stopDragging);
    };

    const onDrag = (e) => {
      if (isDragging.value) {
        const minWidth = 50;
        const maxWidth = window.innerWidth - 50;
        const newLeftWidth = e.clientX;
        if (newLeftWidth > minWidth && newLeftWidth < maxWidth) {
          leftWidth.value = newLeftWidth;
        }
      }
    };

    const stopDragging = () => {
      isDragging.value = false;
      document.removeEventListener("mousemove", onDrag);
      document.removeEventListener("mouseup", stopDragging);
    };

    const toggleQueryDiv = () => {
      showQueryDiv.value = !showQueryDiv.value;
    };

    onMounted(() => {
      window.addEventListener("resize", onDrag);
    });

    onUnmounted(() => {
      window.removeEventListener("resize", onDrag);
    });

    return {
      leftWidth,
      showQueryDiv,
      tableHeight,
      startDragging,
      toggleQueryDiv
    };
  }
};
</script>

<style scoped>
.app-container {
  display: flex;
  height: 100vh;
  overflow: hidden;
}

.left {
  overflow-x: auto;
  overflow-y: auto;
  white-space: nowrap;
  min-width: 90px;
}

.divider {
  width: 5px;
  cursor: ew-resize;
  background-color: #ccc;
}

.right {
  display: flex;
  flex-direction: column;
  height: 100%;
  flex: 1; /* 自动填满剩余宽度 */
}

.right-query {
  height: 100px;
  background-color: #f0f0f0;
}

.right-button {
  height: 30px;
  display: flex;
  justify-content: space-between; /* 左右对齐内容 */
  align-items: center; /* 垂直居中对齐 */
  background-color: #ddd;
}

.right-button-left {
  margin-left: 5px;
  text-align: left;
}

.right-button-right {
  margin-right: 5px;
  text-align: right;
}

.right-table {
  overflow-x: auto; /* 添加横向滚动条 */
  overflow-y: auto; /* 添加纵向滚动条 */
  background-color: #f5f5f5;
}

.right-page {
  height: 200px;
  background-color: #ccc;
}
</style>

实现感想

这个功能,从毕业就开始思索,直到八年后的今天成熟完善,真是艰辛也是很不容易。目前市面上没有见过有人实现,很多人都是只言片语的,基本复制下来,无法达到效果。我这个一键复制到自己的项目,就能实现了,中间的坎坷不平,到了完全实现的这一刻,才觉得激动不已。

无任何坑,也没有任何额外的引入,一个普普通通,最简单的vue页面,布局建好,里面的内容就可以自己随意发挥了。

总结

到此这篇关于vue前端自适应布局实现的文章就介绍到这了,更多相关vue前端自适应布局内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue使用国密SM4进行加密、解密的过程

    vue使用国密SM4进行加密、解密的过程

    国密SM4算法是一种对称加密算法,适用于对称密钥加密和解密的场景,这篇文章主要介绍了vue使用国密SM4进行加密、解密,需要的朋友可以参考下
    2023-07-07
  • element-plus/element-ui走马灯配置图片及图片自适应的最简便方法

    element-plus/element-ui走马灯配置图片及图片自适应的最简便方法

    走马灯功能在展示图片时经常用到,下面这篇文章主要给大家介绍了关于element-plus/element-ui走马灯配置图片及图片自适应的最简便方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • Vue解决element-ui消息提示$message重叠问题

    Vue解决element-ui消息提示$message重叠问题

    这篇文章主要为大家介绍了Vue解决element-ui消息提示$message重叠问题,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • Vue3项目实现前端导出Excel的示例代码

    Vue3项目实现前端导出Excel的示例代码

    这篇文章主要介绍了Vue3项目实现前端导出Excel的示例,在vue3的项目中导出Excel表格的功能,可以借助xlsx库来实现,下面是详细的操作步骤,需要的朋友可以参考下
    2025-01-01
  • 详解关于Vue2.0路由开启keep-alive时需要注意的地方

    详解关于Vue2.0路由开启keep-alive时需要注意的地方

    这篇文章主要介绍了关于Vue2.0路由开启keep-alive时需要注意的地方,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • 浅谈Vue的响应式原理

    浅谈Vue的响应式原理

    让我们来回顾下Vue的介绍,可以发现Vue 最显著的一个功能是响应系统。那么它的实现原理有又是如何呢?下面小编和大家来一起学习一下
    2019-05-05
  • 关于Vue组件库开发详析

    关于Vue组件库开发详析

    这篇文章主要给大家介绍了关于Vue组件库开发的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用vue具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07
  • Vue.js仿Metronic高级表格(一)静态设计

    Vue.js仿Metronic高级表格(一)静态设计

    这篇文章主要为大家详细介绍了Vue.js仿Metronic高级表格的静态设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • vue + element-ui的分页问题实现

    vue + element-ui的分页问题实现

    这篇文章主要介绍了vue + element-ui的分页问题实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • vue中给el-radio添加tooltip并实现点击跳转方式

    vue中给el-radio添加tooltip并实现点击跳转方式

    这篇文章主要介绍了vue中给el-radio添加tooltip并实现点击跳转方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04

最新评论