vue ---- 仿ElementUI自定义换肤,更换主题

网站更换皮肤,有如下三种思路供参考:

  1. 预定义几套已经写好的样式文件,如下。然后动态切换选中的主题对应的css文件。
    在这里插入图片描述

  2. 在根元素上定义一个用来设置主题的class,然后动态更换该class,以达到切换主题的目的。

  3. 以上两种方式都可以轻易达到切换主题的目的,但是有一个限制,就是我们只能有定义好的这几种主题可以切换。
    今天我们来介绍一种新的更换主题的方式:
    优点: 该方式能够通过拾色器选择自己喜欢的主题色,并根据这个选择的主题色自由生成我们想要的主题。
    思路: 根据拾色器选择的颜色,配合一定的算法,动态生成一套主题样式,并将生成的样式插入到DOM中,作为全局样式。

步骤:

1. 新建主题定义组件theme-picker.vue, 代码如下:

注意:

  1. 设计中将主题样式文件写入在**<script type=‘text/template’ id=“themeColorInfo”>**中,目的有两点:
    1. 可以像在style标签中写样式一样,结构清晰且便于维护。
    2. 可以完美与{{theme}}数据模板结合使用。
    3. 不会再Dom中显示,且可以很容易获取其中的样式内容。
  2. 由于是动态获取<script type=‘text/template’ id=“themeColorInfo”>中的样式,而vue中的DOM更新是异步的,所以获取最终生成的主题样式的calTheme函数需要在nextTick中执行才有效。
  3. 主题颜色存入本地,进行持久化。主题色优先获取本地已选择的主题色,默认主题色次之。
<template>
  <div>
    <input type="color" id='selectTheme' v-model="theme">
    <script type='text/template' id="themeColorInfo">
      .theme-color {
        color: {{theme}}
      }
      .theme-bg {
        background-color: {{theme}}
      }
      a {
        color: {{theme}};
        text-decoration: none;
      }
      a:hover {
        color: white;
        background-color: {{theme}}
      }
    </script>
  </div>
</template>

<script>
export default {
  data () {
    return {
      theme: ''
    }
  },
  props: {
    themeColor: { // 默认主题颜色
      type: String,
      default: '#000000'
    }
  },
  created () {
    // 优先获取本地已选择的主题色,默认主题色次之。
    let themeColor = localStorage.getItem('themeColor')
    this.theme = themeColor || this.themeColor
  },
  mounted () {
    this.$nextTick(() => {
      this.calTheme()
    })
  },
  watch: {
    theme (val, oldVal) {
      // 已选择的主题颜色存入本地,持久化。
      localStorage.setItem('themeColor', this.theme)
      this.$nextTick(() => {
        this.calTheme()
      })
    }
  },
  methods: {
    /** 
     * 因为calTheme函数需要根据theme的值,动态获取<script type='text/template' id="themeColorInfo">中的样式文件
     *而vue中的DOM更新是异步的,所以calTheme函数需要在nextTick中执行才有效
    */
    calTheme () {
      let colorStr = document.getElementById('themeColorInfo').innerHTML
      let colorPickerStyle = document.getElementById('color-picker-style')
      // 判断是否存在主题样式的style标签
      // 如果存在则替换最新的样式信息,否则新建一个style标签并插入新的主题样式信息
      if (colorPickerStyle) {
        colorPickerStyle.innerHTML = colorStr
      } else {
        let oStyle = document.createElement('style')
        oStyle.id = 'color-picker-style'
        oStyle.innerHTML = colorStr
        document.body.appendChild(oStyle)
      }
    }
  }
}
</script>

2. 在网站中任意一个组件引入theme-picker.vue, 切换主题即可看到效果。

<template>
  <div class="page-wrap theme-color">
    <header class="theme-bg">
      <h2>页面头部</h2>
      <themePicker></themePicker>
    </header>
    <section class="page-content">
      <div><a href="#">样式一</a></div>
      <div><a href="#">样式二</a></div>
      <div><a href="#">样式三</a></div>
      <div><a href="#">样式四</a></div>
    </section>
  </div>
</template>

<script>
import themePicker from './theme-picker/themePicker.vue'
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  components: {
    themePicker
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="less" scoped>
.page-wrap{
  padding-top: 60px;
  header {
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    height: 60px;
    color: white;
  }
  .page-content {
    display: flex;
    flex-direction: row;
    justify-content: center;
    div {
      width: 200px;
      height: 240px;
      margin: 10px;
      border: 1px solid #eee;
      position: relative;
      a{
        position: absolute;
        bottom: 0;
        left: 0;
        width: 100%;
        height: 32px;
        line-height: 32px;
      }
    }
  }![在这里插入图片描述](https://img-blog.csdnimg.cn/20190712221556383.gif)
}
</style>

效果:
在这里插入图片描述

这只是换皮肤的一种实现思路,实现的方式当然不止一种,如果有更好的实现方式,欢迎大家分享和指正。
文中这只是一个简单的例子,旨在分享一种实现方式。具体实现时,我们也可以配合一定的算法,根据所选择的颜色,生成一套多色或者更复杂更贴合具体业务的主题样式。

发布了27 篇原创文章 · 获赞 4 · 访问量 6282

猜你喜欢

转载自blog.csdn.net/studentenglish/article/details/95403454