前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >详解在 vaw-layouts 中通过 sass 实现动态换肤功能 (一)

详解在 vaw-layouts 中通过 sass 实现动态换肤功能 (一)

作者头像
用户9078190
发布2022-10-25 21:31:09
1.1K0
发布2022-10-25 21:31:09
举报
文章被收录于专栏:知码前端知码前端

在以往的前端开发中,css 一直不能称之为一种编程语言,虽然在 css3中增加了几个变量和函数,但是实现的功能还是比较有限。后来出现了几个css预处理器,比较常用的有:sass、less 、stylus。有了他们,我们可以对css进行一些简单的编程。如果您对他们还不了解,可以查看一下他们的官网学习一下,vaw-layouts项目中使用的的预处理器是sass,因此本文也是基于sass进行讲解实现动态换肤的功能。

先说一下实现换肤的大体思路:

1、提前定义好几个不同命名空间下的class

2、通过js实现对元素动态切换class属性值

这种方式有几个缺点:

1、要提前定义好不同命名空间下的class,不够灵活

2、会增加打包后的应用体积

但是好在这种方式比较简单,适合大多数的场景。因此我们也采用了这种方式。

vaw-layouts中有四种不同的主题:light、dark、dark-side、blue-side

实际上主要的有两种:light dark。因为dark-side、blue-side两种主题只是对 sidebar和navbar进行了适配,主体内容并没有适配,因此我们主要说一下light和dark

其实如果我们不考虑dark的情况下,默认的就是light,我们可以把一个div设置成白色的背景,黑色的字体。这就是light主题了。所以light主题并不用多说什么,按照我们平常的开发该怎么写就怎么写。我们重点说一下怎么适配dark主题,正如前面说的,要实现动态换肤就可定义好不同的命名空间下的class,如下:

代码语言:javascript
复制
.dark{
    .el-button {
      background: $mainContentBgColor;
      color: $mainTextColor;
    }
    .el-table {
      background-color: $mainCardBgColor;
      color: $mainTextColor;
      .hover-row {
        background-color: $mainCardBgColor !important;
      }
      th,
      tr {
        background-color: $mainCardBgColor !important;
      }
      th.is-leaf,
      td {
        border-bottom: 1px solid $mainTextColor;
      }
    }
  	div{
      background: $mainContentBgColor;
      color: $mainTextColor;
  	}
  ...
  }

详解在 vaw-layouts 中通过 sass 实现动态换肤功能 (一)

原创2021-06-03 22:22·知码

在以往的前端开发中,css 一直不能称之为一种编程语言,虽然在 css3中增加了几个变量和函数,但是实现的功能还是比较有限。后来出现了几个css预处理器,比较常用的有:sass、less 、stylus。有了他们,我们可以对css进行一些简单的编程。如果您对他们还不了解,可以查看一下他们的官网学习一下,vaw-layouts项目中使用的的预处理器是sass,因此本文也是基于sass进行讲解实现动态换肤的功能。

先说一下实现换肤的大体思路:

  • 提前定义好几个不同命名空间下的class
  • 通过js实现对元素动态切换class属性值

这种方式有几个缺点:

  • 要提前定义好不同命名空间下的class,不够灵活
  • 会增加打包后的应用体积

但是好在这种方式比较简单,适合大多数的场景。因此我们也采用了这种方式。

vaw-layouts中有四种不同的主题:light、dark、dark-side、blue-side

实际上主要的有两种:light dark。因为dark-side、blue-side两种主题只是对 sidebar和navbar进行了适配,主体内容并没有适配,因此我们主要说一下light和dark

其实如果我们不考虑dark的情况下,默认的就是light,我们可以把一个div设置成白色的背景,黑色的字体。这就是light主题了。所以light主题并不用多说什么,按照我们平常的开发该怎么写就怎么写。我们重点说一下怎么适配dark主题,正如前面说的,要实现动态换肤就可定义好不同的命名空间下的class,如下:

代码语言:javascript
复制
.dark{
    .el-button {
      background: $mainContentBgColor;
      color: $mainTextColor;
    }
    .el-table {
      background-color: $mainCardBgColor;
      color: $mainTextColor;
      .hover-row {
        background-color: $mainCardBgColor !important;
      }
      th,
      tr {
        background-color: $mainCardBgColor !important;
      }
      th.is-leaf,
      td {
        border-bottom: 1px solid $mainTextColor;
      }
    }
  	div{
      background: $mainContentBgColor;
      color: $mainTextColor;
  	}
  ...
  }

这里只是简单说明一下,还有大量的css代码未列出。

说明一下:以 $开头的都是scss下定义的变量,如果不明白,还请查看官方文档。

1、$mainContentBgColor 主要指定背景色

2、$mainTextColor 主要指定文本颜色

同理,我们也定义好light下的class

代码语言:javascript
复制
.light{
    .el-button {
      background: $mainContentBgColor;
      color: $mainTextColor;
    }
    .el-table {
      background-color: $mainCardBgColor;
      color: $mainTextColor;
      .hover-row {
        background-color: $mainCardBgColor !important;
      }
      th,
      tr {
        background-color: $mainCardBgColor !important;
      }
      th.is-leaf,
      td {
        border-bottom: 1px solid $mainTextColor;
      }
    }
  	div{
      background: $mainContentBgColor;
      color: $mainTextColor;
  	}
  ...
  }

然后当我们需要切换背景色的时候就可以改变一下元素的class属性就好了,js代码如下:

代码语言:javascript
复制
export function toggleThemeClass(element, className) {
  if (!element || !className) {
    return
  }
  let classString = element.className
  const clazz = classString.split(' ').filter(it => it.indexOf('theme_') !== -1)
  clazz.push(className)
  classString = clazz.join(' ')
  element.className = classString
}

我们主要是把class应用到了body元素上

代码语言:javascript
复制
<body class="theme_color_blue light">
  ....
</body>

这样就可以完了动态换肤,你以为这就完了?肯定不是,这样有一个问题:

1、如果我们以后再定义几个主题,还得再写一遍上面的代码吗,大量冗余的代码,肯定不好

这个时候就体现出sass的强大了,我们知道,换肤就是改一下那几个变量的值:mainContentBgColor,mainTextColor。如果我们可以通过js动态地修改这几个值,不也可以实现动态换肤?答案是不可以,因为预处理器是在我们开发阶段使用,一旦打包之后,他们就没有了,我们也就没办法再改这些值。所以我们还是老老实实写恶心的代码?当然不行,虽然不可以动态改变这几些,但我们可以提前定义好不同命名下的变量,再通过scss生成不同的全名空间不就行了。如下代码:

代码语言:javascript
复制
// dark下的变量
@function getDarkMaps($primaryColor) {
  @return (
    dark-menuBgColor: #141414,
    dark-contentBgColor: #0f0f10,
    dark-activeTextColor: $primaryColor,
    dark-textColor: #f5f5f5,
    dark-menuActiveBgColor: #2f2f2f,
    dark-badgeColor: #000000,
    dark-headerBgColor: #141414,
    dark-headerBorderColor: $primaryColor,
    dark-headerTextColor: #ffffff,
    dark-headerShadow: #7b7b7b,
    dark-headerTabItemBgColor: #2f2f2f,
    dark-headerTabItemActiveBgColor: #2f2f2f,
    dark-headerTabItemTextColor: #f5f5f5,
    dark-headerTabItemActiveTextColor: $primaryColor,
    dark-mainBorderColor: $primaryColor,
    dark-contentActiveBgColor: #2f2f2f,
    dark-mainContentBgColor: #000000,
    dark-mainCardBgColor: #141414,
    dark-mainCardBorderColor: $primaryColor,
    dark-mainTextColor: #f5f5f5,
    dark-mainActiveTextColor: $primaryColor,
    dark-popoverBgColor: #000,
    dark-popoverBorderColor: $primaryColor,
    dark-popoverTextColor: #f5f5f5
  );
}
// light下的变量
@function getLightMaps($primaryColor) {
  @return (
    light-menuBgColor: #ffffff,
    light-contentBgColor: #f7faff,
    light-activeTextColor: #ffffff,
    light-textColor: #333333,
    light-menuActiveBgColor: $primaryColor,
    light-badgeColor: $primaryColor,
    light-headerBgColor: #ffffff,
    light-headerTextColor: #333333,
    light-headerBorderColor: #f5f5f5,
    light-headerShadow: #f5f5f5f5,
    light-headerTabItemBgColor: #e8f4ff,
    light-headerTabItemActiveBgColor: #e8f4ff,
    light-headerTabItemTextColor: rgb(97, 97, 97),
    light-headerTabItemActiveTextColor: $primaryColor,
    light-mainBorderColor: #ffffff,
    light-contentActiveBgColor: $primaryColor,
    light-mainContentBgColor: #f0f2f5,
    light-mainCardBgColor: #ffffff,
    light-mainCardBorderColor: #f5f5f5,
    light-mainTextColor: #333333,
    light-mainActiveTextColor: #888888,
    light-popoverBgColor: #ffffff,
    light-popoverBorderColor: #f5f5f5,
    light-popoverTextColor: #333333
  );
}

虽然这样也有冗余的代码,但比起一个个定义class 这样还算可以的

再通过 @each指令生成class

代码语言:javascript
复制
@mixin theme($themeName: 'light') {
  @each $key, $value in $themeColorsMap {
    // 这里就是生成类似于:.dark.theme_color_blue
    // 因为我们还有切换主题色的功能,所以还得适配不同的颜色
    .#{$themeName}.#{$key} {
      @include mainLayout(
        $mainContentBgColor: map-get($map: $value, $key: #{$themeName}-mainContentBgColor), 
        $mainCardBgColor: map-get($map: $value, $key: #{$themeName}-mainCardBgColor),
        $mainCardBorderColor: map-get($map: $value, $key: #{$themeName}-mainBorderColor),
        $mainTextColor: map-get($map: $value, $key: #{$themeName}-mainTextColor),
        $mainActiveTextColor: map-get($map: $value, $key: #{$themeName}-mainActiveTextColor),

        $parent: $themeName,
      );
    }
  }
}

再看一下:mainLayout:

代码语言:javascript
复制
@mixin mainLayout(
  $mainContentBgColor: $mainContentBgColor,
  $mainCardBgColor: $mainCardBgColor,
  $mainCardBorderColor: $mainCardBorderColor,
  $mainTextColor: $mainTextColor,
  $mainActiveTextColor: $mainActiveTextColor,
  $parent: "light"
) {
  .vaw-main-layout-container {
    background-color: $mainContentBgColor;
    color: $mainTextColor;
  }
  .footer-container {
    background: $mainCardBgColor;
    border-top: 1px dashed #848484;
    color: $mainTextColor;
  }
  @if $parent == dark {
    .el-button {
      background: $mainContentBgColor;
      color: $mainTextColor;
    }
    .el-table {
      background-color: $mainCardBgColor;
      color: $mainTextColor;
      .hover-row {
        background-color: $mainCardBgColor !important;
      }
      th,
      tr {
        background-color: $mainCardBgColor !important;
      }
      th.is-leaf,
      td {
        border-bottom: 1px solid $mainTextColor;
      }
    }
    .el-table::before {
      display: block;
    }
    .el-table__body tr:hover > td {
      background-color: $mainContentBgColor !important;
    }

    .el-table__body tr.current-row > td {
      background-color: $mainContentBgColor !important;
    }

    .el-table__body tr.hover-row > td {
      background-color: $mainContentBgColor !important;
    }

    .el-message-box {
      background-color: $mainCardBgColor;
      .el-message-box__title {
        color: $mainActiveTextColor;
      }
      .el-message-box__content {
        color: $mainTextColor;
      }
    }
  }
}

通过上面的代码我们就实现了:

代码语言:javascript
复制
.dark{
  .xx1{}
  .xx2{}
  .xx3{}
}

这样的命名空间class,说了这么多就是为了生成这种样式的class。有点麻烦啊,但这样有一个好处是:我们以后再生成不同的主题就能生成 变量值就好了,不用写一个个class了。是不是很爽~~ 好了,文章太长了,但功能还没有完全实现,下一篇讲解如何实现动态换主题色。敬请期待~ 最后看一下效果图:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 知码前端 微信公众号,前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 详解在 vaw-layouts 中通过 sass 实现动态换肤功能 (一)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档