17.vue自定义主题颜色皮肤

17.vue 自定义主题

1.安装需要的相关依赖

npm i element-theme -g
npm i element-theme-chalk -D

2.初始化变量文件

 et -i

项目根目录下生成

打卡此文件
修改变量

编译主题

et

3.引入主题

main.js中引入

import Vue from 'vue'import App from './App.vue'import router from './router'import store from './store'// 导入字体图标库import './assets/fonts/iconfont.css'import './plugins/element.js'import 'element-ui/lib/theme-chalk/index.css'import '../theme/index.css'import ElementUI from 'element-ui'// 导入全局样式表import './assets/scss/global.scss'// 导入全局接口入口文件import api from './api/index'// 导入国际化i18nimport VueI18n from 'vue-i18n'// 导入全局mockimport './mock'Vue.config.productionTip = falseVue.use(VueI18n) // 通过插件的形式挂载Vue.use(ElementUI)const i18n = new VueI18n({  locale: 'zh-CN', // 语言标识  // this.$i18n.locale // 通过切换locale的值来实现语言切换  messages: {    'zh-CN': require('./assets/lang/zh'), // 中文语言包    'en-US': require('./assets/lang/en') // 英文语言包  }})// 将导入的接口文件全局挂载在vue全局上Vue.prototype.$api = apinew Vue({  i18n,  router,  store,  render: h => h(App)}).$mount('#app')

4.封装动态换肤色ThemePicker.vue组件

参考大神:
博客园:https://www.cnblogs.com/dengqichang/p/10364455.html
大神的博客地址

  • ThemePicker.vue内容
<template>  <el-color-picker class="theme-picker" popper-class="theme-picker-dropdown" v-model="theme" :size="size"> </el-color-picker></template><script>const version = require('element-ui/package.json').version // element-ui version from node_modulesconst ORIGINAL_THEME = '#409EFF' // default colorexport default {  name: 'ThemePicker',  props: {    default: {      // 初始化主题,可由外部传入      type: String,      // default: '#EB815B'      default: ''   localStorage.getItem('tremePackers')   ''    },    size: {      // 初始化主题,可由外部传入      type: String,      default: 'small'    }  },  data() {    return {      chalk: '', // content of theme-chalk css      theme: ORIGINAL_THEME,      showSuccess: true // 是否弹出换肤成功消息    }  },  mounted() {    if (this.default != null) {      this.theme = this.default      this.$emit('onThemeChange', this.theme)      this.showSuccess = false    }  },  watch: {    theme(val, oldVal) {      if (typeof val !== 'string') return      const themeCluster = this.getThemeCluster(val.replace('#', ''))      const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))      const getHandler = (variable, id) => {        return () => {          const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))          const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)          let styleTag = document.getElementById(id)          if (!styleTag) {            styleTag = document.createElement('style')            styleTag.setAttribute('id', id)            document.head.appendChild(styleTag)          }          styleTag.innerText = newStyle        }      }      const chalkHandler = getHandler('chalk', 'chalk-style')      if (!this.chalk) {        const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`        this.getCSSString(url, chalkHandler, 'chalk')      } else {        chalkHandler()      }      const styles = [].slice.call(document.querySelectorAll('style')).filter(style => {        const text = style.innerText        return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)      })      styles.forEach(style => {        const { innerText } = style        if (typeof innerText !== 'string') return        style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)      })      // 响应外部操作      this.$emit('onThemeChange', val)      // 存入localStorage      localStorage.setItem('tremePackers', val)      if (this.showSuccess) {        this.$notify.success({          title: this.$t('lang.tip'),          message: this.$t('lang.optSuccess')        })      } else {        this.showSuccess = true      }    }  },  methods: {    updateStyle(style, oldCluster, newCluster) {      let newStyle = style      oldCluster.forEach((color, index) => {        newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])      })      return newStyle    },    getCSSString(url, callback, variable) {      const xhr = new XMLHttpRequest()      xhr.onreadystatechange = () => {        if (xhr.readyState === 4 && xhr.status === 200) {          this[variable] = xhr.responseText.replace(/@font-face{[^}] }/, '')          callback()        }      }      xhr.open('GET', url)      xhr.send()    },    getThemeCluster(theme) {      const tintColor = (color, tint) => {        let red = parseInt(color.slice(0, 2), 16)        let green = parseInt(color.slice(2, 4), 16)        let blue = parseInt(color.slice(4, 6), 16)        if (tint === 0) {          // when primary color is in its rgb space          return [red, green, blue].join(',')        } else {          red  = Math.round(tint * (255 - red))          green  = Math.round(tint * (255 - green))          blue  = Math.round(tint * (255 - blue))          red = red.toString(16)          green = green.toString(16)          blue = blue.toString(16)          return `#${red}${green}${blue}`        }      }      const shadeColor = (color, shade) => {        let red = parseInt(color.slice(0, 2), 16)        let green = parseInt(color.slice(2, 4), 16)        let blue = parseInt(color.slice(4, 6), 16)        red = Math.round((1 - shade) * red)        green = Math.round((1 - shade) * green)        blue = Math.round((1 - shade) * blue)        red = red.toString(16)        green = green.toString(16)        blue = blue.toString(16)        return `#${red}${green}${blue}`      }      const clusters = [theme]      for (let i = 0; i <= 9; i  ) {        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))      }      clusters.push(shadeColor(theme, 0.1))      return clusters    }  }}</script><style>.theme-picker .el-color-picker__trigger {  vertical-align: middle;}.theme-picker-dropdown .el-color-dropdown__link-btn {  display: none;}</style>

5.导入组件

<template>  <header>    <!-- 头部左侧导航折叠按钮 -->    <div>      <i class="el-icon-s-fold" v-show="!isCollapse" @click="collapseMenu"></i>      <i class="el-icon-s-unfold" v-show="isCollapse" @click="collapseMenu"></i>    </div>    <!-- 右侧工具栏部分 -->    <div class="opt-wrapper">      <!-- 主题选择 -->      <div class="theme-picker">        <theme-picker></theme-picker>      </div>      <!-- 语言切换 -->      <div class="lang">        <el-dropdown :hide-on-click="false" @command="changeLang">          <span class="el-dropdown-link">{{ lang }}<i class="el-icon-arrow-down el-icon--right"></i></span>          <el-dropdown-menu slot="dropdown">            <el-dropdown-item command="zh-CN">{{ $t('lang.chinese') }}</el-dropdown-item>            <el-dropdown-item command="en-US">{{ $t('lang.engLish') }}</el-dropdown-item>          </el-dropdown-menu>        </el-dropdown>      </div>      <!-- 是否全屏 -->      <div class="fullScreen">        <i class="iconfont icon-caozuo-quanping-shousuo" v-show="isFullscreen" @click="screen"></i>        <i class="iconfont icon-icon-GIS_quanping" v-show="!isFullscreen" @click="screen"></i>      </div>      <!-- 用户信息、退出登录 -->      <div>        <el-dropdown :hide-on-click="false" @command="handleCommand">          <span class="el-dropdown-link"> <img :src="avatar" alt="" class="avatar"/></span>          <el-dropdown-menu slot="dropdown">            <el-dropdown-item command="userinfo"><i class="el-icon-info"></i>{{ $t('lang.personal') }}</el-dropdown-item>            <el-dropdown-item command="logout"><i class="el-icon-switch-button"></i>{{ $t('lang.logout') }}</el-dropdown-item>          </el-dropdown-menu>        </el-dropdown>      </div>    </div>  </header></template><script>// 导入选择主题组件import ThemePicker from '@/components/ThemePicker/ThemePicker'import { mapState } from 'vuex'import screenfull from 'screenfull'export default {  components: {    ThemePicker  },  data() {    return {      isFullscreen: false, // 是否是全屏      avatar: require('@/assets/images/admin-logo.jpg')    }  },  computed: {    ...mapState({      isCollapse: state => state.tab.isCollapse,      lang: state => state.header.lang    })  },  created() {    // 获取刷新之前的语言信息    const sessionLang = JSON.parse(sessionStorage.getItem('currentLang'))    console.log(sessionLang)    if (sessionLang !== null) {      // 获取到存储的路由列表之后,将信息利用vuex进行存储      if (sessionLang.currentLang === 'EngLish') {        this.$i18n.locale = 'en-US'        this.$store.commit('changeLang', 'en-US')      }      if (sessionLang.currentLang === '中文') {        this.$i18n.locale = 'zh-CN'        this.$store.commit('changeLang', 'zh-CN')      }    }  },  mounted() {    // 刷新之前存储当前语言信息    window.addEventListener('beforeunload', e => {      sessionStorage.setItem(        'currentLang',        JSON.stringify({          currentLang: this.lang        })      )    })  },  methods: {    // 退出方法    handleCommand(command) {      if (command === 'logout') {        sessionStorage.clear()        sessionStorage.removeItem('tabs')        this.$router.push('/login')        window.location.reload()      }      if (command === 'userinfo') {        this.$router.push('/userinfo')        const userinfo = {          path: '/userinfo',          name: 'userinfo',          label: '个人信息',          icon: 'info'        }        this.$store.commit('selectMenu', userinfo)      }      this.$message.success('click on item '   command)    },    // 控制左侧导航栏开启/关闭事件    collapseMenu() {      this.$store.commit('collapseMenu')    },    // 切换语言    changeLang(command) {      if (command === 'zh-CN') {        this.$i18n.locale = 'zh-CN'      }      if (command === 'en-US') {        this.$i18n.locale = 'en-US'      }      this.$store.commit('changeLang', command)    },    // 控制是否是全屏还是非全屏    screen() {      // 如果不允许进入全屏,发出不允许提示      // if (!screenfull.enabled) {      //   this.$message('您的浏览器不能全屏')      //   return false      // }      screenfull.toggle()      this.isFullscreen = !screenfull.isFullscreen      // console.log(screenfull.isFullscreen)      // this.$message.success('全屏啦')    }  }}</script><style lang="scss" scoped>@import '~@/assets/scss/common/header.scss';</style>

6.效果演示

来源:https://www.icode9.com/content-4-770051.html

(0)

相关推荐