Node.js 10.13.0
NPM 6.10.3
Vue 2.5.2
vue-router 3.0.1
element-ui 2.11.1
element-theme-chalk 2.11.1 # `npm install element-theme-chalk --save-dev`
webpack-theme-color-replacer 1.2.17 # `npm install webpack-theme-color-replacer --save-dev`
2.1、【ElementUI主题修改】原理:通过官网下载几个主题到本地,然后修改主题名(注意与本地文件名一致),然后动态将页面样式通过link标签引入
【下载了三个主题,分别命名为default、green、orange】,放在static目录下
【封装定义包含ElementUI组件名的数组文件themeArray.js】
//主题文件数组 const themeArray = [ "Pagination", "Dialog", "Autocomplete", "Dropdown", "dropdown-menu", "dropdown-item", "Menu", "Submenu", "menu-item", "menu-item-group", "Input", "input-number", "Radio", "radio-group", "radio-button", "Checkbox", "checkbox-group", "Switch", "Select", "Option", "option-group", "Button", "button-group", "Table", "table-column", "date-picker", "time-select", "time-picker", "Popover", "Tooltip", "Breadcrumb", "breadcrumb-item", "Form", "form-item", "Tabs", "tab-pane", "Tag", "Tree", "Alert", "Slider", "Icon", "Row", "Col", "Upload", "Progress", "Spinner", "Badge", "Card", "Rate", "Steps", "Step", "Carousel", "Scrollbar", "carousel-item", "Collapse", "collapse-item", "Cascader", "color-picker", "Loading", "message-box", "Message" ] export default themeArray
【封装改变主题的changeTheme.js文件,根据主题名,手动添加link标签到Dom元素中】
2.2、【自定义样式修改】需要设置主组件的data属性,在入口文件APP.vue中,写上属性"data-theme",初始值存储在vuex的store中(通过改变data-theme的属性值,改变自定义样式的值,如菜单、顶部导航栏、部分文字颜色等)
【当前data-theme的值有:'default-theme'、'green-theme'、'orange-theme'】
2.3、【Vuex存储"data-theme"属性值】存储在store对应的文件中,主要变量值:主题属性名"nowThemeInfo",修改变量的函数"setThemeInfo",比如nowThemeInfo属性值从"default-theme"变成"green-theme"(即通过修改nowThemeInfo属性值,控制App.vue组件的data-theme属性值)
2.4、【自定义样式文件】首先新建一个theme.scss文件,里面存放三种主题颜色值,通过定义变量,如$default-theme默认主题名,和自定义修改的函数,如base-color文本hover时的效果,其中结合sass提供Sass Maps的语句、定义变量、获取Map的值、循环Map生成类等,即遍历对应主题下的样式,参考此处
2.5、【引入到需要的组件中】在需要样式修改的组件中,对应样式处,引入指定map函数即可
2.6、【重点:修改主题的组件】此处是通过单选框进行修改(changeRadio函数),注意computed属性中,引入store的"nowThemeInfo"属性,就不用在data()中return,其中参考mapGetters辅助函数
传值给上述函数中,参数必须与本地文件夹名字相同!!定义属性themeArr:包含所有主题的数组;属性nowTheme:当前主题值
【methods属性中的初始化initRadio函数】
【控制台打印如下】
【methods属性中的改变颜色的changeRadio函数】选择对应的单选框之后,修改主题颜色
3.1、【当打包时npm run build】报一下错误 (node:7852) UnhandledPromiseRejectionWarning: CssSyntaxError:xxxx.Unknown word
3.2、【解决方法】注释build目录下,webpack.prod.conf.js文件中的以下代码
【因为,需要判断是测试环境还是生产(打包之后)的环境】
所以先安装 `cross-env`
npm install cross-env --save-dev
然后重新配置package.json文件
3.3、【又遇到问题啦】生产环境下,切换主题时,报错`Uncaught RangeError: Maximum call stack size exceeded`
【是的,修改removeChildNode函数】
【下面查看生产环境下的效果】
3.4、【又㕛遇到新问题啦】哈哈哈,就是换肤成功,但ELementUI组件主题刷新就失效,所以需要获取当前主题属性值(存储在localStorage),再设置当前的主题样式(调用changeTheme函数)
【因为刷新,每次会先加载main.js文件,所以引入初始化主题函数initThemeColor】
【文件themeColorClient.js,中的函数initThemeColor如下】getStore函数封装过
【changeTheme函数中,每次修改时,存储当前主题值到localStorage中】setStore函数封装过
【setStore、getStore函数如下】
3.5、【又㕛叒遇到问题啦】其他组件作为当前页时,换肤没有任何问题;但是!!首页换肤,会出现只有首页子组件,菜单和顶部导航栏都不在啦,嘤嘤嘤,哭死我了,当然找错啦,后来隐隐约约感觉是Breadcrumb 面包屑组件的问题,因为除了首页,其他前面都是有父组件的名字的,确实是面包屑组件的问题哎!!
【首页换肤效果如下】
【查找原因哈】面包屑的原理,通过获取this.$route.matched的值,进行对面包屑的渲染,所以赋值问题,这里应该将浅拷贝换成深拷贝(浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。)
【对比】即首页,只有子组件的名字,没有父组件的名字
【控制台打印如下】
3.6、【项目标题根据组件名变化】创建配置文件,在main.js入口文件中,结合全局守卫,动态修改网页标题
【配置文件】
【main.js入口文件】
总结:
1、实现指定颜色的主题,结合ElementUI官网,下载自己需要的几个主题包
2、根据对应的主题,自定义的修改根据主题变动的组件,如菜单、顶部导航栏、部分文字颜色等
3、自定义的样式,是结合sass提供Sass Maps的语句、定义变量、获取Map的值、循环Map生成类等,即遍历对应主题下的样式
4、需要修改的主题名,存储在Vuex中;然后自定义样式则根据主题名的变化,修改App.vue组件的data属性值;而ElementUI组件的主题修改,根据主题名的变化,动态引入link标签
5、具体代码开源到github中,欢迎star
6、写给自己的随笔,有问题欢迎指出ψ(*`ー´)ψ