vue组件封装——固定宽高比的容器(2种方法:纯CSS实现 + JS实现)

简介: vue组件封装——固定宽高比的容器(2种方法:纯CSS实现 + JS实现)

什么是固定宽高比容器?

定义:

无论浏览器窗口或页面元素如何变化,容器的宽度和高度永远保持固定的比例,如16:9。

应用场景:

如大屏自适应,内部元素对容器宽高比依赖很高的复杂模块布局等。

纯CSS实现固定宽高比的容器

原理

  • padding-top的值为百分比时,最终padding-top的计算值 = 百分比 * 当前元素宽度的计算值,从而通过padding-top将容器撑开。
  • 为容器添加样式 box-sizing: border-box; 则容器的高度 = padding-top的计算值,从而实现容器高度根据容器的宽度按百分比自适应变化。
  • 使用“子绝父相”,让容器中的内容完全覆盖容器。

cssRatioContainer.vue

<template>
  <div class="box" :style="ratioStyle">
    <div class="content" :style="contentStyle">
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    ratio: {
      type: Number,
      default: 1,
    },
    overflow: {
      type: String,
      default: "auto",
    },
    overflowX: {
      type: String,
    },
    overflowY: {
      type: String,
    },
  },
  computed: {
    ratioStyle() {
      let ratio = (1 / this.ratio) * 100;
      if (ratio == null || Number.isNaN(ratio)) {
        ratio = 100;
      }
      if (typeof ratio !== "string" || !ratio.endsWith("%")) {
        ratio = ratio + "%";
      }
      return `padding-top: ${ratio};`;
    },

    contentStyle() {
      const styles = [];
      if (this.overflow) {
        styles.push("overflow:" + this.overflow);
      }
      if (this.overflowX) {
        styles.push("overflow-x:" + this.overflowX);
      }
      if (this.overflowY) {
        styles.push("overflow-y:" + this.overflowY);
      }
      return styles.join(";");
    },
  },
};
</script>

<style scoped>
.box {
  position: relative;
  box-sizing: border-box;
}
.content {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
</style>

JS实现固定宽高比的容器

原理

  • 通过js获取容器的宽度计算值后,按宽高比计算出容器的高度,并赋值给容器。

jsRatioContainer.vue

<template>
  <div id="jsRatioContainerBox" class="box" :style="contentStyle">
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: {
    ratio: {
      type: Number,
      default: 1,
    },
    overflow: {
      type: String,
      default: "auto",
    },
    overflowX: {
      type: String,
    },
    overflowY: {
      type: String,
    },
  },
  data() {
    return {
      myHeight: "",
    };
  },
  computed: {
    contentStyle() {
      const styles = [];
      if (this.myHeight) {
        styles.push("height:" + this.myHeight);
      }
      if (this.overflow) {
        styles.push("overflow:" + this.overflow);
      }
      if (this.overflowX) {
        styles.push("overflow-x:" + this.overflowX);
      }
      if (this.overflowY) {
        styles.push("overflow-y:" + this.overflowY);
      }
      return styles.join(";");
    },
  },
  mounted() {
    this.setHeight();
    window.addEventListener("resize", () => {
      this.setHeight();
    });
  },
  watch: {
    ratio() {
      this.setHeight();
    },
  },
  methods: {
    // 根据宽高比和当前宽度,设置最终的高度
    setHeight() {
      this.$nextTick(() => {
        let myDom = document.getElementById("jsRatioContainerBox");
        let width = window.getComputedStyle(myDom)["width"];
        this.myHeight =
          Number(width.replace("px", "")) * (1 / this.ratio) + "px";
      });
    },
  },
};
</script>

<style scoped>
.box {
  width: 100%;
}
</style>

使用范例

<template>
  <div class="father">
    <h2>CSS实现固定宽高比的容器</h2>
    <CssRatioContainer
      ref="CssRatioContainer"
      id="CssRatioContainer"
      :ratio="ratioWidth / ratioHeight"
    >
      <div class="itemBox" v-for="item in 100" :key="item">段落{{ item }}</div>
    </CssRatioContainer>
    <p>容器的宽度为:{{ mySize.width }}</p>
    <p>容器的高度为:{{ mySize.height }}</p>
    <label>容器的宽高比:</label>
    <input
      class="inputStyle"
      type="number"
      v-model="ratioWidth"
      @input="getSize"
    />
    <input
      class="inputStyle"
      type="number"
      v-model="ratioHeight"
      @input="getSize"
    />
    <h2>JS实现固定宽高比的容器</h2>
    <JsRatioContainer :ratio="ratioWidth / ratioHeight">
      <div class="itemBox" v-for="item in 100" :key="item">段落{{ item }}</div>
    </JsRatioContainer>
  </div>
</template>
<script>
import CssRatioContainer from "./cssRatioContainer.vue";
import JsRatioContainer from "./jsRatioContainer.vue";
export default {
  components: { CssRatioContainer, JsRatioContainer },
  mounted() {
    this.getSize();
    window.addEventListener("resize", () => {
      this.getSize();
    });
  },
  methods: {
    getSize() {
      this.$nextTick(() => {
        let myDom = document.getElementById("CssRatioContainer");
        let myComputedStyle = window.getComputedStyle(myDom);
        this.$set(this.mySize, "height", myComputedStyle.height);
        this.$set(this.mySize, "width", myComputedStyle.width);
      });
    },
  },

  data() {
    return {
      mySize: {},
      ratioWidth: 6,
      ratioHeight: 1,
    };
  },
};
</script>
<style scoped>
.father {
  max-width: 1200px;
  margin: 20px;
}
.itemBox {
  background: red;
  border: 1px solid yellow;
}
.inputStyle {
  width: 60px;
  text-align: center;
}
</style>

目录
相关文章
|
1月前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
|
1月前
|
监控 JavaScript Java
Node.js中内存泄漏的检测方法
检测内存泄漏需要综合运用多种方法,并结合实际的应用场景和代码特点进行分析。及时发现和解决内存泄漏问题,可以提高应用的稳定性和性能,避免潜在的风险和故障。同时,不断学习和掌握内存管理的知识,也是有效预防内存泄漏的重要途径。
128 52
|
16天前
纸屑飘落生日蛋糕场景js+css3动画特效
纸屑飘落生日蛋糕CSS3动画特效是一款js+css3制作的全屏纸屑飘落,生日蛋糕点亮庆祝动画特效。
33 3
|
1月前
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
45 5
|
1月前
|
JavaScript 前端开发
js中的bind,call,apply方法的区别以及用法
JavaScript中,`bind`、`call`和`apply`均可改变函数的`this`指向并传递参数。其中,`bind`返回一个新函数,不立即执行;`call`和`apply`则立即执行,且`apply`的参数以数组形式传递。三者在改变`this`指向及传参上功能相似,但在执行时机和参数传递方式上有所区别。
27 1
|
1月前
|
缓存 前端开发 JavaScript
优化CSS和JavaScript加载
优化CSS和JavaScript加载
|
1月前
|
缓存 前端开发 JavaScript
优化CSS和JavaScript加载
Next.js和Nuxt.js在优化CSS和JavaScript加载方面提供了多种策略和工具。Next.js通过代码拆分、图片优化和特定的CSS/JavaScript优化措施提升性能;Nuxt.js则通过代码分割、懒加载、预渲染静态页面、Webpack配置和服务端缓存来实现优化。两者均能有效提高应用性能。
|
1月前
|
前端开发 JavaScript
用HTML CSS JS打造企业级官网 —— 源码直接可用
必看!用HTML+CSS+JS打造企业级官网-源码直接可用,文章代码仅用于学习,禁止用于商业
135 1
|
1月前
|
JavaScript 前端开发
.js方法参数argument
【10月更文挑战第26天】`arguments` 对象为JavaScript函数提供了一种灵活处理参数的方式,能够满足各种不同的参数传递和处理需求,在实际开发中具有广泛的应用价值。
44 7
|
1月前
|
前端开发 JavaScript 安全
HTML+CSS+JS密码灯登录表单
通过结合使用HTML、CSS和JavaScript,我们创建了一个带有密码强度指示器的登录表单。这不仅提高了用户体验,还帮助用户创建更安全的密码。希望本文的详细介绍和代码示例能帮助您在实际项目中实现类似功能,提升网站的安全性和用户友好性。
48 3