• vue-element-admin分析


    观摩一下开源项目vue-element-admin的源码,来看看花裤衩大神是如何优雅的写代码,如何封装业务组件的,顺便如果能在自己的项目中应用想必也是极好的

    首先拉取代码然后在本地运行

    下载依赖的时候遇到报错

    解决

    echarts

    代码运行后第一眼就看见我前些天研究的图表,刚好项目是用的echarts,趁着还有些印象,先来研究一下Vue-element-admin是如何在项目中使用echarts的

     看了几个图表后就得折线图比较符合我的思路就以折线图为例

    src/views/dashboard/admin/components/LineChart.vue

    先把代码复制下来逐行分析

    1. <template>
    2. <div
    3. :class="className"
    4. :style="{height:height,width:width}"
    5. />
    6. template>
    7. <script>
    8. //导入echarts 好像不是按需导入
    9. import echarts from 'echarts'
    10. require('echarts/theme/macarons') // echarts theme
    11. import resize from './mixins/resize' //应该是封装的resize函数等下再看
    12. export default {
    13. mixins: [resize],//通过混合使用
    14. props: {
    15. //图表样式
    16. className: {
    17. type: String,
    18. default: 'chart'
    19. },
    20. width: {
    21. type: String,
    22. default: '100%'
    23. },
    24. height: {
    25. type: String,
    26. default: '350px'
    27. },
    28. //不知道啥用 false 和true好像没区别
    29. autoResize: {
    30. type: Boolean,
    31. default: true
    32. },
    33. //接收图表数据
    34. chartData: {
    35. type: Object,
    36. required: true
    37. }
    38. },
    39. data () {
    40. return {
    41. chart: null
    42. }
    43. },
    44. //监听数据变化 如果发生改变就重新渲染图表
    45. watch: {
    46. chartData: {
    47. deep: true,
    48. handler (val) {
    49. this.setOptions(val)
    50. }
    51. }
    52. },
    53. //创建图表
    54. mounted () {
    55. this.$nextTick(() => {
    56. this.initChart()
    57. })
    58. },
    59. // 销毁图表实例
    60. beforeDestroy () {
    61. if (!this.chart) {
    62. return
    63. }
    64. this.chart.dispose()
    65. this.chart = null
    66. },
    67. methods: {
    68. // 初始化图表实例
    69. initChart () {
    70. //vm.$el获取Vue实例关联的DOM元素;
    71. this.chart = echarts.init(this.$el, 'macarons')
    72. this.setOptions(this.chartData)
    73. },
    74. // 接收图表数据进行渲染
    75. setOptions ({ expectedData, actualData } = {}) {
    76. this.chart.setOption({
    77. xAxis: {
    78. data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
    79. boundaryGap: false,
    80. axisTick: {
    81. show: false
    82. }
    83. },
    84. grid: {
    85. left: 10,
    86. right: 10,
    87. bottom: 20,
    88. top: 30,
    89. containLabel: true
    90. },
    91. tooltip: {
    92. trigger: 'axis',
    93. axisPointer: {
    94. type: 'cross'
    95. },
    96. padding: [5, 10]
    97. },
    98. yAxis: {
    99. axisTick: {
    100. show: false
    101. }
    102. },
    103. legend: {
    104. data: ['expected', 'actual']
    105. },
    106. series: [{
    107. name: 'expected', itemStyle: {
    108. normal: {
    109. color: '#FF005A',
    110. lineStyle: {
    111. color: '#FF005A',
    112. width: 2
    113. }
    114. }
    115. },
    116. smooth: true,
    117. type: 'line',
    118. data: expectedData,
    119. animationDuration: 2800,
    120. animationEasing: 'cubicInOut'
    121. },
    122. {
    123. name: 'actual',
    124. smooth: true,
    125. type: 'line',
    126. itemStyle: {
    127. normal: {
    128. color: '#3888fa',
    129. lineStyle: {
    130. color: '#3888fa',
    131. width: 2
    132. },
    133. areaStyle: {
    134. color: '#f3f8ff'
    135. }
    136. }
    137. },
    138. data: actualData,
    139. animationDuration: 2800,
    140. animationEasing: 'quadraticOut'
    141. }]
    142. })
    143. }
    144. }
    145. }
    146. script>

    一路看下来没什么问题,只有 autoResize不知道是干什么的,看结构应该是在index.vue传入图表数据

    index.vue

    没有传入宽高,用的默认值

    1. <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
    2. <line-chart :chart-data="lineChartData" />
    3. el-row>

    再看看resize.js,我水平不够还没有使用过mixins,正好借这个机会看看怎么使用

    1. import { debounce } from '@/utils'//引入防抖函数等会来看
    2. export default {
    3. data () {
    4. return {
    5. $_sidebarElm: null,//字面意思是侧边栏,没太搞懂什么作用
    6. $_resizeHandler: null
    7. }
    8. },
    9. mounted () {
    10. //定义resize事件 echart如果存在就会调用resize 让图表自适应显示
    11. this.$_resizeHandler = debounce(() => {
    12. if (this.chart) {
    13. this.chart.resize()
    14. }
    15. }, 100)
    16. // 窗口大小变化时就会resize保证图表显示正常
    17. this.$_initResizeEvent()
    18. //等会再研究
    19. this.$_initSidebarResizeEvent()
    20. },
    21. //销毁上面两个函数
    22. beforeDestroy () {
    23. this.$_destroyResizeEvent()
    24. this.$_destroySidebarResizeEvent()
    25. },
    26. //从其他组件切换到当前组件的时候,调用resize事件
    27. activated () {
    28. this.$_initResizeEvent()
    29. this.$_initSidebarResizeEvent()
    30. },
    31. //切换到其他组件销毁上面两个方法
    32. deactivated () {
    33. this.$_destroyResizeEvent()
    34. this.$_destroySidebarResizeEvent()
    35. },
    36. methods: {
    37. $_initResizeEvent () {
    38. window.addEventListener('resize', this.$_resizeHandler)
    39. },
    40. $_destroyResizeEvent () {
    41. window.removeEventListener('resize', this.$_resizeHandler)
    42. },
    43. $_sidebarResizeHandler (e) {
    44. if (e.propertyName === 'width') {//e.propertyName忘了是啥玩意,大概率是改变的属性啥的 等会查查
    45. this.$_resizeHandler()
    46. }
    47. },
    48. $_initSidebarResizeEvent () {
    49. this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
    50. //动画transition结束后调用this.$_sidebarResizeHandler
    51. this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
    52. },
    53. $_destroySidebarResizeEvent () {
    54. this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
    55. }
    56. }
    57. }

    图表相关的都能看懂,就是sidebar相关的有点懵,e.propertyName也忘了,查了一下mdn好像有了点思路

      我猜测应该是侧边栏宽带发生变化时调用resize方法让图表正常显示

    我这里操作了一下侧边栏可以变大变小,当宽带小到一定的时候侧边栏会消失

    相关代码

    1. $_sidebarResizeHandler (e) {
    2. if (e.propertyName === 'width') {
    3. this.$_resizeHandler()
    4. }
    5. $_initSidebarResizeEvent () {
    6. this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
    7. //动画transition结束后调用this.$_sidebarResizeHandler
    8. this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
    9. },

    最后我在

    src/style/sidebar.css中证实了想法

    这样一来上面的代码就不难理解了 

    通过e.propertyName指示完成动画的css属性名称,然后监听侧边栏的变化,如果是宽带发生改变,就对图表进行resize 保证正常显示

    图表部分差不多就这些,用mixin 来处理 resize 代码确实是十分优雅,学到了

    直接借鉴到自己的组件中

    防抖函数

    再分析一下防抖函数

    好像和昨天刚看的underscore中防抖函数差不多的思想,有空我写一篇文章仔细分析一下

    传入一个参数immediate,代表是否想要立即执行,如果传递了immediate,则立即执行一次函数,然后设置一个定时器,时间截止后将定时器设置为null,下次进入函数时先判断定时器是否为null,然后决定是否再次执行。

    1. /**
    2. * @param {Function} func
    3. * @param {number} wait
    4. * @param {boolean} immediate
    5. * @return {*}
    6. */
    7. export function debounce(func, wait, immediate) {
    8. let timeout, args, context, timestamp, result
    9. const later = function() {
    10. // 据上一次触发时间间隔
    11. const last = +new Date() - timestamp
    12. // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    13. if (last < wait && last > 0) {
    14. timeout = setTimeout(later, wait - last)
    15. } else {
    16. timeout = null
    17. // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
    18. if (!immediate) {
    19. result = func.apply(context, args)
    20. if (!timeout) context = args = null
    21. }
    22. }
    23. }
    24. return function(...args) {
    25. context = this
    26. timestamp = +new Date()
    27. const callNow = immediate && !timeout
    28. // 如果延时不存在,重新设定延时
    29. if (!timeout) timeout = setTimeout(later, wait)
    30. if (callNow) {
    31. // 如果定时器不存在并且传递了immediate,立即执行
    32. result = func.apply(context, args)
    33. context = args = null
    34. }
    35. return result
    36. }
    37. }

    未完待续

  • 相关阅读:
    基于PHP+MySQL的教室自习室预约信息管理系统#毕业设计
    【MySQL高级篇】一文带你吃透数据库的约束
    【红队】ATT&CK - 自启动 - 利用LSA身份验证包自启动机制
    XTU-OJ 1215-A+B V
    pytorch的安装教程
    CG代码 雪景补充
    Navicat连接mysql8.0:提示无法加载身份验证插件“caching_sha2_password”
    【C++】list
    华钜同创:亚马逊开店有哪些注意事项
    驰骋BPM RunSQL_Init接口SQL注入漏洞复现 [附POC]
  • 原文地址:https://blog.csdn.net/qq_60587956/article/details/126803623