整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

移动端使用amfe-flexible和postcss-plugin-px2rem做适配

移动端做适配有几种方法,今天来聊聊amfe-flexible和postcss-plugin-px2rem。

amfe-flexible:动态改变根字体的大小(会在html上自动添加上font-size);

postcss-plugin-px2rem: 编译时,根据字根的大小,将px转换成rem。

  • 安装

1. 安装amfe-flexible

npm install -S amfe-flexible

2. 在main.js中引入

import 'amfe-flexible/index.js'

3. 修改public/index.html

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">

安装好后,重新启动,就可以看到html上设置了font-size样式,切换不同型号的手机,可以看到font-size会随之变化。

1. 安装postcss-plugin-px2rem

npm install postcss-plugin-px2rem lib-flexible --save-dev

2. 在vue.config.js添加如下码

module.exports = {
   css: {
       // 启用 CSS modules
       // 是否使用css分离插件
       extract: true,
       // 开启 CSS source maps?
       sourceMap: false,
       // css预设器配置项
       loaderOptions: {
         css: {},
         postcss: {
           plugins: [
             require('postcss-plugin-px2rem')({
               rootValue: 100, //字体基数,设计稿为750的基数
               exclude: /(node_module)/, // 默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
               mediaQuery: true, // (布尔值)允许在媒体查询中转换px。
               minPixelValue: 3 // 设置要替换的最小像素值(3px会被转rem)。 默认 0
             })
           ]
         }
       }
     }
};

配置好后,貌似我们成功喽。来试一下是否可以。在app.vue页面里给#app配置一下宽度,并给个黑色背景。

启动服务看下效果:控制台确实变成了7.5rem,html上的字根大小也确实是动态的。但似乎哪里不对啊!为什么任何型号的手机上都没有全屏铺满黑色?

揭密:

是因为px2rem和amfe-flexible换算的基数不一样!

以UI图750px为例,在插件px2rem里配置的基数是100px,即将整屏分成了7.5份,其它型号的手机如果分成7.5份的话,那么基数则是手机宽度/7.5,这个基数是html里的字根的大小。我们来看看amfe-flexible的基数是多少嘞?在node_modules找到amfe-flexible的库,发现这里设置的是将手机宽度分成了10,则每份的基数变少,所以铺不满。这里我们要做下修改,使amfe-flexible与px2rem匹配上:

打开amfe-flexible所在的目录:

var rem = docEl.clientWidth / 10

替换成

var rem = docEl.clientWidth / 7.5

修改后我们再重新启动一下看看效果吧~

在任何机型下都能铺满屏!完美!

接下来我们就可以使用px畅快淋漓地写代码啦!

提示:当脱离掉node_modules重新npm install项目依赖时还是需要重新修改一遍的,千万别忘了!

于 CSSer 来说,多多少少都会遇到过 “样式规则不生效?”、“样式规则被覆盖?” 等等问题,这些都与 CSS 权重有关系。

我自己是一名从事了多年开发的web前端老程序员,目前辞职在做自己的web前端私人定制课程,今年年初我花了一个月整理了一份最适合2019年学习的web前端学习干货,各种框架都有整理,送给每一位前端小伙伴,想要获取的可以关注我的头条号并在后台私信我:前端,即可免费获取

选择器匹配原理

在此之前,容我先简单介绍浏览器是怎么通过各种选择器,把样式规则和 DOM 元素扯上关系的。

浏览器中存在着专门的渲染引擎来渲染 HTML 文档。这里以 Webkit 内核为例,在启动渲染流程时,引擎一方面会解析 HTML 文档,构建 DOM 节点树(DOM Tree),另一方面会解析样式文件生成 样式规则(Style Rules),然后结合分析 DOM 树和样式规则生成 渲染树(Render Tree),最后 布局绘制 出 UI 界面。

Webkit 渲染流程(摘自 https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/)

CSS 的选择器匹配就发生在 渲染树 的构建过程。浏览器会从 DOM 树的根节点开始遍历每个可见节点,对于每个可见节点都会在规则表中查找适配的样式规则。那么,如此庞大的样式数据和复杂的选择器结构,渲染引擎是怎么寻找到适配当前元素的样式规则呢?

请看下面这个复合选择器。如果引擎是按照从左向右的顺序匹配选择器,将会导致大量 回溯 的发生:先是在当前节点到 DOM 树跟节点的路径上寻找 div 元素,然后沿着分支路径继续往下找第二个 div 元素,如果当前路径找不到,就得回退到上一个 div 元素尝试另一条分支路径。如此往复,对性能损耗将会非常严重。

div div span .text {}

所以,引擎是采取 从右向左 的顺序来匹配选择器。也就是 从最具体的选择器开始,如果与当前节点不匹配,则直接抛弃该条规则;如果匹配,只需要沿着路径往上确认其他选择器是否也匹配,这样做可以大大减少无效的匹配数,提高性能。除此之外,引擎还会把不同类型的选择器(id、class、tag 及其他类型)归类到哈希表中,进一步减少查找基数。

了解选择器的匹配原理,有利于我们理解其权重规则,对于编写简洁、高效的 CSS 代码非常有帮助。

CSS 权重

通过不同的方式(内联样式、外部样式表)、不同类型的选择器组合针对某个元素声明样式规则时,如何决定最终哪个声明会被应用到元素上?这就涉及到 CSS 权重(也指优先级,Specificity)

围绕 CSS 权重主要有以下三条规则:

  • 权重不同的样式规则作用于同一元素时,权重高的规则生效;
  • 权重相同的样式规则作用于同一元素时,后声明的规则生效;
  • 选择器在 DOM 中的位置关系不会对规则产生影响。
<html>
 <head>
 <style>
 body div {
 color: red;
 }
 html div {
 color: blue;
 }
 </style>
 </head>
 <body>
 <div>测试</div>
 </body>
<html>


  • 这里的 body 标签元素在 DOM 中离目标 div 更近,但最后还是按照样式规则的声明顺序来决定。
  • 直接作用于元素的样式规则优先级高于从祖先元素继承的规则;
<html>
 <head>
 <style>
 #parent {
 color: red;
 }
 span {
 color: blue;
 }
 </style>
 </head>
 <body>
 <div id="parent">
 <span>测试</span>
 </div>
 </body>
<html>


CSS 权重等级

如何比较不同选择器的权重高低?这里划分成 5 个权重等级,按照等级 由高到低 的顺序:

  • !important 关键字
  • 内联样式
<div style="color: #fff;">测试</div>

id 选择器

#demo {}

类选择器属性选择器伪类选择器

.demo {}
[type="text"] {}
div:hover {}
div:first-child {}

需要注意,否定伪类(:not())比较特殊,它不会对权重产生影响,但是 否定伪类内部的选择器会影响权重

<html>
 <head>
 <style>
 div#demo span {
 color: red;
 }
 div:not(#demo) span {
 color: blue;
 }
 </style>
 </head>
 <body>
 <div id="demo">
 <span>普通 demo</span>
 <div id="pseudo">
 <span>否定伪类 demo</span>
 </div>
 </div>
 </body>
<html>


  • 实例中,:not(#demo) 的权重值和 #demo 的权重值是相等的,所以后面声明的样式规则成功生效。
  • 标签选择器伪元素选择器
div {}
div:before {}
div:after {}

除了上述的选择器之外,通配符选择器(*)结合符(+、>、~)对优先级没有影响。

对于复杂的复合选择器,我们需要逐个等级比较权重大小,不允许跨越等级比较。为了方便计算,我们可以把权重值具象化,每出现一个选择器就在其对应的等级区间中权重值加 1,参考下面实例:

* {} /* 权重值 0-0-0-0-0 */
div {} /* 权重值 0-0-0-0-1 */
div h1+h2 {} /* 权重值 0-0-0-0-3 */
div, ... div {} /* 权重值 0-0-0-0-n */
#demo a:hover {} /* 权重值 0-0-1-1-1 */

国外大神 把 CSS 权重的计算模拟成海洋生物链,选择器组合权重越大则在生物链位置越高,非常浅显生动,建议收藏。

图片转自 https://specifishity.com/

建议

在充分了解 CSS 选择器匹配原理和权重规则之后,在编写 CSS 代码时不妨多注意以下细节:

  • 尽量不要使用 !important,尤其是在 对外提供的插件全站范围的样式表 中,这会对模块代码中的样式覆盖带来非常大的麻烦。
  • !important 关键字的权重值为 1-0-0-0-0,只需要按照权重规则继续累加权重值即可覆盖该样式属性。
<html>
 <head>
 <style>
 div {
 color: red !important;
 }
 /* 通过 id选择器 增加权重 */
 #demo {
 color: blue !important;
 }
 </style>
 </head>
 <body>
 <div id="demo">测试</div>
 </body>
<html>

减少不必要的选择器嵌套,嵌套最好不要超过三级。大量的复合选择器,会影响选择器匹配的效率,同时也会增加 CSS 样式文件的体积,不易维护。

当出现大量嵌套时,我们可以指定一个更具体的类选择器来替换复合选择器。

文分享自华为云社区《DTSE Tech Talk | 3招解决时序数据高基数难题,性能多维度提升!-云社区-华为云》,作者:华为云开源。

本期openGemini全新列存引擎,为您解决时序数据高基数难题的主题直播中,华为云开源DTSE技术布道师&数据库创新Lab技术专家黄飞腾,与开发者朋友们分享了时序数据库的特点和遥测数据应用场景下的优势,通过解析openGemini的框架引出了数据库行业长期存在的一大痛点—由于高基数导致的性能大幅下降,并向大家介绍了openGemini时序数据库针对这一难题而开发的列存引擎是如何有效改善高基数带来的不利影响。

为什么面对海量遥测数据,时序数据库才是更佳选择?

市面上有很多不同类型的数据存储系统,它们在不同场景具有不同的优势和局限性。那海量遥测数据场景下,我们应该选择什么类型的数据库呢?先感受一下遥测数据的庞大,全国每天光智能电表就能生成500亿条记录,10万辆车的企业每天采集约1PB数据。海量的数据产生后给存储带来了巨大的压力,传统数据库已不能满足如今的实际业务需求。因此,面向运维监控、物联网等众多领域,专注海量遥测数据存储与分析的时序数据库应运而生。

以openGemini时序数据库为例,它具有高并发、低时延、低成本的特性,完美契合企业的需要。更重要的是,openGemini框架中自带全新开发的“列存引擎”,重点解决时序高基数问题,为性能保驾护航。

高基数会带来什么样的问题?

首先了解一下基数是什么,基数:表示某一列数据中唯一值的个数。

那高基数就可以理解为一个列中不同值的数量很大。不同的标签或者列有不同的基数,如 ip 地址基数可能达到亿级,时间戳则与采样频率相关,采样频率越高则基数越高。

在高基数的场景下,tag组合数量、SID数量会急剧膨胀,倒排索引中的 SID lists 膨胀,导致倒排索引的维护与查询开销增大。

最终,对外表现的性能会急剧下降,那高基数给时序引擎带来的具体问题为:

  • 内存资源
  • 读写性能下降

openGemini如何应对高基数问题?

openGemini目前解决该问题应对措施为:列式存储+排序+聚簇索引。

简单来说,我们把时间线的约束去掉,采取部分的标签和列做排序,排序完成后会按照排序键排序列示存储,存储之后再构造一个稀疏(聚簇)索引,这样的优势是:索引相对于数据而言,总是稀疏的,与时间线无关,构建开销不会随时间线的增加而增加。聚簇索引存储每个 Block 的第一条记录,数据有序时,该索引有良好得过滤效果。

列存引擎和时序引擎最主要的差别是数据排序的方式和索引方式的不同。时序引擎是按照时间线力度来做聚簇,然后再按时间做排序。而高基数列存引擎是按照特定的列做排序,跟时间线无关。时序引擎采用倒排索引,时间线膨胀会导致倒排索引的开销变大,列存引擎的构建与时间线无关。继而以上的列存引擎设计思路可以大大提升数据库的读写性能。

时序引擎的倒排索引,本质上存储了一个 kv 对,其中 key 对应到所有的 tag 列名 + tag 值,value 对应该 tag 值所对应的所有时间线,所以通过倒排索引可以快速查找到特定 tag 列的所有唯一值。如果没有倒排索引,则需要完全扫描该列数据,并进行去重,查询开销与数据量成正比,在数据量较大的情形,开销非常大。新引入的列式存储方案,基于现有倒排索引对 key 的去重能力,直接存储了该列的唯一值。

手把手教你轻松使用列存引擎

openGemini 从 v1.1.0 版本开始支持列存引擎以及 Arrow 协议。

文档:https://docs.opengemini.org/zh/guide/features/high_series_cardinality.html

Arrow Flight 配置

创表

接下来请查看实操演示视频,复制链接查看直播完整版:https://bbs.huaweicloud.com/live/DTT_live/202311151630.html

列存引擎在高基数场景的验证结果

如下图所示,与其他数据库做测试对比,从时间线支持规模来看,openGemini达到无上限;单核写入性格提升到60万rows/s/cpu;

在特定4个场景下,亿级时间线并发查询时延都远远低于测试产品,最低时延为0.012s。在全量数据统计查询场景下,openGemini与对比产品基本相当,整体时延都非常低。总体看,openGemini不论是写入还是查询,性能都十分优秀。

欢迎大家加入openGemini社区

openGemini社区旨在打造开放、合作、包容的全球性技术社区,社区正在快速发展中,接下来会聚焦于开发更多功能,对性能进行调优。社区尚有理想未达,在此诚邀大家参与openGemini的建设(不限于代码、文档、生态贡献),同社区一起成长,彼此携手方能到达远方。

关注#华为云开发者联盟# 点击下方,第一时间了解华为云新鲜技术~

华为云博客_大数据博客_AI博客_云计算博客_开发者中心-华为云