Vue - vue 前端开发技术指南

以 vite + vue3 + ElementPlus + pinia 开发技术栈所遇到的技术难题及解决方案汇总

如何在 vite+vue3 项目中支持 jsx 技术

  1. 安装插件 pnpm add -D @vitejs/plugin-vue-jsx
  2. 配置 vite.config.js
import vueJsx from '@vitejs/plugin-vue-jsx';
 export default defineConfig({
   plugins: [
     vueJsx(),  // 在vue() 之前
     vue(),
	 ]
 })
  1. 在使用 jsx 语法的组件中设置 lang
<script lang='jsx' setup>
 function formatPlateNumber(row) {
 const colorStyle = PLATE_COLOR[row.plateColor];
 return (
   <div style={colorStyle}>{row.plateNumber}</div>
 );
}
</script>

如何在 vue3 项目中支持 echarts

  1. 安装 echarts pnpm add echarts
  2. 在项目中使用 echarts
// 设置图形挂载点ref
<template>
  <div class="board-item-body" ref="chartRef" v-loading="isLoading"  element-loading-background="rgba(0,0,0,0)">
  </div>
</template>
// 导入echarts
import * as echarts from 'echarts';
const isLoading = ref(false); // 设置图像加载过程指示
const statsData = ref(null); // 统计数据

// 初始化ref
const chartRef = ref();
// 设置图像实例
let chart = null;

// 绘制图表
function renderChart() {
  // 构建图表数据
  const legendData = map(statsData.value, 'overRangeName');
  const seriesData = map(statsData.value, (item) => ({ name: item.overRangeName, value: item.rangeRatio }));
  // 图表参数配置
  const option = {
      legend: {
          orient: 'vertical',
          x: '15%',
          y: 'center',
          textStyle: {
              color: '#E5EFFF',
          },
          data: legendData,
      },
      tooltip: {
          trigger: 'item',
          formatter: (item) => `${item.marker}${item.name}&nbsp;&nbsp;&nbsp;<span style="font-weight: bold;">${item.value}%</span>`,
      },
      series: [
      {
          type: 'pie',
          avoidLabelOverlap: true,
          label: { show: false },
          data: seriesData,
          radius: ['30%', '70%'],
          center: ['70%', '50%'],
      }]
  };

  // 图表容器是否已加载完毕
  if (chartRef) {
      // 首次绘制图表需要进行初始化
      if (!chart) chart = echarts.init(chartRef.value);
      // 设置图表参数更新图表
      chart.setOption(option);
  }
}

// 获取统计数据
function getData(callback) {
  isLoading.value = true;
  overRangeStats({}).then((res) => {
    statsData.value = res.data;
    callback && callback();
  }).finally(() => {
    isLoading.value = false;
  });
}


// 设置图表在页面调整大小时也能够适配调整大小
window.addEventListener('resize', function () {
  chart.resize();
});

// 页面加载后获取图表数据后绘制图表
onMounted(() => {
  getData(renderChart);
});

// 页面卸载后销毁图形实例
onUnmounted(() => {
  chart.dispose();
});

vue3 中引入 dayjs 处理日期时间

  1. 安装 dayjs pnpm add dayjs
  2. 使用 dayjs
  import dayjs from 'dayjs';
  // 引入duration 插件
  import duration from 'dayjs/plugin/duration'
  dayjs.extend(duration);

  dayjs.duration(duration, 'seconds').format('HH:mm:ss');
  dayjs(time).format('YYYY-MM-DD HH:mm');

vue3 项目中引入 lodash-es 进行数据处理

  1. 安装 lodash-es pnpm add lodash-es
  2. 使用 lodash-es
  import {map, isEmpty, reduce} from 'lodash-es';

vue3 页面中监听键盘事件的方法

  1. @keydown.enter 进行事件绑定到回车键
  <el-form-item prop="username">
    <el-input v-model="form.username" :placeholder="t('form.username')" prefix-icon="user" @keydown.enter="doLogin"></el-input>
  </el-form-item>

在vue3中如何引入样式

  1. 在组件的style区域引入
  <style>
    @import "./styles/index.less"
  </style>
  1. 在main.js 中引入
  import "@/styles/index.less";

在vue3 style中如何引入js变量

  1. 使用v-bind(variable) 的形式
<script setup>
  const paddingStyle = props.isFront ? '0!important' : '15px 20px';
  const marginStyle = props.isFront ? '0!important' : '20px';
</script>

<style scoped lang="scss">
  :deep(.cm-table_top__toolbar){
    padding: v-bind(paddingStyle);
    margin-top: v-bind(marginStyle);
  }
</style>

vue3 中 v-loading, 遮罩层变透明的方法加 (element-loading-background="rgba(0,0,0,0)")属性即可。

<template>
  <div class="board-item-body" v-loading="isLoading" element-loading-background="rgba(0,0,0,0)"> </div>
</template>
<script>
  const isLoading = ref(false);
</script>

vue3 中引入element-Plus 图标集

  1. 将图标注册为全局组件Icon,并通过属性icon进行区分, 其优势是可以做到动态图标,通过传入不同的icon属性值可以渲染不同的图标
  • 在main.js 中注册为全局组件, 通过createVNode, h 函数创建vue的虚拟节点
// 导入 element-plus 的图标集
import * as ElIcons from '@element-plus/icons-vue';
// 注册Icon组件
const Icon = (props) => {
  const { icon } = props;
  return createVNode(ElIcons[icon]);
}
app.component('Icon', Icon);
  • 在vue组件中使用
<el-icon :size="25">
  <Icon :icon="weatherName"/>
</el-icon>
  1. 将图标直接注册为全局组件, 其优势是简单明了,但无法在动态场景下使用。
  • 在main.js 进行全局注册
import * as ElIcons from '@element-plus/icons-vue';
// 注册ElIcons为app的子组件
for (const name in ElIcons){
  app.component(name, ElIcons[name]);
}
  • 在vue组件中使用
  <el-icon :size="25">
    <WeatherName />
  </el-icon>

vue3 + Element-plus 项目中 el-select 数据无法正常回显,设定了value值,但不能正常回显label问题

问题原因: 在于设定的value值类型与options选项value值类型不匹配造成的。
解决方案:可以转换options里的value值类型或者设定的value值类型,值类型两者匹配后即可正常回显。

<template>
  <el-form-item prop="status" label="状态">
    <el-select clearable v-model="filters.status" placeholder="全部" style="width: 180px">
      <el-option v-for="item in statusOptions" :label="item.label" :value="item.value" />
    </el-select>
  </el-form-item>
</template>
<script setup>
import { SWITCH_STATUS } from '@/const';
const statusOptions = computed(() =>
  // 将options 中的value值转为数字型
  map(SWITCH_STATUS, (value, key) => ({ label: value, value: Number(key) }))
);
</script>

vue-router, 通过路由传送参数,以及接收参数

  1. 通过query
// 传送参数
const router = useRouter();
router.push({path: '', query: {key: value}});

// 接收参数
const route = useRoute();
const value = route.query?.key;

vue 页面中的图片或图标在本地正常显示,部署上线后无法正常显示

原因分析: 对于js代码中的路径,vite无法进行提前分析和编译,所以导致打包后找不到相关图片,对于style中的背景图片静态路径则没有影响。
解决方案:

  1. 将无法正常显示的图标移到项目更目录的public 目录下。
  2. 在图片路径引用的地方,将路径全部改为'/' 根目录下的图片即可。

js 代码中图片引用

<script setup>
// 处理icon图标
function formatIcon(row) {
  return <img src={`/img/z${row.vehicleType}.png`} />;
}
</script>
图片实际所在位置: /public/img/z1.png

css 中的图片引用

<style lang="scss">
  .board-item-header {
    background: url('@/assets/panel-title-bg.png') center top no-repeat;
    display: flex;
    justify-content: space-between;
  }
</style>
图片实际所在位置: /src/assets/panel-title-bg.png

html 中的图片引用

<template>
  <img src="@/assets/login-bg.png" </div>
</template>
图片实际所在位置: /src/assets/login-bg.png

vite build 执行后sass报警告: Sass‘s behavior for declarations that appear after nested rules will be changing

问题原因: sass 为了迎合css最新的行为,将之前嵌套定义的规则会统一定义在开始,现在则保持原来的位置

.el-icon.el-dialog__close:hover {
	svg {
	  color: #fff;
	}
	background: #2a77b7;  // 报错位置
}

解决方案一: 手动将原有的嵌套规则,放在开始位置

.el-icon.el-dialog__close:hover {
  background: #2a77b7;  // 放到开头
	svg {
	  color: #fff;
  }
}

解决方案二: 使用 & {} 将已有的规则包含起来

.el-icon.el-dialog__close:hover {
	svg {
	  color: #fff;
	}

	& {       // 使用 & {}
	  background: #2a77b7;
	}
}

vue组件样式重置 :deep (child) {}

<style scoped lang="scss">
.charts-body-data {
  width: 100%;
	:deep(.el-progress) {
	  padding-top: 5px;
  }
}
</style>

vue 前端路由模式为history模式,部署到线上刷新页面404问题

问题分析:出现此问题的原因是刷新页面后,向后端发送url请求,nginx无法找到路由对应的资源所以返回了404,
因此需要对后端nginx服务器进行适当的配置, 使其始终返回网站首页,这样网站首页加载后会根据前端的路由加载对应的页面。

  #index  index.html index.htm;
  try_files $uri $uri/ /index.html;

[element-plus] el-dialog 组件以及由它封装的组件必须放置在template 的最顶层,否则可能出现异常情况,包括打不开,关闭不了的情况。

[element-plus] el-select 作为行内组件使用时,必须设置style="width:200px" 属性,否则会有样式问题。

[element-plus] el-form 组件必须设置ref , 所有el-form-item 必须设置prop 属性, resetFields 方法才会生效。

[element-plus] el-progress无法正常显示的问题

  • 将组件放到别的地方看能否正常显示,如果能够在别的地方正常显示,则说明放置的位置上层的样式对当前的组件产生了影响。
  • 去掉父级组件的样式,重新为el-progress 添加新的父级样式。

eharts 中设置柱状图的图例,无法显示处理方法

  • 在series中设置name属性
  series: [
    {
      type: 'bar',
      name: '检测量',
      data: [240, 180, 140, 180, 80],
      itemStyle: {
        color: '#3EAAFF',
      }
    },
    {
      type: 'bar',
      name: '超限',
      data: [95, 70, 80, 60, 23, 20],
      itemStyle: {
        color: '#FFBA37',
      }
    }
  ]
  • lengend 属性中data数据项与name保持一致
  legend: {
    orient: 'horizontal',
    x: 'center',
    y: 'bottom',
    data: ['检测量', '超限'],
  },

调整echarts 圆环图的位置

  series: [{
    center: ['60%', '50%'],
	}]

在使用async,await发送多个网络请求时,如果请求之间没有依赖关系,则要注意使其并行发送。

async function getData1() {
  const res = await getRemoteData();
  return res;
}
async function getData2() {
  const res = await getRemoteData();
  return res;
}
// 将多个请求进行各自的封装然后进行调用,实现并行发送
onMounted(() => {
  getData1();
  getData2();
});

后端返回的数据id作为整数传送到前端,导致数据精度丢失,从而导致获取接口调用失败

原因分析: 由于前端的数字类型实际存储时都是8为double类型存储的,因此最大能表示的数字范围有限,导致从后端返回的大整数在前端无法正常处理,进行json解析后 导致了数据失去精度, 从而进一步影响到后续的接口调用。

解决方案:

  • 后端解决方案: 在服务端将整型改为字符串类型(最佳方案)
  • 前端解决方案:
    1. 将返回的数据在未进行解析前,通过正则表达式将要转换的数据从数字类型改为字符串类型。
    2. 引入json-bigint包,并替换axios等相关请求解析库的JSON.parse 方法, 在使用时通过大数整型的.tostring 转为字符串。
posted @ 2024-12-24 18:18  箫笛  阅读(8)  评论(0编辑  收藏  举报