vue3常用代码:监听路由 | mitt、project/inject无效 | 防抖函数 | 下载函数 | 复制函数
监听路由路由跳转跨界面跳转获取参数mitt、project / inject 无效解决方案防抖函数 (已封装)复制函数封装下载函数(get)post注意
菜鸟做项目时发现很多 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);
};
};
复制函数封装
复制函数
/**
* 复制文本到粘贴板
* @param {*} txt 需要粘贴的文本
* @returns {function}
*
*/
export let copyTxt = (txt) => {
// 惰性函数
if (navigator.clipboard) {
copyTxt = (txt) => {
navigator.clipboard.writeText(txt);
};
copyTxt(txt);
} else {
copyTxt = (txt) => {
const input = document.createElement("input");
input.setAttribute("value", txt);
document.body.appendChild(input);
input.select();
document.execCommand("copy");
document.body.removeChild(input);
};
copyTxt(txt);
}
};
下载函数(get)
下载函数(get)
下载和请求接口的逻辑不太一样,只需要访问就行了,菜鸟有时候也容易忘记,所以这里记一下!
/**
* 判断是否是微信浏览器
*/
export const isWxBrowser = () => {
// 判断是否H5微信环境,true为微信浏览器
const ua = navigator.userAgent.toLowerCase();
return ua.match(/MicroMessenger/i) == "micromessenger" ? true : false;
};
/**
* 下载工具
* @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
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)