vue2、3项目所遇问题记录,避免翻找原来项目

本文详细介绍了JavaScript中的数组去重方法、echarts图形定制、动态宽度设置、Vue组件缓存、滚动控制、图表滚动动画、颜色图例管理、vuex状态管理以及HTML2Canvas截图技巧和cookie值获取,旨在提供项目开发中的实用参考。
摘要由CSDN通过智能技术生成

前言:记录项目相遇功能难点,为后续项目做参考,避免翻找原来项目

1.实现对数组对象某个属性值去重

const pageList = [
  { fullPath: '/targetEstimate/ceTask' },
  { fullPath: '/targetEstimate/ceTask2' },
  { fullPath: '/dashboard/analysis' },
  { fullPath: '/dashboard/analysis' },
];

const uniquePages = Array.from(pageList.reduce((map, page) => {
  map.set(page.fullPath, page);
  return map;
}, new Map()).values());

console.log(uniquePages);

2.echarts树形图根据字节点多少决定容器宽度、高度,避免固定宽高元素重叠挤压

    // 树图配置
    const option = {
        // 鼠标悬浮提示过长处理
        tooltip: {
          trigger: 'item',
          triggerOn: 'mousemove',
          extraCssText: 'max-width:600px; white-space:pre-wrap', 
          formatter: function (params) {
            if (params.data.formula) {
              return `<div>${params.data.formula}</div>`
            } else {
              return params.data.formula
            }
          },
        },
        series: [
          {
            type: 'tree',
            symbolSize: ['150', 60],
            left: 0,
            right: 0,
            top: '8%',
            bottom: '13%',
            symbol: `image://${zi}`,
            edgeShape: 'polyline',
            orient: 'TB',
            lineStyle: { color: '#3193FF', width: 2 },
            label: {
              position: ['50%', '20%'],
              align: 'center',
              color: '#fff',
              formatter: ({ data }) => {
                return `{name|${data.score}(分)}\n${data.name || ''}`
              },
              rich: {
                name: { fontWeight: 700, fontSize: 20, padding: [0, 0, 10, 0] },
              },
            },
            data: [
              {
                symbolSize: [188, 60],
                symbol: `image://${gen}`,
                lineStyle: {
                  color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    { offset: 0.5, color: '#FE7000' },
                    { offset: 0.9, color: '#31A2FF' },
                  ]),
                },
                ...this.targetInfo.targetList[0],
              },
            ],
          },
        ],
      }
      this.ec5 = echarts.init(this.$refs.ec5)
      this.ec5.setOption(option)

      // 根据子项目多少决定宽度度
      let container = this.$refs.ec5
      let allNode = 0
      let nodes = this.ec5._chartsViews[0]._data._graphicEls
      for (let i = 0, count = nodes.length; i < count; i++) {
        let node = nodes[i]
        if (node === undefined) continue
        allNode++
      }
      // 根据子项目多少决定高度
      // let height = window.innerHeight
      // let currentHeight = 35 * allNode
      // let newHeight = Math.max(currentHeight, height)
      // container.style.height = newHeight + 'px'
      let width = window.innerWidth
      let currentWidth = 150 * allNode
      let newWidth = Math.max(currentWidth, width)
      // 判断字节点小于等于5容器就100%显示
      if (nodes.length <= 5) {
        container.style.width = '100%'
      } else {
      // 超过5个根据节点宽度*个数,设置容器宽度
        container.style.width = newWidth + 'px'
      }

3.echarts平均线(数值、阴影)

            markLine: {
              symbolSize: 6,
              label: { position: 'insideEndTop', formatter: '{b}: {c}' },
              data: [{ name: '平均分', type: 'average' }],
              lineStyle: {
                color: '#3193FF',
                type: 'solid',
                width: 2,
                shadowBlur: 10, // 阴影模糊度
                shadowColor: '#BFDCFF', // 阴影颜色
              },
            },

4.多行3列瀑布流

.box{    /* 瀑布流父容器 */
    column-count: 3;    /* 控制屏幕分为多少列 */
    column-gap: 10px; /* 控制列与列之间的距离 */
 }

5.实现两个数组长度一样的数,合并成一个固定格式的对象格式数组

const arr1 = ['项目1','项目2','项目3']
const arr2 = [15,33,6]
arr2.map((value, index) => ({ name: arr1[index], value }));

6.前后补0或者其它字符

padEnd() 方法会将当前字符串从末尾开始填充给定的字符串(如果需要会重复填充),直到达到给定的长度。填充是从当前字符串的末尾开始的。

padStart() 方法用另一个字符串填充当前字符串(如果需要会重复填充),直到达到给定的长度。填充是从当前字符串的开头开始的。

console.log('5'.padStart(2, '0'));
// 输出: "05"

console.log('Breaded Mushrooms'.padEnd(25, '.'));
// 输出: "Breaded Mushrooms........"

7.折叠面板(展开多个面板、手风琴效果)

// 1. 可同时展开多个面板,面板之间不影响

// closedIndexes:array 收起索引数组 (如果当前项已在关闭列表中)
if (this.closedIndexes.includes(uuid)) { 
  // 移除它,使其展开
  this.closedIndexes = this.closedIndexes.filter(index => index !== uuid); 
  } else { 
  // 当前项不在关闭列表中,将其添加进去并收起
  this.closedIndexes.push(uuid);
}

// 模板样式样式
closedIndexes.includes(a.uuid)?'展开样式':'收起样式'


// 2.手风琴效果,每次只能展开一个面板 

// dropIndex:string|number 当前打开的索引(点击项等于dropIndex ,先置空再赋值)
if (this.dropIndex === i) {
  return this.dropIndex = ''
}
this.dropIndex = i

// 模板样式样式
dropIndex===index ? 'arrow-up' : 'arrow-down'

8.uniapp点击滚动指定元素位置


//目标位置的节点:类class或者id
uni.createSelectorQuery().select("#app" + index).boundingClientRect(data => { 
  //最外层盒子的节点:类class或者id
  uni.createSelectorQuery().select(".box1").boundingClientRect(res => { 
    uni.pageScrollTo({	duration: 100, 	scrollTop: data.top + 80 - res.top		
    })
  }).exec()
}).exec();

9.vue实现页面缓存 

 // 路由对象需要被缓存的添加
 meta: {
   keepAlive: true
 }

 // router-view外层添加keep-alive
 <div id="app">
  <keep-alive>
     <router-view v-if="$route.meta.keepAlive" />
  </keep-alive>
  <router-view v-if="!$route.meta.keepAlive" />
 </div>

10.滚动到页面顶部


// options 包含以下参数的对象:

// top:指定沿 Y 轴滚动窗口或元素的像素数。
// left:指定沿 X 轴滚动窗口或元素的像素数。
// behavior:
//   smooth 表示平滑滚动并产生过渡效果
//   instant 表示滚动会直接跳转到目标位置,没有过渡效果
//   auto 或缺省值表示浏览器会自动选择滚动时的过渡效果

window.scrollTo({ top: 0, behavior: 'smooth' });

11.echarts图表自动滚动,鼠标移入停止滚动,移出滚动继续

// echartConfig 文件代码
export default {
    /**
	 * echarts x轴滚动条
	 * @param {Number} dataLength series.data数组长度
	 * @param {Number} endValue 一次显示多少条
	 * @returns datazoom对象
	 */
	dataZoom: (dataLength = 0, endValue = 11) => {
		return {
			show: dataLength > endValue ? true : false,
			type: 'slider',
			startValue: 0,
			endValue,
			showDataShadow: false,
			// 拖动显示文字
			textStyle: false,
			fillerColor: '#019069',
			moveHandleSize: 0,
			borderColor: 'rgba(1, 144, 105, 0.2)',
			backgroundColor: 'rgba(1, 144, 105, 0.2)',
			height: 6,
			bottom: 15,
			handleStyle: {
				borderWidth: 0,
				color: '#019069'
			}
		}
	},

    /**
	 * echarts图标自动滚动
	 * @param {object} documentEC echarts实例对象
	 * @param {object} option echarts图表配置
	 * @param {Number} dataLength series.data数组长度
	 * @param {Number} endValue 一次显示多少条
	 */
	autoMove: (documentEC, option, dataLength, endValue = 11) => {
		option.timer = setInterval(() => {
			if (Number(option?.dataZoom.endValue) === dataLength - 1) {
				option.dataZoom.endValue = endValue;
				option.dataZoom.startValue = 0;
			} else {
				option.dataZoom.endValue = option?.dataZoom.endValue + 1;
				option.dataZoom.startValue = option?.dataZoom.startValue + 1;
			}
			documentEC.setOption(option);
		}, 3000);
	}
}


// 页面中使用
const option = {
  dataZoom: ec.dataZoom(15),
}
const automaticEC = () => ec.autoMove(departmentEC, option,option?.dataset.source.length)

automaticEC()
departmentEC.on('mouseover', () => clearInterval(option.timer))
departmentEC.on('mouseout', automaticEC)
departmentTimer = option.timer

12.echarts多个系列设置不同颜色图例 

用途:UI图表是渐变色,图例是纯色,可以这么处理

 const marks = [
   { name: '复用额', color: '#FFCB17' },
   { name: '回收额', color: color }
 ]

 legend: { 
   textStyle: { color: '#fff' }, 
   data: marks.map(i => ({ name: i.name, itemStyle: { color: i.color } })) 
 }

13.vuex的使用

// store文件
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}


export default new Vuex.Store({
  state: {
    select: {
      year: '2024年',
      month: '05月'
    },
  },
  // 计算属性
  getters: {
    selects (state) {
      return state.select
    }
  },
  // 修改state属性值且必须是同步函数
  mutations: {
    updateSelect(state, data) {
      state.select = data
    }
  },
  // 做异步处理:发送ajax请求,通过 store.dispatch 方法触发
  actions: {
    activeSelect(context) {
     setTimeout(() => {
        commit('updateSelect',{year:'5099',month:'99'})
      }, 1000)
    }
  },
  // 分模块
  modules: {a:moduleA}
})


// 页面中修改store.state中属性的值
this.$store.commit('updateSelect',newVal)

// 页面中读取store.state的值
this.$store.state.doneTodosCount

// 页面中读取store.getters的值
this.$store.getters.doneTodosCount

// 页面中异步处理store.active
this.$store.store.dispatch('activeSelect')

14.实现将数字按千位逗号分隔并保留两位小数 

function formatNumber(number) {
  // 将数字转换为字符串并根据小数点分割整数部分和小数部分
  let parts = number.toString().split('.');
  // 处理整数部分,添加千位分隔符
  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  // 如果有小数部分,则保留两位小数;否则补充".00"
  if (parts.length > 1) {
      parts[1] = parts[1].substring(0, 2);
  } else {
      parts.push("00");
  }
  return parts.join(".");
}
// 测试示例
console.log(formatNumber(5000));   // 输出: "5,000.00"
console.log(formatNumber(8557.674));  // 输出: "8,557.67"

15.使用html2Canvas 点击按钮把某个元素 下载为图片

问题:在项目中使用html2Canvas进行截图时发现无法截取滚动条部分

解决思路:当我们截取的div容器的宽和高与内部的子容器div的宽和高不一样时,内部div就会出现滚动条,因为我们截取的div与内部div的宽和高不一致,所以截取时只能截取我们定位的div,无法截取到滚动条部分。

截取元素的宽高改成和滚动的宽和高一致,截取时就能包含滚动条部分,截取结束后宽高再恢复原来值。

<template>
  <div class="about" ref="capture">
    <div class="gantt_data_area" style="width: 3200px;background-color: red;">
      <button @click="download" style="position: fixed;left: 0;">download</button>
      <div style="height: 1500px; background-color: pink;"></div>
    </div>
  </div>
</template>

<script>
import html2canvas from 'html2canvas';

export default {
  methods: {
    download() {
      let targetDom = this.$refs.capture;   //原本需要截图的div
      this.$nextTick(() => {
        const swidth = document.querySelector('.gantt_data_area'); // 定位到内层出现滚动条div宽度
        targetDom.style.width = `${swidth.offsetWidth + 300}px`;
        html2canvas(targetDom, {
          dpi: window.devicePixelRatio * 4,
          scale: 4,
          useCORS: true, //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
          allowTaint: false,
          height: targetDom.scrollHeight,  //画布高度(包含未显示的滚动部分)
          width: targetDom.scrollWidth,  //画布高度(包含未显示的滚动部分)
          windowWidth: targetDom.scrollWidth,
          windowHeight: targetDom.scrollHeight,
        }).then((canvas) => {
          var imgUri = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream') // 获取生成的图片的url
          var saveLink = document.createElement('a')
          saveLink.href = imgUri
          saveLink.download = 'downLoad.png'
          saveLink.click()
          targetDom.style.width = '100%'; // 截图结束后需要将修改的宽度高度恢复
          targetDom.style.height = '100%';
        });
      });
    }
  }
}
</script>

16.获取cookie名未指定名称的值

document.cookie = "token=11111111111111111111";
document.cookie = "name=11111111111111111111";
// 获取cookie名未token的值
var token = document.cookie.replace(/(?:(?:^|.*;\s*)token\s*\=\s*([^;]*).*$)|^.*$/, "$1");

17.计算百分比

百分比 = (已使用量 / 总量) * 100%

将给定的数字代入公式中:
百分比 = (10 / 300) * 100

18.递归获取某个值

function getUncheckedIds(data) {
  let uncheckedIds = [];
  function traverse(item) {
    if (item.hasChecked === 0) {
      uncheckedIds.push(item.id);
    }
    if (item.children && item.children.length > 0) {
      for (const child of item.children) {
        traverse(child);
      }
    }
  }
  for (const item of data) {
    traverse(item);
  }
  return uncheckedIds;
}
const data = [{id: 1, hasChecked: 0, children: [ {id: 1, hasChecked: 1, children: [ { id: 2,hasChecked: 0 } ] } ] }];

const uncheckedIds = getUncheckedIds(data);
console.log(uncheckedIds); // Output: [1, 2]

19.递归给每一项都加上 isSelected: false

function addIsSelectedProperty(data) {
  function traverse(item) {
    item.isSelected = false;
    if (item.children && item.children.length > 0) {
      for (const child of item.children) {
        traverse(child);
      }
    }
  }
  for (const item of data) {
    traverse(item);
  }
  return data;
}
const data = [
  {
    id: 1,
    hasChecked: 0,
    children: [ {id: 1, hasChecked: 1,  children: [ {id: 2, hasChecked: 0 } ] } ]
  }
];
const updatedData = addIsSelectedProperty(data);
console.log(updatedData);

20.实现复制,将指定内容写到剪切板

const copyItem = async (item) => {
  await navigator.clipboard.writeText(`试卷名称:${item.name}`)
  message.success('复制成功');
}

21.uniapp路由跳转携带对象字符报有关encodeURIComponent的错

uni.navigateTo({url: `./children/auditLog?item=${encodeURIComponent(JSON.stringify(item))}`})

22.JS实现JSON对象与URL参数的相互转换

const json = {
    a:1,
    b:2
}
// 1. json 转url参数

// 第一种:循环处理
const jsonToUrlParam = (json) => Object.keys(json).map(key => `${key}=${json[key]}`).join('&')
// 第二种:URLSearchParams 
new URLSearchParams(json).toString();

console.log(jsonToUrlParam(json))
console.log(new URLSearchParams(json).toString())
// 输出:a=1&b=2


// URL参数转换为JSON对象
function urlParamToJson(urlParam) {
    let json = {};
    urlParam.trim()
        .split('&')
        .forEach(item => json[item.split('=')[0]] = item.split('=')[1]);

    return json;
}
console.log(urlParamToJson(json))
// 输出 {a:1,b:2}

结语:后续会持续更新......

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值