根据Css Variable的主题风格转换极致处理计划方案

2021-03-23 19:39 jianzhan

 

当收到这一要求的情况下,百度搜索到业内有关主题风格转换的计划方案还挺多的,css连接更换、className变更、less.modifyVars、css in js这些,但每一种计划方案听起來全是又累又贵。有木有那类编码入侵低,新手没脑子又好维护保养的计划方案呢?那当然是有的,准确的说成css它自身就适用。

Css3 Variable

界定一个全局性色调自变量,更改这一自变量的值网页页面内全部引入这一自变量的原素都是开展更改。好简易不是是?

// base.less
:root {
  --primary: green;
  --warning: yellow;
  --info: white;
  --danger: red;
}

// var.less
@primary: var(--primary)
@danger: var(--danger)
@info: var(--info)

// page.less
.header {
  background-color: @primary;
  color: @info;
}
.content {
  border: 1px solid @danger;
}
// change.js
function changeTheme(themeObj) {
  const vars = Object.keys(themeObj).map(key => `--${key}:${themeObj[key]}`).join(';')
  document.documentElement.setAttribute('style', vars)
}

文中完毕

个P,它不兼容 IE 啊!!0202年也要适配IE吗?是的,便是要适配IE。

 

css vars ponyfill

是的,还真有polyfill能适配IE: css-vars-ponyfill 。它拿下IE的方法大约是那样子的

+-------------------------+
|   获得网页页面内style标识內容  |
|     恳求外部链接css內容       |
+-------------------------+
  |
  |
  v
+-------------------------+  是   +-------------------------+
|      內容是不是带有var()    | ----> |        标识为src         |
+-------------------------+       +-------------------------+
  |                                 |
  | 否                              |
  v                                 v
+-------------------------+       +-------------------------+
|       标识为skip         |       |   将var(*)更换为自变量值,  |
|                         |       |  增加style标识加上到head  |
+-------------------------+       +-------------------------+

实际效果大约是这一模样的

 

简易粗鲁又无失雅致,在适用css var的访问器中不容易开展解决,因此不用担忧特性难题( 是IE的难题,并不是问提

)。 大家来更新改造一下编码

// store/theme.js
import cssVars from 'css-vars-ponyfill'

export default {
  state: {
    'primary': 'green',
    'danger': 'white'
  },
  mutations: {
    UPDATE_THEME(state, payload) {
      const variables = {}
      Object.assign(state, payload)
      Object.keys(state).forEach((key) => {
        variables[`--${key}`] = state[key]
      })
      cssVars({
        variables
      })
    }
  },
  actions: {
    changeTheme({ commit }, theme = {}) {
      commit('UPDATE_THEME', theme)
    }
  }
}

// router.js
// 由于路由器自动跳转后的网页页面会按需载入新的css資源,再次变换
const convertedPages = new Set()
router.afterEach((to) => {
  if (convertedPages.has(to.path)) return
  convertedPages.add(to.path)
  context.store.dispatch('theme/changeTheme')
})

SSR新项目闪屏难题提升

在SSR新项目选用所述计划方案你可以能会在IE看出到那样的状况

 

由于 css-vars-ponyfill

是依靠dom原素来完成变换的,在node中没法应用,因此从server直出未变换的css编码到client载入js文档变换css间存有一段款式空档。

+- - - - - - - - - - - - - - - - - - - -+
                 ' 款式空窗期:                             '
                 '                                       '
+----------+     ' +----------------+     +------------+ '     +-------------+
| 进行恳求  | --> ' |  SSR直出网页页面     | --> | 载入js依靠  | ' --> |  更换css自变量 |
+----------+     ' +----------------+     +------------+ '     +-------------+
                 '                                       '
                 +- - - - - - - - - - - - - - - - - - - -+

处理这一难题也非常简单,只必须在每一个采用 css var 的地区再加一个适配书写

@_primary: red
@primary: var(--primary)

:root{
  --primary: @_primary
}

.theme {
  color: @primary;
}

// 改成
.theme {
  color: @_primary;
  color: @primary;
}

不在适用css var的访问器上面3D渲染默认设置色调 red ,等候js载入结束后ponyfill更换款式遮盖。

Webpack软件开发设计

手动式在每一个采用的地区加上适配书写既幸苦又不太好维护保养,这一情况下大家必须掌握一些 webpack 性命周期时间及其软件开发设计有关的专业知识,大家能够根据笔写一个webpack软件,在 normalModuleLoader ( v5版本号被废料,应用NormalModule.getCompilationHooks(compilation).loader )的hooks中为全部css module加上一个loader来解决适配编码。

小编新项目应用了less,留意webpack中loader实行次序是 相近栈的优秀后出 ,因此我必须把变换loader加上到less-loader以前,保证大家解决的是编译程序后的css var书写并非less自变量。

// plugin.js
export default class HackCss {
  constructor (theme = {}) {
    this.themeVars = theme
  }

  apply(compiler) {
        compiler.hooks.thisCompilation.tap('HackCss', (compilation) => {
          compilation.hooks.normalModuleLoader.tap(
            'HackCss',
            (_, moduleContext) => {
              if (/\.vue\?vue&type=style/.test(moduleContext.userRequest)) {
                // ssr新项目同构会出现两次compiler,假如module中存有loader则不再次加上
                if (hasLoader(moduleContext.loaders, 'hackcss-loader.js')) {
                  return
                }

                let lessLoaderIndex = 0
                // 新项目用了less,寻找less-loader的部位
                moduleContext.loaders.forEach((loader, index) => {
                  if (/less-loader/.test(loader.loader)) {
                    lessLoaderIndex = index
                  }
                })
  
                moduleContext.loaders.splice(lessLoaderIndex, 0, {
                  loader: path.resolve(__dirname, 'hackcss-loader.js'),
                  options: this.themeVars
                })
              }
            }
          )
        })
      }
    })
}

// loader.js
const { getOptions } = require('loader-utils')

module.exports = function(source) {
  if (/module\.exports/.test(source)) return source
  const theme = getOptions(this) || {}
  return source.replace(
    /\n(.+)?var\(--(.+)?\)(.+)?;/g,
    (content, before, name, after = '') => {
      const [key, indent] = before.split(':')
      const add = after.split(';')[0]
      return `\n${key}:${indent}${theme[name]}${after}${add};${content}`
    }
  )
}

到此,大家能够开心轻松的转换主题风格了。

 

续篇

根据怎样“懒得写大量编码”来消化吸收新专业知识会更为趣味, 期待本文可以协助到你。

到此这篇有关根据Css Variable的主题风格转换极致处理计划方案(强烈推荐)的文章内容就详细介绍到这了,大量有关css Variable的主题风格转换內容请检索脚本制作之家之前的文章内容或再次访问下边的有关文章内容,期待大伙儿之后多多的适用脚本制作之家!