2021/08/02
1. 退出登录的问题
+ 场景
- url携带了token,退出登录时,去除url中的参数,并清空路由
+ 解决方法:
- 点击退出按钮时,this.$router.replace({path: '/login'}); location.reload(); 并执行相关的初始化函数
- 在login页面,检测是否有参数,有则location.replace(location.href.split("?")[0] + "#/login");
2. 替换掉图片src的相对路径的方法
const exchangeUrl = function (txt, reverse = false) {
if (!reverse) {
//换掉相对路径的图片
txt = txt.replace(
/<img [^>]*src=['"]([^'"]+)[^>]*>/gi,
function (match, capture) {
if (capture.includes("./")) {
let newCapture = capture.replace(
"./",
"http://xxxxxxxxxxxxxxxxxxxxxxxxxx"
);
match = match.replace(capture, newCapture);
}
return match;
}
);
} else {
//换掉相对路径的图片
txt = txt.replace(
/<img [^>]*src=['"]([^'"]+)[^>]*>/gi,
function (match, capture) {
if (capture.includes("./")) {
let newCapture = capture.replace("tiku/", ".");
match = match.replace(capture, newCapture);
}
return match;
}
);
}
return txt;
};
时间戳转时分秒
timeStr() {
let { sumSecond } = this;
let mss = sumSecond * 1000;
var hours = parseInt((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = parseInt((mss % (1000 * 60 * 60)) / (1000 * 60));
var seconds = (mss % (1000 * 60)) / 1000;
hours = hours <= 9 ? "0" + hours : hours;
minutes = minutes <= 9 ? "0" + minutes : minutes;
seconds = seconds <= 9 ? "0" + seconds : seconds;
if (hours == "00") {
return `${minutes}:${seconds}`;
} else {
return `${hours}:${minutes}:${seconds}`;
}
},
检测用户关闭浏览器或关闭tab
// 检测的浏览器行为
// 挂载时 定义window的onbeforeunload事件
mounted() {
let that = this;
window.onbeforeunload = function (e) {
// 如果未保存 则有关闭提示 这里的条件你可自己定义
if (!that.isSave) {
e = e || window.event;
// 兼容IE8和Firefox 4之前的版本
if (e) {
e.returnValue = "关闭提示";
}
// Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
return "关闭提示";
}
};
},
// 销毁时 定义window的onbeforeunload事件为null
destroyed() {
window.onbeforeunload = null;
},
vue检测用户离开时是否保存页面
// 只能检测路由的行为
beforeRouteLeave(to, from, next) {
if (!this.isSave) {
next(false);
let result = confirm("草稿未保存,是否退出?");
if (result) {
next();
}
} else {
next();
}
},
2021/10/12
scss变量全局引入的方法
- 在vue.config.js中设置
css: {
loaderOptions: {
sass: {
prependData: `@import "@/style/varible.scss";`
}
}
}
2021/10/30
IE与低版本webview不兼容es6导致的白屏
- 主要设置方法
- 补充
- 对于某些采用ES6语法的第三方module 需要再vue.config.js中设置对其进行转译
- 如下所示 对几个库进行转译
transpileDependencies: [ // can be string or regex /vue-echarts-v3.src.*?js$/, 'webpack-dev-server/client', /_js-base64.*?/, /_@keyrinrin_rtf-util.*?/, // '_vconsole@3.7.0@vconsole' ],
antd-vue按需引入的坑
-
创建vue项目时,选择的是sass-loader,提示缺少less-loader
- 需要安装较低版本的less-loader 否则会报错 this.getOptions is not a function
npm install less-loader@6.0.0
-
报错.bezierEasingMixin()
- 在vue.config.js中设置
module.exports = { css: { loaderOptions: { less: { lessOptions: { javascriptEnabled: true, }, }, }, }, }
2021/11/24
Vue首屏加载优化
- 接触到的原因
- 公司一个项目,首屏加载比较慢,需要优化。
- 寻找加载慢的原因
- 通过控制台查看加载的资源情况
- 资源加载的情况
- 分析原因
- chunk-vendors过大
- 背景图片过大
- 解决方法
-
使用图片压缩工具,减少png大小
-
-
vue router设置路由懒加载
-
-
部分首屏用不到的组件,设置其按需导入
-
-
2021/11/30
- 原笔迹轨迹顺滑还原的方法(利用canvas的贝塞尔曲线)
let t = 0.5; // 曲率参数0-1 经过验证0.5比较合适
/**
@params points 点数组
@params t 曲率参数
**/
function Draw(points, t = 0.5){
for (var i = 0; i < points.length - 1; i++) {
ctx.beginPath();
ctx.moveTo(points[i].x, points[i].y);
var p0 = (i > 0) ? points[i - 1] : points[0];
var p1 = points[i];
var p2 = points[i + 1];
var p3 = (i != points.length - 2) ? points[i + 2] : p2;
ctx.lineWidth = (p0.p + p1.p) / 2 * p0.width;
var cp1x = p1.x + (p2.x - p0.x) / 6 * t;
var cp1y = p1.y + (p2.y - p0.y) / 6 * t;
var cp2x = p2.x - (p3.x - p1.x) / 6 * t;
var cp2y = p2.y - (p3.y - p1.y) / 6 * t;
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, p2.x, p2.y);
ctx.stroke();
ctx.closePath();
}
}
2022/09/29
后端返回buffer, 前端下载文件
return request({
method: "POST",
responseType: "blob",
params: {
// 相关参数
},
data,
}).then((resp) => {
let content = resp.headers["content-disposition"];
let name = content && content.split(";")[1].split("filename=")[1];
let fileName = decodeURIComponent(name).slice(1, -1);
var blob = resp.data;
var downloadElement = document.createElement("a");
var href = window.URL.createObjectURL(blob);
downloadElement.href = href;
downloadElement.download = fileName;
document.body.appendChild(downloadElement);
downloadElement.click();
document.body.removeChild(downloadElement);
window.URL.revokeObjectURL(href);
});
2023/09/19
uniApp 开发安卓App相关问题
- 扫一扫相机权限
const scanCode = () => {
let hasRight = plus.navigator.checkPermission('CAMERA'); // 判断是否授权
if (hasRight != 'authorized') {
// 发起权限请求
plus.android.requestPermissions(['android.permission.CAMERA'], (e) => {
// 若无相机权限 则提示
if (e.granted.length == 0) {
uni.showToast({
title: '无相机权限',
duration: 3000,
})
} else {
scanCodeFn();
}
});
} else {
scanCodeFn();
}
};
const scanCodeFn = () => {
uni.scanCode({
onlyFromCamera: true,
success: function(res) {
console.log('条码类型:' + res.scanType);
console.log('条码内容:' + res.result);
},
fail: (error) => {
console.log("扫码失败 =>", error);
}
});
}
2023/09/20
window.Notification 浏览器通知功能
// 权限判断
if (window.Notification) {
// 浏览器通知--window.Notification
if (Notification.permission == 'granted') {
console.log('允许通知')
} else if (Notification.permission != 'denied') {
console.log('需要通知权限')
Notification.requestPermission((permission) => {})
}
} else {
console.error('浏览器不支持Notification')
}
// 发送通知的方法
setTimeout(() => {
new Notification('title', { body: 'notification body' })
}, 5000)
2023/12/04
Vue3 NavieUI DataTable组件 动态max-height属性Hook
- hook部分
import { useWindowSize, useDebounceFn } from '@vueuse/core';
const TabelThHeight = 50;
export const useTableFn = (thClass?: string, initHeight?: number) => {
initHeight = initHeight ? initHeight : 100;
thClass = thClass ? thClass : '.n-data-table-th';
const { width, height } = useWindowSize(); // 窗口宽高
const tableWrapper = ref<HTMLElement | undefined>();
const maxHeight = ref<number>(initHeight); // 表格最大高度
const reFreshFlag = ref(false); // 组件刷新用标志位
const dataLodaing = ref(false); // 数据加载loading
const getMaxHeight = () => {
reFreshFlag.value = true;
let height = tableWrapper.value?.clientHeight;
// 动态获取表头高度
let tableThHeightTemp = tableWrapper.value?.querySelector(thClass!)?.clientHeight;
let tableThHeightNow = tableThHeightTemp ? tableThHeightTemp : TabelThHeight
// 表体的最大高度为外框高度减去表头高度
maxHeight.value = height ? (height - tableThHeightNow) : initHeight!;
nextTick(() => {
reFreshFlag.value = false;
})
}
watch([
() => width.value,
() => height.value
], useDebounceFn(getMaxHeight));
onMounted(() => {
getMaxHeight();
});
return {
maxHeight,
reFreshFlag,
dataLodaing,
tableWrapper
}
}
// 此处定义了一个Hooks 用于实时刷新表体最大高度
// 首先定义了一个初始的表头高度TabelThHeight
// 之后定义了Hooks函数 useTableFn 其接受2个参数 thClass initHeight 分别代表 表头的类名(可缺) 初始表体高度(可缺)
// 若后两者参数缺省 则会使用相关默认值
// 接着 定义了三个响应式变量 tableWrapper maxHeight reFreshFlag dataLodaing 分别代表 表格父盒子 表体最大高度 组件刷新用标志位 数据加载loading
// 同时 还使用了useWindowSize函数 获取windows宽高的响应式变量 height width
// 之后我们定义一个获取当前表体最大高度的函数 getMaxHeight
// 之后 我们使用watch监听器 监听height与width,在二者之一发生变化时,调用getMaxHeight函数, 同时这里使用了useDebounceFn函数进行函数防抖处理
// 最后导出响应式变量 tableWrapper maxHeight reFreshFlag dataLodaing
// 相关页面导出此Hook后 将tableWrapper绑定在表格的父盒子的ref属性上
// 将 maxHeight reFreshFlag dataLodaing 分别绑定在表格的 max-height、v-if(v-if="!reFreshFlag")、loading上
- 页面调用
<div class="w-full h-full" ref="tableWrapper">
<!-- 组件其他属性请自行填写 -->
<n-data-table :max-height="maxHeight" v-if="!reFreshFlag" :loading="dataLodaing" />
</div>
<script setup lang="ts">
import { useTableFn } from '@/hooks'
const { maxHeight, reFreshFlag, dataLodaing, tableWrapper } = useTableFn();
</script>