Hello World - 2024年6月
type: channel
link: https://blog.xunbaidu.com/2024/06/
description: ----------------------------------------------------------------------------------------
items: 202406近期问题汇总
items: 前端性能指标学习
items: 第3章-优先级和层叠

202406近期问题汇总
type: item
date: 2024-06-23T20:36:16+08:00
description: 1.边框重叠问题如图，两个input框纵向紧密排列，相邻的边框靠在一起但没有重叠，视觉效果就是边框不对称，中间的边框看起来很粗，很奇怪。如果直接隐藏上面input的下边框或者下面input的上边框虽然默认状态下是可以解决问题的，但当input框处于:hover状态时，边框会高亮，隐藏边框的地方高亮就会缺失，看起来更奇怪了。为了避免“露馅”，一个很巧妙的方法是通过设置box-shadow来模拟边框的样式。input { border-top: 0; &:hover, &:focus { box-shadow: 0 -1px 0 0 #0364ff; } }实现效果如下图：2.vue文件引入外部css文件的作用域问题vue文件中的script标签以及style标签都可引入外部css文件： 如上代码，import方式导入的话默认是全局引入的，如果只想组件在内部生效可以使用CSS Modules，使用起来比较麻烦。style标签默认也是全局引入的，如果只想组件在内部生效可以添加scoped关键字，相对import的方式更加方便。3.el-table横线问题使用el-table组件并且开启固定列时，固定列地步可能会出现多一条异常横线的问题，可通过调用表格组件的doLayout方法或者添加以下样式解决： 4.el-table滚动条位置重置（丢失）问题如上图的场景，在一个抽屉中会显示多个“子页面”，包括列表页、编辑页、查看页。默认显示列表页，通过v-show控制显示不同页面。列表页中使用了el-table组件显示一个数据列表，当表格中数据较多时，会显示竖向滚动条，此时如果点击显示其他页面然后再切回列表页时，el-table组件会重新渲染，滚动条位置会重置到顶部，原有位置丢失。一个解决方法是，在切换其他页面前获取当前滚动条位置，然后切换回列表页时再恢复滚动条位置： // 获取滚动条位置 public getListScrollHeight() { let bodyWrapper = table.querySelector('.el-table__body-wrapper') this.saveListScrollHeight = bodyWrapper ? bodyWrapper.scrollTop || 0 } // 恢复滚动条位置 public recoverListScrollHeight() { table.doLayout() let bodyWrapper = table.$el.querySelector('.el-table__body-wrapper') if (bodyWrapper) { this.$nextTick(() => { bodyWrapper.scrollTop = this.saveListScrollHeight }) table.doLayout() } }另外需注意对于表格数据tableData，如果直接赋值新的数组数据或动态添加/删除数据，滚动条位置都不会丢失，但如果先赋空数组[]，再赋值新数据，滚动条位置也会丢失。5.js中的事件传播js中事件传播分为3个阶段捕获阶段（Capture Phase）：事件从Window对象向下传递到目标元素（触发事件的元素）目标阶段（Target Phase）：事件到达目标元素冒泡阶段（Bubbling Phase）：事件从目标元素开始向上冒泡，直到最外层的DOM元素（Window对象）。addEventListener方法的第三个参数默认为false，指事件会在冒泡阶段触发，若设置为true，事件将会在捕获阶段触发。因此对于这样一个场景，如需要在全局监听click事件并调用事件处理函数handleClick，如果用默认方式添加事件的话，handleClick会在click事件的冒泡阶段调用，但系统中其它元素也可能会绑定click事件，甚至还可能会用stopPropagation方法阻止事件的冒泡，这会导致全局绑定的handleClick不会被触发。这种场景下可以设置全局添加的click事件在捕获阶段触发，从而避免因调用stopPropagation导致阻止事件冒泡。6.vue指令相互覆盖问题有两个vue2项目a, b；a项目被构建为sdk，b项目作为一个业务项目引入了a项目sdk。碰到了这样一个问题：a项目中用了一个指令v-move，并且自己有实现，b项目中有一个同名的指令，在实际应用过程中发现，b项目中的组件触发v-move指令时，有时候触发的是a中的代码，有时候触发的是b中的代码。造成这个问题的原因主要是两个项目中的指令都是全局注册的，而两个项目共用的是同一个全局Vue，因此在指令注册时可能会互相覆盖。为避免这个问题可以采取以下方法：指令改为局部注册尽可能避…

前端性能指标学习
type: item
date: 2024-06-23T19:27:00+08:00
description: web核心性能指标（Core Web Vitals）Web Vitals是谷歌开发的一系列指标，用于从不同方面去衡量网页的性能。而Core Web Vitals是Web Vitals的一个子集，包含了3个需要特别关注的指标，它们在谷歌搜索算法中扮演着一定的角色，并能够改善网站在谷歌搜索中的权重。LCP（Largest Contentful Paint，最大内容绘制）概念LCP用于用于测量用户感知到的页面加载速度，指从页面开始加载到页面中最大的内容元素被渲染到屏幕上的时间点。这个最大的内容元素可能是图片、视频、SVG、含有背景图的元素、包含文本节点或其它含有文本子元素的块级元素。需要注意的是，随着页面的不断加载，页面中的最大内容元素可能会发生变化，因为更大的内容元素可能还未加载，因此LCP在页面加载过程中也会不断更新直至页面加载完毕。LCP包含从上一个网页开始的所有卸载时间、连接设置时间、重定向时间和首字节时间（TTFB）。测量方式通过PerformanceObserver监测LCP：new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { console.log('LCP candidate:', entry.startTime, entry); } }).observe({type: 'largest-contentful-paint', buffered: true});根据LCP的定义，随着网页的加载以上代码会获取到多个startTime值，而所获取到的最后一个值便是页面的LCP值。通过web-vitals监测LCP：import {onLCP} from 'web-vitals'; // Measure and log LCP as soon as it's available. onLCP(console.log);为获取更精确的LCP，推荐使用第二种方式，详见Web.dev。指标分数为提供良好的用户体验，网站应努力将Largest Contentful Paint控制在2.5s以内。为确保大多数用户都达到此目标，最好衡量一下网页加载的第 75 个百分位（按移动设备和桌面设备细分）。INP（Interaction to Next Paint，下一次绘制的交互）概念INP衡量页面在整个生命周期中的交互能力（响应能力），通过观察用户在访问网页期间发生的所有点击、点按和键盘互动的延迟时间，评估网页对用户互动的总体响应情况。INP的计算方法是观察用户与网页进行的所有交互并记录延迟时间，最终INP值是观测到的最长交互时间，离群值会被忽略。对于大多数网站来说，延迟时间最长的交互就是INP，但对于包含大量交互的页面来说可能会不准确，因此INP在计算过程中会忽略达到50次交互中的延迟最长的一次交互。根据INP的定义，只会监测以下类型的交互：使用鼠标点击。点按带有触摸屏的设备。按实体键盘或屏幕键盘上的某个键。如果页面一直未接收到以上类型的交互，那么页面将不会返回INP值。2024年3月，INP取代了FID成为Core Web Vitals。测量方式通过web-vitals监测INP：import {onINP} from 'web-vitals'; onINP(({name, value, rating}) => { console.log(name); // 'INP' console.log(value); // 512 console.log(rating); // 'poor' });指标分数为提供良好的用户体验，网站应努力将Largest Contentful Paint控制在200ms以内，为确保大多数用户都达到此目标，最好衡量一下网页加载实际记录的第 75 个百分位（按移动设备和桌面设备细分）：CLS（Cumulative Layout Shift，累计布局偏移）概念布局偏移指页面中的元素所发生的意外移动，这主要发生在当资源以异步方式加载或DOM元素被动态添加到页面的现有内容中时。比如页面上方有一个广告，当用户刚进入页面时还未获取到广告数据，在获取到广告数据后，广告横幅被加载到页面顶部，此时页面中其它的内容都向下移动了广告横幅的高度，这就叫布局偏移。CLS 用于衡量再页面的整个生命周期中发生的所有意外布局偏移的得分之和。布局的移动可能发生在可见元素从一帧到下一帧改变的任何时候，并且仅当现有元素更改其起始位置时才会发生布局偏移。如果将新元素添加到DOM或现有元素更改了大小，只要没有导致其他可见元素更改其起始位置，就不应将其视为布局偏移。测量方式布局偏移计算方式：new PerformanceObserver(…

第3章-优先级和层叠
type: item
date: 2024-06-02T23:44:49+08:00
description: 1.继承和层叠继承（Inheritance）是从一个元素向其后代元素传递属性值所采用的机制。确定应向一个元素应用哪些值时，用户代理不仅要考虑继承，还要考虑声明的特殊性（优先级），以及声明本身的来源，这个过程就叫做层叠（cascade）。2.CSS特殊性值的计算规则对于选择器中给定的各个ID属性值，加 0, 1, 0, 0对于选择器中给的的各个类属性值、属性选择或伪类，加 0, 0, 1, 0对于选择器中给定的各个元素和伪元素，加 0, 0, 0, 1。内联样式的特殊性为 1, 0, 0, 0结合符和通配选择器对特殊性没有任何贡献，但又不完全一样。结合符和继承根本没有特殊性，通配选择器的特殊性是0, 0, 0, 0，是要高于结合符和继承的。!important 令该样式规则获取到最高的优先级，甚至是超过内联样式h1 {color: red;} /* specificity = 0, 0, 0, 1 */ p, em {color: red;} /* specificity = 0, 0, 0, 2 */ .grape {color: red;} /* specificity = 0, 0, 1, 0 */ *.grape {color: red;} /* specificity = 0, 0, 1, 0 */ p.bright em.dark {color: red;} /* specificity = 0, 0, 2, 2 */ #id666 {color: red;} /* specificity = 0, 1, 0, 0 */ div#sidebar *[href] {color: red;} /* specificity = 0, 1, 1, 1 */注意：通配选择器的特殊性是0, 0, 0, 0，这与根本没有特殊性是有区别的，后续会讲到。相对来说，结合符则根本没有特殊性，甚至连0特殊性都没有。声明性与特殊性一旦确定一个选择器的特殊性，这个值将被授予其所有的相关声明。如h1, h2.section {color: red; background: black;}，为了计算优先级，用户代理会将完整的规则"解组"为单独的规则，如下所示，这样计算出的优先级就可以赋值给每一个相关声明。h1 {color: red;} /* 0, 0, 0, 1 */ h1 {background: black;} /* 0, 0, 0, 1 */ h2.section {color: red;} /* 0, 0, 1, 1 */ h2.section {background: black;} /* 0, 0, 1, 1 */任何情况下，用户代理都会确定那些规则与一个元素匹配，计算出所有相关的声明及其特殊性，确定哪些规则胜出，然后将胜出的规则应用到元素，从而得到应用样式后的结果。每个元素、选择器和声明上都必须完成这些工作。这个行为是层叠的一个重要部分。重要性（重要声明important declaration）在声明的结束分号之前插入!important来标志重要声明。重要声明并没有特殊的特殊性值。如果一个重要声明和一个非重要声明冲突，胜出的总是重要声明。另外：重要声明与非重要声明的特殊性是分开处理的。也就是说，所有重要声明会放在一起，它们之间的冲突在这个范围内解决。同样，非重要的声明作为一个整体，其中的冲突使用特殊性解决。3.继承与特殊性基于继承，样式不仅可以应用到指定的元素，还可以应用到它的后代元素。但是要注意继承到后代的样式是没有特殊性的，连0都没有。所以: Title 今天是周五 如上所示的代码，我们知道通配选择器的特殊性是0，然而继承根本没有特殊性，所以上面的代码运行结果是”周五“是灰色而不是红色。总之，0特殊性比无特殊性要强。4.层叠CSS2.1的层叠规则找出匹配特定元素的所有规则按显示权重排序应用到特定元素上的所有声明。标志!important的规则的权重要高于没有!important标志的规则。按来源对应用到给定元素的所有声明排序。共有3种来源：创作人员、读者和用户代理。正常情况下，创作人员的样式要胜过读者的样式。有!important标志的读者样式要强于所有其他样式，这包括有!important标志的创作人员样式。创作人员样式和读者样式都比用户代理的默认样式要强。按照特殊性对应用到给定元素的所有声明排序。有较高特殊性的元素权重要大于有较低特殊性的元素。按出现顺序对应用到给定元素的所有声明排序。一个声明在样式表或文档中越后出现，他的权重就越大。如果样式表中有导入的样式表，一般认为出现在导入样式表中的声明在前，主样式表中的所有声明在在后。声明的权重级别在声明权重方面要考虑从5级，权重由大到小的顺序依次为：读者的重要声明创作人员的重要…