總有一個功能,你會用的到!
接上篇文章: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
錄屏工具打不開了...效果先看項目吧
將不斷更新完善,期待您的批評指正!