vue3常用代码:监听路由 | mitt、project/inject无效 | 防抖函数 | 下载函数

菜鸟做项目时发现很多 vue3 常用的代码,所以来总结一下!

监听路由

import { useRoute } from "vue-router";
let router = useRoute();
watch(
  () => router.path,
  (newValue, oldValue) => {
    console.log("watch", newValue, oldValue);
  },
  { immediate: true }
);

这里顺便补充一下 路由跳转跨界面跳转获取参数

路由跳转

import { useRouter, useRoute } from "vue-router";
const router = useRouter();
const route = useRoute();

// 跳转路由
const toPath = function (path) {
  if (route.path !== path.path) {
    //判断当前路径与跳转路径是否相同
    router.push(path);
  }
};

跨界面跳转

import { useRouter } from "vue-router"; 
// 新标签页跳转
const router = useRouter();
const openPage = (params = "") => {
  let href = null;
  if (params) {
    href = router.resolve({
      path: "/newform",
      query: {
        id: JSON.stringify(params),
      },
    });
  } else {
    href = router.resolve({
      path: "/newform",
      query: {
        id: null,
      },
    });
  }
  window.open(`${href.href}`, "_blank");
};

这里也可以使用 name:“newform” ,要和自己router里面定义的保持 对应关系

动态路由也是一样:
在这里插入图片描述
普通路由两个同时写也没有问题,但是动态路由不行,会报错!!!
在这里插入图片描述
报错:runtime-core.esm-bundler.js:343 Uncaught Error: Missing required param “xxx”
在这里插入图片描述

获取参数

import { useRoute } from "vue-router";
const route = useRoute();
console.log(route.query.id); // 这里有两种一种 params、一种 query,注意取的时候要对应!

且要分清 动态路由(params)路由后面带参数(query) 这两种情况!具体看文章:23 动态路由(路由传参)

mitt、project / inject 无效

如果通信的组件是 router-view 里面 根据路由加载的 或者 路由有两层嵌套,那么不管是 mitt 还是 project/inject 都无法进行组件间的通信,因为 mitt 要能通信必须是该界面已经加载出来了!而 project/inject 不知道为什么,嵌套了两层后,第二层 router-view 里面的组件就无法获取了,会报错

[Vue warn]: injection "openmenu" not found. 
  at <Resources onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
  at <RouterView> 
  at <ElMain> 
  at <ElContainer> 
  at <Home onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< null > > 
  at <RouterView> 
  at <App>

好像是因为第一层 router-view 被卸载了,所以 project 为 undefined 了!也可能是因为 provide 只能够向下进行传递数据,而路由并不相当于是其子组件!

解决方案

使用pinia、vuex等!

防抖函数 (已封装)

/**
 * 防抖函数
 * @param {function} fn
 * @param {number} delay
 * @returns {function}
 * 如果函数有参数,直接定义一个常量等于debounce(fn,delay)
 * 调用的时候直接 常量(函数参数) 就行
 *
 */
export const debounce = (fn, delay) => {
  let timer = null;
  return function () {
    let context = this;
    let args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function () {
      fn.apply(context, args);
    }, delay);
  };
};

下载函数(get)

下载和请求接口的逻辑不太一样,只需要访问就行了,菜鸟有时候也容易忘记,所以这里记一下!

/**
 * 下载工具
 * @param {string} url 下载地址
 * @param {string} name 文件名
 *
 */
export const downloadTool = (url, name = "") => {
  // 微信内置浏览器要提示
  if (isWxBrowser()) {
    // eslint-disable-next-line
    ElMessage({
      message: "请先在浏览器中打开再下载!",
      type: "error",
    });
  } else {
    let a = document.createElement("a");
    a.style = "display: none"; // 创建一个隐藏的a标签
    a.href = url;
    a.download = name;
    document.body.appendChild(a);
    a.click(); // 触发a标签的click事件
    document.body.removeChild(a);
  }
};

post

当然有时候下载传入的参数比较多,那么后端是可能将下载变成post请求的,这个时候要进行如下修改:

function downloadFileFun(formType) {
    const params = {
      formType,
    };
    downloadFile(params)
      .then((res) => {
        // console.log(res);
        // 从响应中获取文件数据
        const fileData = res;
        // 创建一个Blob对象
        let blob = new Blob([fileData], { type: "application/vnd.ms-excel" });
        // 生成文件URL
        const downloadUrl = URL.createObjectURL(blob);
        downloadTool(downloadUrl, "模板表.xlsx");
      })
      .catch((err) => {
        console.log(err);
      });
  }
}

注意

downloadFile 这个api里面要加一个responseType: “blob”:

export function downloadFile(params) {
  return request({
    url: "/user/downloadExcel",
    method: "POST",
    data: params,
    responseType: "blob",
  });
}

如果是 pdf ,这里要修改为 :

let blob = new Blob([fileData], { type: "application/pdf" });

responseType: "arraybuffer",

如果后端不仅会返回数据,有时候还会返回报错信息的话,就需要对返回的结果进行判断,因为只要使用了 responseType 就算返回的不是数据类型,也会强制转换,那么报错信息就变成了 blob数据对象 了,没有data、message等东西了,需要将数据对象转换回json对象,代码如下:

createReportApi(formdata.value)
   .then((res) => {
     console.log(res);
     loading.close();
     // 非文件数据,长度会较小
     if (res.byteLength <= 100) {
       const jsonString = new TextDecoder("utf-8").decode(res);
       const jsonObject = JSON.parse(jsonString);
       console.log(jsonObject);
       // eslint-disable-next-line
       ElMessage({
         message: jsonObject.message,
         type: "error",
       });
     } else {
       let blob = new Blob([res], { type: "application/pdf" });
       downloadTool(
         window.URL.createObjectURL(blob),
         `${formdata.value.contractNum}-${formdata.value.projectName}.pdf`
       );
     }
   })
   .catch((err) => {
     console.log(err);
     loading.close();
   });

更多常见代码见:常用代码:vue必须配置的部分代码、element ui按需引入、vue动态绑定背景、自适应js、禁止放大、播放声音、store的使用、websocket封装、echarts、swiper

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PBitW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值