从0到1搭建一款页面自适应组件(Vue.js)
前端历劫之路
共 6867字,需浏览 14分钟
· 2021-02-20
组件将根据屏幕比例及当前浏览器窗口大小,自动进行缩放处理。
建议在组件内使用百分比搭配flex进行布局,以便于在不同的分辨率下得到较为一致的展示效果。
使用前请注意将body的margin设为0,否则会引起计算误差。
fullScreenContainer.vue
<template>
<div id="full-screen-container" :ref="ref">
<template v-if="ready">
<slot>slot>
template>
div>
template>
<script>
import autoResize from './autoResize.js'
export default {
name: 'DvFullScreenContainer',
mixins: [autoResize],
data () {
return {
ref: 'full-screen-container',
allWidth: 0,
scale: 0,
datavRoot: '',
ready: false
}
},
methods: {
afterAutoResizeMixinInit () {
const { initConfig, setAppScale } = this
initConfig()
setAppScale()
this.ready = true
},
initConfig () {
const { dom } = this
const { width, height } = screen
this.allWidth = width
dom.style.width = `${width}px`
dom.style.height = `${height}px`
},
setAppScale () {
const { allWidth, dom } = this
const currentWidth = document.body.clientWidth
dom.style.transform = `scale(${currentWidth / allWidth})`
},
onResize () {
const { setAppScale } = this
setAppScale()
}
}
}
script>
<style lang="scss">
#full-screen-container {
position: fixed;
top: 0px;
left: 0px;
overflow: hidden;
transform-origin: left top;
z-index: 999;
}
style>
autoResize.js
export default {
data() {
return {
dom: '',
width: 0,
height: 0,
debounceInitWHFun: '',
domObserver: ''
};
},
methods: {
debounce(delay, callback) {
let lastTime;
return function() {
clearTimeout(lastTime);
const [that, args] = [this, arguments];
lastTime = setTimeout(() => {
callback.apply(that, args);
}, delay);
};
},
observerDomResize(dom, callback) {
const MutationObserver =
window.MutationObserver ||
window.WebKitMutationObserver ||
window.MozMutationObserver;
const observer = new MutationObserver(callback);
observer.observe(dom, {
attributes: true,
attributeFilter: ['style'],
attributeOldValue: true
});
return observer;
},
async autoResizeMixinInit() {
const {
initWH,
getDebounceInitWHFun,
bindDomResizeCallback,
afterAutoResizeMixinInit
} = this;
await initWH(false);
getDebounceInitWHFun();
bindDomResizeCallback();
if (typeof afterAutoResizeMixinInit === 'function')
afterAutoResizeMixinInit();
},
initWH(resize = true) {
const { $nextTick, $refs, ref, onResize } = this;
return new Promise(resolve => {
$nextTick(() => {
const dom = (this.dom = $refs[ref]);
this.width = dom ? dom.clientWidth : 0;
this.height = dom ? dom.clientHeight : 0;
if (!dom) {
console.warn(
'DataV: Failed to get dom node, component rendering may be abnormal!'
);
} else if (!this.width || !this.height) {
console.warn(
'DataV: Component width or height is 0px, rendering abnormality may occur!'
);
}
if (typeof onResize === 'function' && resize) onResize();
resolve();
});
});
},
getDebounceInitWHFun() {
const { initWH } = this;
this.debounceInitWHFun = this.debounce(100, initWH);
},
bindDomResizeCallback() {
const { dom, debounceInitWHFun } = this;
this.domObserver = this.observerDomResize(dom, debounceInitWHFun);
window.addEventListener('resize', debounceInitWHFun);
},
unbindDomResizeCallback() {
let { domObserver, debounceInitWHFun } = this;
if (!domObserver) return;
domObserver.disconnect();
domObserver.takeRecords();
domObserver = null;
window.removeEventListener('resize', debounceInitWHFun);
}
},
mounted() {
const { autoResizeMixinInit } = this;
autoResizeMixinInit();
},
beforeDestroy() {
const { unbindDomResizeCallback } = this;
unbindDomResizeCallback();
}
};
这样,一个页面自适应组件就这样搭建完成了,下面,我们将引入组件看一下效果。
<template>
<div id="app">
<fullScreenContainer>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js App" />
fullScreenContainer>
div>
template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
import fullScreenContainer from "./components/fullScreenContainer/fullScreenContainer.vue";
export default {
name: "App",
components: {
HelloWorld,
fullScreenContainer,
},
};
script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
style>
效果很好,这样对于一些开发自适应页面非常容易。
欢迎关注我的公众号 前端历劫之路
回复关键词 电子书
,即可获取12本前端热门电子书。回复关键词 红宝书第4版
,即可获取最新《JavaScript高级程序设计》(第四版)电子书。我创建了一个技术交流、文章分享群,群里有很多大厂的前端大佬,关注公众号后,点击下方菜单了解更多即可加我微信,期待你的加入。
评论
搭建完美的技术写作环境,第1-10章
大家好,我是章北海,《机器学习算法与 Python 实战》和《玩机器学习的章北海》号主,985 统计学硕士,5 年时间撰写了 460 余篇优质原创文章,内容涵盖统计学、数据分析、机器学习、深度学习、Python 实战。毕业之后先后从事数据分析、机器学习工程师、项目管理,这些年积累了很多经验,工作之外
机器学习算法与Python实战
0
OpenAI的Sora竟然造假:生成的AI大片只有1%的AI,剩下的99%是人工!
点蓝色字关注“机器学习算法工程师”设为星标,干货直达!啊?Sora火爆短片《气球人》,也“造假”了???背后艺术家团队的最新揭秘,可谓一石激起千层浪:原来,视频画面并非完全由AI生成,其中有大量视觉效果需要人类后期实现。be like:这下网友不干了,合着大家伙儿跟OpenAI玩真心,OpenAI背
机器学习算法工程师
1
从原理到实践:掌握DPDK内存池技术
前言:本文整理下之前的学习笔记,基于DPDK17.11版本源码分析。主要分析一下内存管理部分代码。一、概述内存管理是数据面开发套件(DPDK)的一个核心部分,以此为基础,DPDK的其他部分和用户应用得以发挥其最佳性能。本系列文章将详细介绍DPDK提供的各种内存管理的功能。但在此之前,有必要先谈一谈为
开源Linux
0
教你基于 Jenkins 搭建一套 CI/CD 系统
原文链接:https://mp.weixin.qq.com/s/KVc4IFky1z7kZn-7bz79DQ一、CI/CD环境介绍本次要实现如下效果,开发人员完成功能开发并提交代码到gitlab仓库,jenkins自动完成拉取代码、编译构建、代码扫描(sonarqube)、打
码农编程进阶笔记
0
强烈推荐一款好用到爆的可视化拖拽库
大厂技术 高级前端 Node进阶点击上方 程序员成长指北,关注公众号回复1,加入高级Node交流群今天给大家推荐这款拖拽组件VueDraggablePlus,试了一下非常不错,据说还被尤雨溪推荐过,咱们国人自己开发的,中国人不骗🇨🇳人,我就再来推
程序员成长指北
2
了解加密货币到加密货币的互换
1、什么是加密货币互换?加密货币到加密货币的互换是指以现行市场汇率将一种加密货币直接兑换为另一种加密货币。与需要法定货币存款和较长流程的传统交易所不同,加密货币到加密货币的互换可以无缝地促进交换。掉期在提高加密货币的流动性和效率方面发挥着重要作用。该功能使用户能够将他们的加密货币与钱包中的其他代币进
区块链头条
0
阿里P6,年薪50W+,女朋友父母死活不同意,去年上岸公务员,月薪4k,不料她爸妈却主动邀请到家里吃饭,特别热情主动
上一篇:人到中年, 发现同学间差距了,学医的高薪且稳定,进国企的工资不高但稳定,考公的工资不高,却生活滋润在任何时代,与国家有关的总是受到青睐。如果能够担任公职,那么在社会上就会受到极高的尊敬。近年来,"成为体制内的一员"已经逐渐成为许多年轻人的职业追求。无论是公务员、事业单位员工还是教师,他们不再
开发者全社区
0
面试官:在原生input上面使用v-model和组件上面使用有什么区别?
前言面试官:vue3的v-model都用过吧,来讲讲。粉丝:v-model其实就是一个语法糖,在编译时v-model会被编译成:modelValue属性和@update:modelValue事件。一般在子组件中定义一个名为modelValue的props来接收父组件v-model传递的值,然后当子组
高级前端进阶
0