工作笔记2021/06/15-至今

Echarts篇

基础

所有图都是一个dom,一个options的写法,主要的options的配置,太多了

html部分
js部分 import echarts from 'echarts' import 'echarts-wordcloud' // 词云图,单独引入 Vue.prototype.$echarts = echarts const myChart = this.$echarts.init(document.getElementById(this.config.id)) myChart.setOption(this.config.option)

词云图

词云图是要另外安装依赖的,echarts里面并没有包含这个功能

"dependencies": {
    "axios": "^0.21.1",
    "core-js": "^3.15.2",
    "echarts": "^4.9.0", //本地
    "echarts-wordcloud": "^1.1.3",//就是这个
    "element-ui": "^2.4.5",
    "html2canvas": "^1.0.0-rc.7",
    "vue": "^2.6.14",
    "vue-router": "^3.5.2",
    "vuex": "^3.6.2",
    "xlsx": "^0.16.5"
  },

配置

// 声量情感分布-提及内容词云
      wordOption: {
        id: 'wordOption',
        option: {
          series: [
            {
              // 词的类型
              type: 'wordCloud',
              // 设置字符大小范围,那种字太多的有可能因为最小值太小不显示,可以设大一点
              sizeRange: [16, 58],
              // 每个字的倾斜角度
              rotationRange: [-45, 90],
              textStyle: {
                normal: {
                  // 生成随机的字体颜色
                  color: function () {
                    return 'rgb(' + [
                      Math.round(Math.random() * 160),
                      Math.round(Math.random() * 160),
                      Math.round(Math.random() * 160)
                    ].join(',') + ')'
                  }
                }

              },
              // 不要忘记调用数据
              data: [
                {
                  'name': '花鸟市场',
                  'value': 1446
                },
                {
                  'name': '汽车',
                  'value': 928
                },
                {
                  'name': '视频',
                  'value': 906
                },
                {
                  'name': '电视',
                  'value': 825
                },
                {
                  'name': '动漫',
                  'value': 486
                }
              ]

            }
          ]
        }
      },

柱状图

配置

// 声量情感分布
      volEmotionOption: {
        id: 'volEmotionOption',
        option: {
          color: ['#32B0F2', '#006699', '#4cabce'], // 这个是颜色
          xAxis: {
            type: 'category',
            data: []
          },
          yAxis: [
            {
              name: '声量',
              type: 'value'
            },
            {
              name: '占比',
              type: 'value',
              min: 0,
              max: 100,
              axisLabel: {
                formatter: '{value} %'
              }
            }
          ],
          legend: {
            bottom: '5%',
            data: ['总体', '正面', '负面']
          },
          series: [
            {
              name: '总体',
              type: 'bar',
              data: [100]
            },
            {
              name: '正面',
              type: 'bar',
              data: [200]
            },
            {
              name: '负面',
              type: 'bar',
              data: [300]
            }
          ]
        }
      },

柱状图的xAxis和series,legend的关系有点奇怪,emmm,我笔记懒的详细些了,我就大概说一下
xAxis.data,比如有3个,[1,2,3];
series的每一项的data也必须有3值,对应每个柱子的内容,注意不是series的个数,是series每一项的data这个个数;

series: [
            {
              name: '总体',
              type: 'bar',
              data: [100,200,300]  //是这个
            },

legend是图下面的图例,可以点击让柱子消失,但是它的data的值是对应series每一项的值的name,如果series的每一项没name,你怎么配置legend都没用

饼图

配置

officialVol: {
        id: 'officialVol',
        option: {
          color: ['rgb(114, 143, 223)', 'rgb(106, 203, 148)'],
          tooltip: {
            trigger: 'item'
          },

          legend: {
            bottom: '5%'
          },
          series: [
            {
              name: '占比',
              type: 'pie',
              radius: '50%',
              data: [
                { value: 1048, name: 'PGC' },
                { value: 735, name: 'UGC' }
              ],
              emphasis: {
                itemStyle: {
                  shadowBlur: 10,
                  shadowOffsetX: 0,
                  shadowColor: 'rgba(0, 0, 0, 0.5)'
                }
              }
            }
          ]
        }
      },

漏斗图

配置

// 声量转化分析
      volConversion: {
        id: 'volConversion',
        option: {
          tooltip: {
            trigger: 'item',
            formatter: '{a} 
{b} : {c}%' }, series: [ { name: '占比', type: 'funnel', top: 60, width: '60%', // 大小 left: '20%', // 跟上面奏够100,就是左右居中 bottom: 60, min: 0, max: 100, minSize: '0%', maxSize: '100%', label: { position: 'right' }, data: [ { value: 60, name: '访问' }, { value: 40, name: '咨询' }, { value: 20, name: '订单' }, { value: 80, name: '点击' } ] } ] } },

柱状图-堆积

配置

brandInfluence: {
        id: 'brandInfluence',
        option: {
          color: ['#32B0F2', '#006699', '#4cabce'],
          xAxis: {
            type: 'category',
            data: ['活动前', '活动中', '活动后']
          },
          yAxis: [
            {
              name: '声量',
              type: 'value'
            }
          ],
          legend: {
            bottom: '0%',
            data: ['安全的', '奥运的', '奥运的2', '奥运的3', '奥运的4']
          },
          series: [
            {
              name: '安全的',
              type: 'bar',
              barWidth: 40,
              stack: 'default', //随便设置一样字符串
              data: [100, 99, 88]
            },
            {
              name: '奥运的',
              type: 'bar',
              barWidth: 40,
              stack: 'default',//必须一样,
              data: [100, 99, 88]
            },
            {
              name: '奥运的2',
              type: 'bar',
              barWidth: 40,
              stack: 'default',
              data: [100, 99, 88]
            },
            {
              name: '奥运的3',
              type: 'bar',
              barWidth: 40,
              stack: 'default',
              data: [100, 99, 88]
            },
            {
              name: '奥运的4',
              type: 'bar',
              barWidth: 40,
              stack: 'default',
              data: [100, 99, 88]
            }
          ]
        }
      }

折线图

配置

// 活动声量变化趋势
      activityVolLine: {
        id: 'activityVolLine',
        option: {
          color: ['#32B0F2', '#006699', '#4cabce'],
          xAxis: {
            type: 'category',
            data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
          },
          yAxis: [
            {
              name: '声量',
              type: 'value'
            }
          ],
          legend: {
            bottom: '5%',
            data: ['Q3营销声量', 'Q3整合营销&品牌声量']
          },
          series: [
            {
              name: 'Q3营销声量',
              type: 'line',
              data: [120, 132, 101, 134, 90, 230, 210]
            },
            {
              name: 'Q3整合营销&品牌声量',
              type: 'line',
              data: [220, 182, 191, 234, 290, 330, 310]
            }
          ]
        }
      },

散点图,气泡图

配置

option = {
    xAxis: {
        name: '真粉数', //根据你的数据自动生成x轴值
         splitLine: { show: false } //显示格子线
    },
    yAxis: {
        name: '美誉度 (%)',//根据你的数据自动生成y轴值
        splitLine: { show: false } //显示格子线
    },
    series: [
        {
            name: '彭于晏',
            data: [
                ['1555',80] //二维数组,两个值够了
            ],
            type: 'scatter',
            symbolSize: 40, //控制气泡大小
            label: {
                normal: {
                    show: true,
                    formatter: function (param) {
                                return '彭于晏'
                            },
                    position: 'top'
                    
                }
            },
            itemStyle: {
                normal: {
                    shadowBlur: 10,
                    shadowColor: 'rgba(120, 36, 50, 0.5)',
                    shadowOffsetY: 5,
                    color: 'red'
                }
            }
        },
        {
            name: '陈小春',
            data: [
                ['1355',60] //二维数组,两个值够了
            ],
            type: 'scatter',
            symbolSize: 10, //控制气泡大小
            label: {
                normal: {
                    show: true,
                    formatter: function (param) {
                                return '陈小春'
                            },
                    position: 'top'
                    
                }
            },
            itemStyle: {
                normal: {
                    shadowBlur: 10,
                    shadowColor: 'rgba(120, 36, 50, 0.5)',
                    shadowOffsetY: 5,
                    color: 'red'
                }
            }
        }
    ]
};

Echarts常用配置补充

太多太多太多了,没办法,用到就记一下
(1) 数据视图

toolbox: {
        show: true,
        feature: {
          dataView: {
              show: true,
              title: '名字', //这个是鼠标悬浮上去的文案
              readOnly: true,
              lang: [' ', '关闭 ',' '] //这个才是打开后的文案
          }
        }
    },

(2) 缩放
如果图表的数据太多什么的,全部都挤在一起显示,可以加这个

dataZoom:{
      show: true,
      height: 52, //高度
       bottom: '0', //位置,默认在底部
       start: 0, //不清楚
       end: 50, //不清楚
       fillerColor: 'red', //背景色
       handleColor: 'skyblue' //左右两边的小块
}

工作笔记2021/06/15-至今_第1张图片

(3) 图例缩放
上面那个是表的缩放,如果是图例的,legend那个,可以加个

legend:{
  type: 'scroll'
}

工作笔记2021/06/15-至今_第2张图片

(4) tooltip配置
鼠标悬浮上面的显示,formatter是自定义

 tooltip: {
              trigger: 'axis', //触发范围,一般写这个,不要写item,item的话触发面积太小,要点到线或者柱子才行
              axisPointer: {
                type: 'shadow' //这个是阴影,hover效果默认是一根线,加这个就变成阴影
              },
formatter: function (params) { //params这个有你需要显示的参数
                return 'lalala'
              }
            },

(5) x,y轴配置

yAxis: {
              name: '声量',
              type: 'value',
              axisLabel: {
              formatter: '{value} %' //如何显示
            },
            axisLine: { //y轴的连线
              show: true, //是否要连起来
              lineStyle: {
                color: 'red'
              }
            },
            axisTick: { //刻度,突出来的
              show: true
            },
            splitLine: { //间隔线
              lineStyle: {
                // 间隔色
                color: ['skyblue']
              }
            }
          }

(6) 如何在series加多点参数
需求是这样tooltip要显示一些额外的参数,如果能直接在format参数里面拿到就不用额外处理,注意
data里面的子项一定是对象才能这样做,如果是[100],是不行的

series: [
            {
              name: '总体',
              type: 'bar',
              data: [  //这个data一定是这个格式
                {
                  value: 100,
                  temtemtem: '自定义参数'
                }
              ]
            },
]
//上面你这样写了之后,你就可以
 tooltip: {
              trigger: 'item',
              formatter: function (params) {
                return '声量值: ' + params.data.temtemtem
              }
            },

(7) setoptions第二个参数问题
至少我这边是有遇过,当图表数据从少到多的时候,正常变化,但是,如果是从多变少,比如少一个数据,图表就不正常了,还是变少之前的样子
原因是在第二个参数,设置成true就可以,默认是false

this.myChart.setOption(copyconfig.option, true)

(8) 柱状图柱子间隙
这个应该比较少用到,不过还是记一下,情景我很难解释,大概是legend和series不能同时满足的时候,你必须清掉xais的data值让它可以正常显示,但是会挤在一起
barGap,每一个都要设置,而且是一样的值才生效

 xAxis: { 
            data: []
          },
legend: {
            bottom: '5%',
            data: ['总体','正面','负面']
          },
series: [
            {
              name: '总体',
              type: 'bar',
              
              barGap: '100%',
              data: [
                {
                  value: 100
                }
              ]
            },
           {
              name: '正面',
              type: 'bar',
              
              barGap: '100%',
              data: [
                {
                  value: 200
                }
              ]
            },
            {
              name: '负面',
              type: 'bar',
              
              barGap: '100%',
              data: [
                {
                  value: 300
                }
              ]
            },
          ]

(9) 双y轴
一般双y轴,右边的要有另外一组series数据,一般是柱状图配折线图我遇到的比较多
用yAxisIndex定位y轴
工作笔记2021/06/15-至今_第3张图片

yAxis: [
          {
            name: "互动量",
            type: "value",
            axisLine: {
              lineStyle: {
                color: "#A9A9A9",
              },
            },
            splitLine: {
              lineStyle: {
                // 间隔色
                color: ["#F5F5F5"],
              },
            },
          },
          {
            name: "贡献度(%)",
            type: "value",
            min: 0,
            max: 100,
            axisLabel: {
              formatter: "{value} %",
            },
            axisLine: {
              lineStyle: {
                color: "#A9A9A9",
              },
            },
            splitLine: {
              show: false,
            },
          },
        ],
series: [
          {
            name: "互动量",
            type: "bar",
            barWidth: 40,
            data: [],
          },
          {
            name: "贡献度",
            data: [],
            type: "line",
            yAxisIndex: 1, //用这个定位
          },
        ],

(10) 饼图为0隐藏显示
这种做法一般有两种,一种就是常见的过滤数据,我下面这种是不过滤的,通过控制label和labelLine
但是经过测试发现,label的show关了后,labelLine也会关,不过保险起见,两个都写

series: [
    {
      name: 'Access From',
      type: 'pie',
      radius: '50%',
      data: [
        { 
          value: 0, //不用过滤,0就0
          name: 'Search Engine',
          label:{
            show: 0? true:false, //通过控制show
            color: 'skyblue'
          },
          labelLine:{
            show: 0? true:false, //同上
            length: 30,
            lineStyle:{
              color: 'red'
            }
          }
          
        }]
}],

(11) 图表的resize设置
一般窗口变化的时候,你按F12拖动窗口,这个时候如果图表没有设置这个resize,图表会飘
window监听resize事件,最后一个参数表示要捕获true还是冒泡false
我本来以为设置同个resize会覆盖掉前面那个,其实不会

mounted(){
window.addEventListener('resize', this._resizeEventHandler, false)
}
methods:{
_resizeEventHandler() {
      // 这里加多个判断,容错
      if (this.myChart) {
        // 这个节流,我是比较倾向用防抖,这个是我拷贝其他项目的做法
        // 核心,this.myChart.resize(),实例自带的方法,调用一下就行
        this.$common.throttle(this.myChart.resize(), 300)
      }
    },
}
beforeDestroy() {
    if (this.myChart) {
      this.myChart.dispose() // 图表实例销毁
    }
    window.removeEventListener('resize', this._resizeEventHandler, false) //事件移除
  }

element篇

表格固定第一行

官方的例子是固定最后一行,如何把这一行放到第一行显示呢

.hotList /deep/ .el-table {
  display: flex;
  flex-direction: column;
}
.hotList /deep/ .el-table__body-wrapper {
  order: 1;
}

表格设置自适应

设置width为auto,你也可以给某一列,比如第一列设死宽度,


          
        


var TableWidth = "auto";
              if (item === "帖子") {
                TableWidth = "740";
              }
              colum.push({
                label: item,
                width: TableWidth,
                prop: item,
              });

Vue篇

vue指令

我写了一个简单的图片替换的,就是如果src空或者加载失败,就替换默认图
因为指令只能传一个参数,其他参数我不知道怎么传,所以就用了data-这样传

使用


代码
let imgError = require('@/images/emptyImage.png')
// 部分图片替换需要一些额外的操作
function imgFixHandle(type,el){
  if(type == 1){
    el.style = 'width:60px;';
    el.parentNode.style = 'background:#eee;text-align:center;'
  }
}
export default {
  bind(el, binding) {
    let imgUrl = binding.value
    let imgFix = el.getAttribute('data-imgloadfix') 
    // let imgUrl = 'https://cxp-test.yili.com/resources/images/[email protected]'
    if(!imgUrl){
      el.setAttribute('src',imgError)

      // 额外操作
      setTimeout(() => {
        imgFixHandle(imgFix,el)
      },0)

      return 
    }
    let img = new Image()
    img.onload = function(){
      el.setAttribute('src',imgUrl)
      img = null
    }
    img.onerror = function(){
      el.setAttribute('src',imgError)

      // 额外操作
      imgFixHandle(imgFix,el)

      img = null
    }
    img.src = imgUrl
  }
}

我就用了一个钩子,其他没用到,只能百度先写下来
钩子+参数

bind(el,binding,vnode,oldVnode):             首次绑定执行一次,负责初始化
inserted:          被绑定元素插入父节点时候调用,仅保证父节点存在,不一定已被插入文档
update:            组件VNode更新时,可能在其子VNode更新前
componentUpdated:  组件VNode及其子VNode都更新后调用
unbind:            解绑时调用

el:       绑定的元素
binding:   绑定对象,包含参数值,value和oldValue
vnode:     当前虚拟节点
oldVnode:  上一个虚拟节点,仅在update和componentUpdate钩子可用

区别
bind 和 inserted

共同点: dom插入都会调用,bind在inserted之前

不同点:
    bind 时父节点为 null
    inserted 时父节点存在。
    bind是在dom树绘制前调用,inserted在dom树绘制后调用

bind: function (el) {
    console.log(el.parentNode)  // null
    console.log('bind')
},
inserted: function (el) {
    console.log(el.parentNode)  // 
...
console.log('inserted') }

update 和 componentUpdated
跟vue组件的up,bup差不多

update(el, binding,vnode,oldVnode){
    console.log(el.innerHTML);       // 
} componentUpdated(el, binding,vnode,oldVnode){ console.log(el.innerHTML); // //
!!
}

proxytable的深刻认识

这个到我的文章,跨域那个看

v-modal用法

这个是语法糖,有两部分,一般可以这样联想,v-model是双向绑定,一般演示的时候都是用input的,input的value值就是当前值,然后输入的时候,就是监听了@input方法,所以


等同于

很多第三方UI库用v-modal都有用来作显示隐藏,就是外层传一个boolean,组件里面不用emit出来,让组件自己改这个值,大概这样

// 传一个temFlag


// 组件
测试v-
// 抛出input事件,也是固定死的
关闭、打开
关闭、打开
props: { value: { // 一定叫这个名字,固定死的 type: Boolean, default: true }, filterParam: { type: Object, default: () => {} } },

vue打包的assetsPublicPath属性

这个属性是针对资源,也就是css,img,js这些资源的引入路径写法,
并且要跟,这个dist文件夹,在服务器目录的层级,保持一致,
比如dist文件扔在根目录,访问xxx.com/index.html
那么assetsPublicPath是 / 或者 ./ 都行 ,
如果放了几层目录,xxx.com/ra/ba/cd/index.html,则这个属性就要变了,要一样
assetsPublicPath: '/ra/ba/cd/'

vue数组用索引修改字符串,数组不生效

这个以前真没注意,数组用索引改是不生效的,视图不会更新,看了一下好像是数组无法用object.defineproperty劫持set,get方法

tem = [1,2,3]
this.tem[1] = 5 //视图不会更新

vue组件style的关系

style加了scoped属性,会在所有dom上面加标识,比如,

data-v-101b773d这个就是标识
数据哦

然后所有的样式也都是默认加这个

虽然写是这样写,
.tem {
  color:skyblue
}
但是编译后,浏览器看到的是这样
.tem[data-v-101b773d] {
  color:skyblue
}

这就是为什么加了这个属性后,不会影响到这个组件里面套入的其他组件,因为其他组件的dom没有data-v-101b773d这个属性,就算其他组件也加了scoped,它的data-v-xxxxxx也是不同的

然后,继续说一下,组件的style是怎么加载的
每个组件的style都是按需下载,并且是会插入html的header标签,不过有点不同,我发现dev的时候,是style形式插入,而build后,是link标签下载

我为什么说这个呢

因为我发现如果某个组件的style不加scoped,然后加载的时候,header标签插入,然后你其他组件的样式,就被它影响了!!

怎么避免
一般来说,不加scoped是为了让整个组件的样式都影响内部组件,或者是改UI库,比如elm的,

  1. 要么你就在类前面加个父类

    .fu .target {}
  2. 要么就不要去掉scoped,用/deep/,这个/deep/编译后的原理其实是吧data-v放在最开始的类,后面的不会有

    .fu /deep/ .target {}
    
    // 编译后
    .fu[daa-v-xxxxx] .target {}

vue-cli3打包去掉consol

这个配置不用额外install依赖,本身你用脚手架3构建的vue项目已经内置了
把这个插到vue.config.js就行了

// vue-cli3内置webpack的TerserPlugin,可以用来处理js
  chainWebpack(config) {
    // 非开发环境,去掉console
    config.when(process.env.NODE_ENV !== 'development', config => {
      config.optimization.minimizer('terser').tap(options => {
        options[0].terserOptions.compress.drop_console = true
        return options
      })
    })
  },

webpack打包,锁版本,静态资源抽离出来,html引入,不参与打包

首先说下打包

我们知道,打包的时候,webpack是爬你js文件,然后看到你有import其他文件,再继续爬,然后通过你的loader,处理文件,最后全部塞进去一个js文件,或者几个js文件里
然后这里要分两种情况,一种是资源放cdn的,一种是还在你的体积包
这次项目中,我把echarts抽了出来,就是网上找一个min.js的版本,然后,在html引入
工作笔记2021/06/15-至今_第4张图片
然后,可以看到,我把文件丢到了public文件夹,这个文件夹作用就是vuecli2的那个static文件夹,这个文件夹下面所有文件不参与打包,原封不动搬到打包之后的文件夹里,所以不用担心引入路径出问题
工作笔记2021/06/15-至今_第5张图片

这里说一下,正规的话,像这种资源应该要用cdn的,减少包体积

然后,html引入的js,都是会默认挂载到window上面?(至少echars是的,其他js文件不太清楚),所以在代码里面,我们可以这样

Vue.prototype.$echarts = window.echarts

还没完,因为代码里面可能还有这种import的代码,所以你还需要在webpakc这样配置

// 某些第三方库,如果使用了html引入js的话,那webpack就不用打包这个文件进入js
  // 一般这种都是用cdn引入,可以减少体积,但是现在这个echarts我只是抽出来而已,放到public静态文件夹
// 个人分析,这里怎么写,取决于你平时import是怎么写,比如echarts就是这样,import echarts from 'echarts'
  configureWebpack: {
    externals: {
      echarts: 'echarts'
    }
  }

配了上面那个后,就算代码里面你写 import ,也不会参与打包

锁版本

补充篇

a标签的下载文件

《“产品概念口味包装测试标准化方法”的补充说明_F》

下载的href路径一定要英语,不能中文,download写文件名加后缀

dist缓存,hash值更新

(1)F12那里有个DOC,可以看到当前页面是加载了哪个html,然后看响应,看它资源hash值判断发版有没有生效;

(2)而且通过这个我们可以发现,我们本地run dev,其实做的事情,跟run build一样,也是打包了,只是这个打包没有放出来,我们看不到而已;

(3)ctrl+f5 ,强制清缓存,清不了iframe的,勾disable cache加c+f5,才能清除

(4)打包关掉sourcemap,体积会小很多

iframe

比如A域名嵌套iframe,B域名
(1)如果B域名跟A同域,也就是

A.html