总有一个功能,你会用的到!
接上篇文章:vue项目干货
源码地址css
建立lineChart组件,折线图表
代码以下:vue
<template> <div :id="srcData.id" class="warnCount"></div> </template> <script> import echarts from 'echarts'; import resize from '../resize' //用于可视区域改变时resize export default { name: "chart", mixins: [resize], data() { return { chartColumn: null, scale: 1, } }, props: { srcData: Object, //数据 isGetData: Boolean //获取好数据 能够开始绘制标记 }, watch: { isGetData(val) { this.drawChart(); } }, methods: { drawChart() { let me=this; setTimeout(() => { let me = this; this.chartColumn.clear(); this.chartColumn.setOption({ tooltip: { trigger: 'axis', confine: true }, yAxis: { name: '得分', type: 'value', axisLine: { lineStyle: { color: '#72aafa' }, }, splitLine: { show:false, lineStyle: { color: '#154d5a', width: 0.5 } }, }, xAxis :{ type: 'time', splitLine: { show: false, lineStyle: { color: '#72aafa', } }, axisLine: { lineStyle: { color: '#72aafa' } }, }, grid:{ top:'15%', right:'10%', left:'10%', bottom:'15%' }, series:this.srcData.sData }) }, 0); } }, created() { var me = this; }, updated() { }, mounted() { let charDom = document.getElementById(this.srcData.id), me = this; charDom.style.height = this.srcData.height + "px"; this.scale = window.innerWidth / 1920; this.chartColumn = echarts.init(charDom); this.chartColumn.on('click', function (params) { me.$emit('click', params); }) }, beforeDestroy() { if (this.chartColumn) { this.chartColumn.clear() } }, destroy() { if (this.chartColumn) { this.chartColumn.dispose() this.chartColumn = null; } }, components: {} } </script> <style scoped lang="scss"> .warnCount { width: 100%; height: 350px; } </style>
接下来开始使用该组件:
传值:git
warnCountTrendData: { id: 'warnCountTrend', height: 350, sData:[ { name:'竞逐对', symbol:'circle', symbolSize:6, type:'line', lineStyle:{ width:1 }, data:[ {value:["2020-01-01 00:00:00",0]}, {value:["2020-01-02 00:00:00",0]}, {value:["2020-01-04 01:01:01",200]}, {value:["2020-01-07 01:01:01",200]} ] }, { name:'竞逐对1', symbol:'circle', symbolSize:6, type:'line', lineStyle:{ width:1 }, data:[ {value:["2020-01-02 00:00:00",0]}, {value:["2020-01-06 04:01:00",100]}, {value:["2020-01-07 01:01:01",200]} ] } ] }
当窗口改变时window.onresize能够被监听到,但当导航栏收起时监听不到,此项目的解决方案是安装:element-resize-detector
resize.js文件:github
import {debounce} from '../common/util'; import elementResizeDetectorMaker from 'element-resize-detector' export default { data() { return { $_sidebarElm: null } }, mounted() { let me=this; this.__resizeHandler = debounce(() => { if (this.chartColumn) { this.chartColumn.resize() } }, 100) window.addEventListener('resize', this.__resizeHandler); const erd = elementResizeDetectorMaker() erd.listenTo(document.getElementsByClassName("contentBox"),(element)=>{ me.$nextTick(()=>{ me.resize() }) }) }, beforeDestroy() { window.removeEventListener('resize', this.__resizeHandler); }, methods: { resize() { this.__resizeHandler() } } }
debounce为函数防抖方法:web
export const debounce = (func, wait, immediate) => { let timeout, args, context, timestamp, result const later = function () { // 据上一次触发时间间隔 const last = +new Date() - timestamp // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait if (last < wait && last > 0) { timeout = setTimeout(later, wait - last) } else { timeout = null // 若是设定为immediate===true,由于开始边界已经调用过了此处无需调用 if (!immediate) { result = func.apply(context, args) if (!timeout) context = args = null } } } return function (...args) { context = this timestamp = +new Date() const callNow = immediate && !timeout // 若是延时不存在,从新设定延时 if (!timeout) timeout = setTimeout(later, wait) if (callNow) { result = func.apply(context, args) context = args = null } return result } }
实现效果:segmentfault
经过drawer控制抽屉展现隐藏浏览器
<el-button @click="showDrawer" type="primary" class='showBtn' :style='sty'> <i class='iconfont iconshezhi' v-if='!drawer'></i> <i class='iconfont iconguanbi' v-else></i> </el-button> <el-drawer :visible.sync="drawer" direction="rtl" style='position:absolute' @close='onClose'> <span class='drawTitle'>设置</span> <div style='margin:0 auto;width:100%;'> <el-form ref="form" label-width="80px"> <el-form-item label="选择主题"> <el-select v-model="value" placeholder="请选择" @change='changeColor'> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-form-item> </el-form> </div> </el-drawer>
再来控制控制按钮的样式:sass
.showBtn { position:absolute; top:50%; transform :translateY(-50%); z-index:100000; transition: right .3s; padding:10px!important; i { font-size:20px; } } .drawTitle { position: absolute; top: 4%; left: 5%; font-weight: 700; color: #666; font-size: 17px; }
方法逻辑:session
showDrawer:function(){ let me=this; me.drawer = !me.drawer; me.value=sessionStorage.getItem('theme'); me.sty.right=me.drawer?'30%':'0' //按钮位置 }, onClose:function(){ let me=this; me.sty.right='0' }
实现效果:app
增长以下两个文件(需安装sass)
mixin.scss
@mixin get-theme-value($type, $value, $css-key, $css-value) { @each $themename , $theme in $themes { [data-theme = '#{$themename}'] & { $_type: map-get($theme, $type); #{$css-key}: #{$css-value} map-get($_type , $value ); } } } @mixin get-color-value($type, $value) { @each $themename , $theme in $themes { [data-theme = '#{$themename}'] & { $_type: map-get($theme, $type); #{$type}-color: map-get($_type , $value ); } } } @mixin background($color){ @include get-theme-value('background', $color, 'background', ''); } @mixin background-color($color){ @include get-color-value('background', $color); } @mixin font-color($color) { @include get-theme-value('font', $color, 'color', ''); } @mixin border-color($color) { @include get-color-value('border', $color); } @mixin border($color, $css-key:'border', $css-value:'1px solid') { @include get-theme-value('border', $color, $css-key , $css-value) } @mixin box-shadow($color, $css-value) { @include get-theme-value('boxShadow', $color, 'box-shadow', $css-value) } @mixin common-link-font($size: 1.2) { font-size: #{$size}rem; font-weight: 600; &:hover, &.selected{ @include font-color('color4'); } @include font-color('color1'); } @mixin common-font($size: 1.2, $font-weight: 400) { font-size: #{$size}rem; font-weight: $font-weight; @include font-color('color1'); } @mixin flex($justify: flex-start, $align-items: center, $dir: row, $wrap: nowrap, $align-content: stretch) { display: flex; flex-flow: $dir $wrap; justify-content: $justify; align-items: $align-items; align-content: $align-content; }
theme.css 定义两套主题
@import './mixin.scss'; // default theme $default-theme : ( font: ( color1: #16284c, ), border: ( color1: #16284c, ), background: ( color1: #16284c, ), boxShadow: ( color1: rgba(0,0,0,.3) ) ); //红色主题 $red-theme : ( font: ( color1: red ), border: ( color1: red ), background: ( color1: red ), boxShadow: ( color1: rgba(0,0,0,.3) ) ); $themes: ( default-theme: $default-theme, red-theme: $red-theme );
App.vue
<template> <div id="app"> <transition name="fade" mode="out-in"> <router-view></router-view> </transition> </div> </template> <script> export default { name: 'app', data(){ return { getNowThemeInfo:'' //初始主题 } }, mounted() { let me=this; me.getNowThemeInfo=sessionStorage.getItem('theme'); me.setBodyTheme(); }, methods: { setBodyTheme() { document.body.dataset.theme = this.getNowThemeInfo; } }, components: {} } </script> <style lang="scss"> body { margin: 0px; padding: 0px; /*background: url(assets/bg1.jpg) center !important; background-size: cover;*/ // background: #1F2D3D; font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif; font-size: 14px; -webkit-font-smoothing: antialiased; } #app { position: absolute; top: 0px; bottom: 0px; width: 100%; } .el-submenu [class^=fa] { vertical-align: baseline; margin-right: 10px; } .el-menu-item [class^=fa] { vertical-align: baseline; margin-right: 10px; } .toolbar { background: #f2f2f2; padding: 10px; //border:1px solid #dfe6ec; margin: 10px 0px; .el-form-item { margin-bottom: 10px; } } .fade-enter-active, .fade-leave-active { transition: all .2s ease; } .fade-enter, .fade-leave-active { opacity: 0; } </style>
当某个元素的颜色信息须要随主题改变时,须要这样定义颜色信息
你会发现浏览器中样式使这样写的
基本换肤功能就实现了,下面介绍下如何切换(此项目将主题信息存储在session中)
main.js中增长以下方法,监听session
Vue.prototype.resetSetItem = function (key, newVal) { if (key =='theme') { // 建立一个StorageEvent事件 var newStorageEvent = document.createEvent('StorageEvent'); const storage = { setItem: function (k, val) { sessionStorage.setItem(k, val); // 初始化建立的事件 newStorageEvent.initStorageEvent('setItem', false, false, k, null, val, null, null); // 派发对象 window.dispatchEvent(newStorageEvent) } } return storage.setItem(key, newVal); } }
在app.vue中监听变化
window.addEventListener('setItem', ()=> { var val = sessionStorage.getItem('theme'); console.log(val); this.getNowThemeInfo=sessionStorage.getItem('theme'); this.setBodyTheme(); })
在改变主题信息时记得存session里theme
录屏工具打不开了...效果先看项目吧
将不断更新完善,期待您的批评指正!