数据大屏适配方案 (vw vh、rem、scale)
转自
https://juejin.cn/post/7163932925955112996
# 前言
最近在公司开发了一个可视化大屏,开发定制化大屏,大家可能都一个感受,开发大屏主要是两方面的工作:
大屏之关键-前期的自适应适配
根据 ui 稿绘制图表,调细节
而解决了适配问题后,后面就只是一个慢工出细活,耗时间的事情了。
# 适配方案分析
看了网上的各种方案,目前大家采用的大概有 3 种👇
方案 | 实现方式 | 优点 | 缺点 |
---|---|---|---|
vm vh | 1. 按照设计稿的尺寸,将 px 按比例计算转为 vw 和 vh | 1. 可以动态计算图表的宽高,字体等,灵活性较高 2. 当屏幕比例跟 ui 稿不一致时,不会出现两边留白情况 | 1. 每个图表都需要单独做字体、间距、位移的适配,比较麻烦 |
scale | 1. 通过 scale 属性,根据屏幕大小,对图表进行整体的等比缩放 | 1. 代码量少,适配简单 2. 一次处理后不需要在各个图表中再去单独适配 | 1. 因为是根据 ui 稿等比缩放,当大屏跟 ui 稿的比例不一样时,会出现周边留白情况 2. 当缩放比例过大时候,字体会有一点点模糊,就一点点 3. 当缩放比例过大时候,事件热区会偏移。 |
rem + vm vh | 1. 获得 rem 的基准值 2. 动态的计算 html根元素的font-size 3. 图表中通过 vm vh 动态计算字体、间距、位移等 | 1. 布局的自适应代码量少,适配简单 | 1. 因为是根据 ui 稿等比缩放,当大屏跟 ui 稿的比例不一样时,会出现周边留白情况 2. 图表需要单个做字体、间距、位移的适配 |
前端服务端渲染和客户端渲染
# 文章目录
- 序言
- 服务端渲染的优点和缺点
- 客户端渲染的优点和缺点
- 服务端渲染是产生并发吗
- 服务端渲染用户每次请求都需要重新渲染吗
- 为什么服务端渲染只做首屏?
- 什么情况下,可能需要进行更多的服务端渲染或客户端渲染
- 前端渲染和前后端分离是不是一回事呢?
- 服务端渲染模板,前端如何热更新?
- 前后端分离,前端渲染每个页面都要去请求后端用户现在的登录状态是否有效吗?
- 客户端渲染和服务端渲染,单页面应用和多页面应用,前端路由和服务端路由有什么区别联系?
JavaScript 中的 Reflect
# reflect 的 13 个方法
方法 | 参数说明 |
---|---|
Reflect.get(target, name, receiver) | target: 目标对象。 |
name: 是我们要读取的属性。 | |
receiver (可选): 可以理解为上下文 this 对象。 | |
Reflect.set(target,name,value,receiver) | target: 我们需要操作的对象。 |
name: 我们需要设置该对象的属性名。 | |
value: 我们要设置的属性值。 | |
receiver: 可以理解为上下文 this 对象。如果我们在设置值的时候遇到 setter 函数,该参数就指向与 setter 中上下文 this 对象。 | |
Reflect.apply(target,thisArg,args) | target: 我们的目标函数。 |
thisArg: target 函数调用的时候绑定的 this 对象。 | |
args: 就是函数参数列表。 | |
Reflect.construct(target,args[, newTarget]) | target: 被运行的目标函数。 |
args: 调用构造函数传递的参数数组或伪数组。 | |
newTarget: 也是构造函数,表示使用 Reflect.construct 后生成的实列对象是谁的实列。如果没有该参数,默认生成的实列对象就和 target 构造函数是一样的。 | |
Reflect.defineProperty(target,name,desc) | 该方法 Object.defineProperty 方法类似的,不过唯一的区别是 Reflect.defineProperty 返回值是一个 Boolean 的值。 |
Reflect.deleteProperty(target,name) | target: 表示要操作的对象。 |
name: 表示要删除该对象上的属性。 | |
Reflect.has(target,name) | target: 就是改对象。 |
name 的含义是:该对象上的属性。 | |
Reflect.ownKeys(target) | target:它是一个对象。 |
Reflect.preventExtensions(target) | target:必须是一个对象,否则的话会抛出一个异常。 |
Reflect.isExtensible(target) | target:表示目标对象。 |
Reflect.getOwnPropertyDescriptor(target, name) | target: 表示的是目标对象。 |
name: 表示目标对象的属性 该方法的具体含义是:如果目标对象中的属性描述符存在的话,就返回这个属性描述符,如果不存在,就返回 undefined。 | |
Reflect.getPrototypeOf(target) | 该方法是返回一个对象的原型的,也就是说内部的 [[Prototype]] 属性的值。 |
Reflect.setPrototypeOf(target, prototype) | 方法的作用是设置一个对象的原型。如果设置成功的话,这个对象就返回一个 true,如果设置失败的话,这个对象就返回一个 false。 |
详解箭头函数和普通函数的区别
# 前言
今天在写代码时,用了箭头函数,出现了如下问题:
function Drawing(shape) { | |
this.shape = shape | |
} | |
Drawing.prototype.drawShape = (radius, x, y) => { //bug 问题所在 | |
return this.shape.draw(radius, x, y) //this 指向了全局 | |
} |
报错信息:
Error in created hook: "TypeError: Cannot read properties of undefined (reading 'shape')"
然后,改成 function
后,错误消除。
function Drawing(shape) { | |
this.shape = shape | |
} | |
Drawing.prototype.drawShape = function(radius, x, y) { | |
return this.shape.draw(radius, x, y) | |
} |
原因是 this 指向问题,这是因为不了解箭头函数属性导致的。
- 箭头函数没有单独的
this
、arguments
、super
,并且不能作为构造函数。
JS中的Proxy代理详解
# 前言
就目前而言,前端框架基本上被 Vue 和 React 瓜分得差不多了。如果你去面试一个前端岗位,那么或多或少都会问你一些关于 Vue 和 React 框架得知识,无论是原理还是使用,我们都有必要去了解一番。
数据响应式可以说是这些框架的一大特色与核心,这里我们就拿 Vue 来说。在 Vue2.x 时代,实现数据响应式主要是使用
Object.defineProperty()
这个 API 来实现的,而到了 Vue3.x 时代,数据响应式主要是使用Proxy()
来实现的。如果你还不了解 Proxy,那么你很有必要跟着本篇文章学习一下!
js中 new 的class对象是在dom之前还是之后
在 JavaScript 中,使用 new
关键字来创建类的实例时,这个过程本身与时序(即在 DOM 加载之前还是之后)关系不大,而是更多地与 JavaScript 代码的执行顺序有关。然而,当你想要在创建类的实例之后进行 DOM 操作时,你需要确保 DOM 元素已经被加载和解析。
JS如何判断滚动条是否滚到底部
首先说一下常识:
网页可见区域宽: document.body.clientWidth; | |
网页可见区域高: document.body.clientHeight; | |
网页可见区域宽: document.body.offsetWidth (包括边线的宽); | |
网页可见区域高: document.body.offsetHeight (包括边线的宽); | |
网页正文全文宽: document.body.scrollWidth; | |
网页正文全文高: document.body.scrollHeight; | |
网页被卷去的高: document.body.scrollTop; | |
网页被卷去的左: document.body.scrollLeft; | |
网页正文部分上: window.screenTop; | |
网页正文部分左: window.screenLeft; | |
屏幕分辨率的高: window.screen.height; | |
屏幕分辨率的宽: window.screen.width; | |
屏幕可用工作区高度: window.screen.availHeight; | |
屏幕可用工作区宽度:window.screen.availWidth; |
JavaScript对象继承的几种方式
# 1. 以复制方式实现的继承
# 1.1 浅拷贝
基本类型的复制
var parent = { | |
lanage: "chinese" | |
} | |
var child = { | |
name: "xxx", | |
age: 12 | |
} | |
function extend(parent, child) { | |
var child = child || {}; | |
for (const propertype in parent) { | |
child[propertype] = parent[propertype]; | |
} | |
} | |
extend(parent, child); | |
console.log(child);//{ name: 'xxx', age: 12, lanage: 'chinese' } |
以上代码中,通过一个 extend () 函数,将父对象 parent 的属性遍历赋给子对象 child,从而实现继承。
但是这种字面量复制的方式存在巨大的缺陷,当父对象有引用类型的属性时,通过这么复制的方式,就像上一节中的 var b = a 一样,只会将 a 对象的引用赋给 b 对象,结果两者是指向同一个对象内存的,继承出来的子对象的属性是同一个,显然是不能满足需求的,(基本类型之间画等号是值的复制,引用类型之间画等号是引用的复制)所以就需要另谋出路。
JavaScript 中的 prototype
# [[Prototype]] 与 prototype
[[Prototype]] 与 prototype 是不同的:
# 凡是被两层方括号括起来的属性都是内部属性,内部属性不能通过 “对象。属性” 的方式获取。
[[Prototype]] 就是内部属性,它不能通过 “对象.[[Prototype]]” 的方式获取,但可以通过 “对象.proto” 的方式获取。
prototype 是一般属性,可以直接通过 “对象.prototype” 的方式获取。