前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >换肤功能(scss、css变量)

换肤功能(scss、css变量)

原创
作者头像
Krry
修改于 2021-04-20 09:52:06
修改于 2021-04-20 09:52:06
4.5K0
举报
文章被收录于专栏:KrryblogKrryblog

博客地址:https://ainyi.com/104

产品 SaaS 化,通常需要有换肤功能

这里简单记录一下主题色及其衍生色(高亮、浅色)的更换功能

scss 全局定义

每个页面都有颜色,那么应该把颜色值定义在 global.scss 文件中,通过变量定义,比如

代码语言:txt
AI代码解释
复制
$color-primary: #4762FE;
$color-primary-dark: #3245D9;
$color-primary-light: #C2D1FF;
$color-primary-lightest: #EBF0FF;
$color-primary-transparency: rgba(71,98,254,0.1);

每个页面的样式表引入此文件

代码语言:txt
AI代码解释
复制
@import './global.scss';

// 使用例子
.demo {
  color: $color-primary
}

这样,只要更改 scss 中全局变量的颜色值,就可以同步更改项目的颜色值

css 变量定义

思考如何注入颜色值?

这里就用到 css 的变量函数了:==var()==

之前有谈到使用 css 的变量以及赋值方法:Bilibili [冬] banner 早中晚切换效果

var() 函数用于插入自定义的属性值

两个参数:property,value

property:必填,自定义属性的名称,必需以 -- 开头

value:可选,备用值,在属性不存在的时候使用

比如

代码语言:txt
AI代码解释
复制
body {
  --tempColor: #fff;
}
.temp {
  color: var(--tempColor)
}

设置其属性:DOM.style.setProperty(name, value)

这里就很清楚了,==scss 中全局变量引入的是 var() 函数的变量值==

获取衍生色

主题色是只有一个,需要通过主题色来获取其衍生颜色(高亮、浅色等)

scss 中提供一个方法:==mix()==

Mix 函数是将两种颜色根据一定的比例混合在一起,生成另一种颜色。其使用语法如下:

代码语言:txt
AI代码解释
复制
mix($color-1,$color-2,$weight);

$color-1 和 $color-2 指的是你需要合并的颜色,颜色可以是任何表达式,也可以是颜色变量

$weight 为 合并的比例(选择权重),默认值为 50%,其取值范围是 0~1 之间。它是每个 RGB 的百分比来衡量,当然透明度也会有一定的权重

如果指定的比例是 25%,意味着==第一个颜色==所占比例为 25%,第二个颜色所占比例为75%

此外,scss 还有一个 HSL 函数,也是设置颜色值的方法,这里就不过多探究了

坑来了

当我把 var() 函数获取的颜色值放进 mix 函数中,居然报错:

SassError: argument $color-2 of mix($color-1, $color-2, $weight: 50%) must be a color

mix 函数无法使用带有 var() 函数变量的参数,HSL 函数也是;但普通变量是可以的

最终只能使用 js 函数通过主题色来获取衍生颜色

这里提供几个方法:

代码语言:txt
AI代码解释
复制
// str: 十六进制颜色值,n:透明度
export function colorRgba(str, n) {
  // 十六进制颜色值的正则表达式
  let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
  let sColor = str.toLowerCase()
  n = n || 1
  // 十六进制颜色转换为RGB格式
  if (sColor && reg.test(sColor)) {
    let sColorChange = getRgbNum(sColor)
    return 'rgba(' + sColorChange.join(',') + ',' + n + ')'
  } else {
    return sColor
  }
}
// 获取 rgb 颜色值
function getRgbNum(sColor) {
  if (sColor.length === 4) {
    let sColorNew = '#'
    for (let i = 1; i < 4; i += 1) {
      // 补全颜色值 例如:#eee,#fff等
      sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
    }
    sColor = sColorNew
  }
  // 处理六位颜色值
  let sColorChange = []
  for (let i = 1; i < 7; i += 2) {
    // 核心代码,通过parseInt将十六进制转为十进制,parseInt只有一个参数时是默认转为十进制的,第二个参数则是指定转为对应进制
    sColorChange.push(parseInt('0x' + sColor.slice(i, i + 2)))
  }
  return sColorChange
}
// 加深或减弱颜色值
export function lightDarkenColor(color, num) {
  let colorArr = getRgbNum(color)
  let sColorChange = []
  for (let i = 0; i < colorArr.length; i++) {
    let val = colorArr[i] + num
    if (val < 0) {
      val = 0
    }
    if (val > 255) {
      val = 255
    }
    sColorChange.push(val)
  }
  return 'rgba(' + sColorChange.join(',') + ',1)'
}

最后只需要在==路由全局前置守卫==中计算颜色值,并赋值到 css 变量上,在 scss 全局变量中用 var() 函数引入 css 变量(各种颜色值)

换肤流程

通过接口获取主题色 --> js 计算衍生色值 --> 赋值到 css 变量 --> scss 全局变量用 var() 函数引入 css 变量 --> 页面样式引用 scss 全局颜色值

使用例子

global.scss

代码语言:txt
AI代码解释
复制
$color-primary: var(--primaryColor, #4762FE);
$color-primary-dark: var(--primaryDarkColor, #3245D9);
$color-primary-light: var(--primaryLightColor, #C2D1FF);
$color-primary-lightest: var(--primaryLightestColor, #EBF0FF);
$color-primary-transparency: var(--primaryTransparencyColor, rgba(71,98,254,0.1));

路由守卫:

代码语言:txt
AI代码解释
复制
router.beforeEach((to, from, next) => {
  const primaryColor = getConfigStyle() // 从接口获取的主题色
  const colorObj = {
    primaryColor: primaryColor,
    primaryDarkColor: lightDarkenColor(primaryColor, -20),
    primaryLightColor: colorRgba(primaryColor, 0.3),
    primaryLightestColor: colorRgba(primaryColor, 0.12),
    primaryTransparencyColor: colorRgba(primaryColor, 0.1)
  }
  Object.entries(colorObj).forEach(ele => {
    // 逐个设置 css 变量到 body 上
    document.body.style.setProperty(`--${ele[0]}`, ele[1])
  })
  next()
})

博客地址:https://ainyi.com/104

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Vue.nextTick 的原理和用途
Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。
青梅煮码
2023/03/02
5300
浅析$nextTick和$forceUpdate
vue中提供了数十种api供我们开发者日常使用,而常用的其实也就十多种,比如setup, mount, forceupdate, nextTick, compute, ref等,这些参数有的是在生命周期中进行管理,有的是在页面执行过程中,更新参数,有些是可以用来检测页面数据,这些随着项目的推进或多或少都是会使用到。其中nextTick和forceUpdate都是用来更新参数的,那这两个参数有什么差异呢?这还真值得仔细琢磨。
Yerik
2022/04/05
1.9K0
vue归纳笔记:对vue中nextTick()的理解及应用场景说明
请记住:vue是依靠数据驱动视图更新的,该更新的过程是异步的。即:当侦听到你的数据发生变化时, Vue将开启一个队列(该队列被Vue官方称为异步更新队列)。视图需要等队列中所有数据变化完成之后,再统一进行更新。
用户1272076
2019/06/13
9540
关于vue中$nextTick的一点使用心得
当下公司在做一个媒体门户网站,后台由另一家公司使用java开发并提供接口,本人负责开发后台页面,使用的是vue-element-admin开发 下面说一下问题场景,在开发过程中有一个后台管理员角色页面,其中包含一个表单dialog,在其中使用了el-tree组件,相关 代码结构如下: <div class="filter-container"> <el-button class="filter-item" style="margin-left: 10px;" v-waves @click="hand
lestat
2018/04/17
2.2K0
Vue面试题-03
前言 马上要秋招了,搜集整理了一些Vue面试题,包括组件、指令、API等相关内容,巩固基础😎秋招冲冲冲!!!本篇包括: ✅keep-alive的理解 ✅nextTick的理解 ✅vue组件之间的通信方式 ✅Vuex的理解及使用场景 keep-alive的理解 Props: include - string | RegExp | Array。只有名称匹配的组件会被缓存。 exclude - string | RegExp | Array。任何名称匹配的组件都不会被缓存。 max - number |
客怎眠qvq
2022/11/01
2.5K0
面试题:Vue中$nextTick原理
 在做项目的时候,我们经常会用到nextTick,简单的理解就是它就是一个setTimeout函数,将函数放到异步后去处理;将它替换成setTimeout好像也能跑起来,但它仅仅这么简单吗?那为什么我们不直接用setTimeout呢?让我们深入剖析一下。
前端迷
2020/05/26
6.1K0
面试题:Vue中$nextTick原理
Vue异步更新队列及nextTick
vue通常鼓励开发人员沿着“数据驱动”的方式思考,避免直接接触 DOM。Vue的dom更新是异步的,当数据发生变化,vue并不是里面去更新dom,而是开启一个队列。跟JavaScript原生的同步任务和异步任务相同。
wade
2020/04/24
7790
2022 最新 Vue 3.0 面试题
Vue 作为一款轻量级框架、简单易学、双向数据绑定、组件化、数据和结构的分离、虚拟 DOM、运行速度快,并且作者是中国人尤雨溪,对应的 API 文档对国内开发者优化,作为前端 开发人员的首选入门框架 Vue 的优势: 1、Vue.js 可以进行组件化开发,使代码编写量大大减少,读者更加易于理解。 2、Vue.js 最突出的优势在于可以对数据进行双向绑定。 3、使用 Vue.js 编写出来的界面效果本身就是响应式的,这使网页在各种设备上都能 显示出非常好看的效果。 4、相比传统的页面通过超链接实现页面的切换和跳转,Vue 使用路由不会刷新页 面。 5、vue 是单页面应用,使页面局部刷新,不用每次跳转页面都要请求所有数据和 dom,这样大大加快了访问速度和提升用户体验。 6、而且他的第三方 UI 组件库使用起来节省很多开发时间,从而提升开发效率。
猫头虎
2024/04/07
1670
Vue中的nexTick()
获取更新后的DOM言外之意就是,操作需要用到了更新后的DOM而不能使用之前的DOM或者使用更新前的DOM会出问题,所以就衍生出了这个获取更新后的 DOM的Vue方法。所以放在Vue.nextTick()回调函数中的执行的应该是会对DOM进行操作的 JS代码。
刘亦枫
2020/03/19
1.6K0
面试官:Vue中的$nextTick怎么理解?
我们可以理解成,Vue 在更新 DOM 时是异步执行的。当数据发生变化,Vue将开启一个异步更新队列,视图需要等队列中所有数据变化完成之后,再统一进行更新
@超人
2021/02/26
1.4K0
面试官:Vue中的$nextTick怎么理解?
Vue.nextTick核心原理
相信大家在写vue项目的时候,一定会发现一个神奇的api,Vue.nextTick。为什么说它神奇呢,那是因为在你做某些操作不生效时,将操作写在Vue.nextTick内,就神奇的生效了。那这是什么原因呢?
yyds2026
2022/10/18
5620
SSM 单体框架 - 前端开发:用户和权限模块
在查询条件中使用了 Element UI 中的日期选择器:https://element.eleme.cn/#/zh-CN/component/date-picker#mo-ren-xian-shi-ri-qi
RendaZhang
2020/10/09
1.7K0
SSM 单体框架 - 前端开发:用户和权限模块
VUE 异步更新队列 - $nextTick()
Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后在下一个的事件循环 “tick” 中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。
用户7043603
2022/02/26
8840
Vue.$nextTick的原理是什么-vue面试进阶
原理性的东西就会文字较多,请耐下心来,细细品味Vue中DOM更新机制当你气势汹汹地使用Vue大展宏图的时候,突然发现,咦,我明明对这个数据进行更改了,但是当我获取它的时候怎么是上一次的值(本人比较懒,就不具体举例了👵)此时,Vue就会说:“小样,这你就不懂了吧,我的DOM是异步更新的呀!!!”简单的说,Vue的响应式并不是只数据发生变化之后,DOM就立刻发生变化,而是按照一定的策略进行DOM的更新。这样的好处是可以避免一些对DOM不必要的操作,提高渲染性能。在Vue官方文档中是这样说明的:可能你还没有注意到
bb_xiaxia1998
2022/10/04
3120
Vue.js 中 nextTick | 笔记
引言 对 Vue 组件数据(props 或状态)的更改不会立即反映在 DOM 中。 相反,Vue 异步更新 DOM。 你可以使用 Vue.nextTick() 或 vm.$nextTick() 函数捕获 Vue 更新 DOM 的时刻。 让我们详细了解这些函数的工作原理。 nextTick() 当 Vue 组件数据发生变化时,DOM 会异步更新。 Vue 会收集来自所有组件的多个虚拟 DOM 更新,然后创建一个批处理来更新DOM。 在单个批次中更新 DOM 比进行多个小的更新更高效。 例如,让我们考虑一个切换元素显示的组件:
yiyun
2023/09/30
2820
Vue.js 中 nextTick | 笔记
第八章:vue生命周期、vue的DOM操作、mixin混入,插件
开发过程中当多个组件开发时有相同类名时,此时vue会按照组件的导入顺序进行解析,后导入的组件 会覆盖先导入的组件类名样式
用户9184480
2024/12/13
1230
重磅来袭~~~ Vue原来可以这样写,开发效率杠杠的
每天上班写着重复的代码,当一个cv仔,忙到八九点,工作效率低,感觉自己没有任何提升。如何能更快的完成手头的工作,提高自己的开发效率,在上一篇《绝对干货~!学会这些Vue小技巧,可以早点下班和女神约会了》,小编整理了一些Vue开发技巧,今天小编又整理了一些新的Vue使用技巧。你们先加班,我先下班陪女神去逛街了。
前端进击者
2021/07/27
5190
Vue 开发技巧总结
v-model 是 Vue 提供的一个语法糖,它本质上是由 value 属性 + input 事件组成的(都是原生的默认属性)
Krry
2020/08/28
6170
3.vue生命周期钩子函数有哪些?(vue生命周期的理解)
1、beforeCreate(创建前):beforeCreate钩子函数,这个时候,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。无法访问到数据和真实的dom和data中的数据,可以在这里面使用loading
全栈程序员站长
2022/07/28
7990
3.vue生命周期钩子函数有哪些?(vue生命周期的理解)
Vue JSX、自定义 v-model
最初用到 JSX,就是做这个博客的时候。iview 表格组件,不支持像 element 那样直接写 html 代码渲染,只能通过 render 函数渲染,也就是 JSX 语法
Krry
2020/07/16
4.7K1
相关推荐
Vue.nextTick 的原理和用途
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文