使用的vue2.x版本,UI框架为ant design vue 1.X版本
遇到技术点记录
1.场景:使用a-form-model组件里根据页面类型单选,切换输入框为页面、外部链接、动态表单,其中输入框是使用if进行判断显示隐藏,但页面类型为页面时a-form-model-item有prop自定义校验,而另外两个单选是没有prop校验的
难点为:切换页面类型单选,页面输入框的prop的校验没有去掉,
目的:切换页面类型去掉指定输入框页面的prop自定义校验提示
页面类型为:页面 (页面是input输入框有prop的自定义校验)
页面类型为:外部链接 (外部链接是input输入框没有校验)
页面类型为:动态表单(动态表单是select选择框没有校验)
解决方案:给 a-form-model-item有prop自定义校验的代码里增加 ref=“refsPath”,然后使用clearValidate()去掉单行指定输入框的校验
//增加if判断是为了防止dom节点未渲染而执行了clearValidate()
if (this.$refs.refsPath != undefined) this.$refs.refsPath.clearValidate()
2.场景:下载 阿里的iconfont某个,使用svg图标,
目的:下载某个svg文件后引入到项目,使用a-icon引用显示,利用 Icon 组件封装一个可复用的自定义图标。可以通过 component 属性传入一个组件来渲染最终的图标,以满足特定的需求。
template标签里的内容
<a-icon :component="WorkIcon" :style="{ fontSize: '20px', color: '#8d8f95' }" />
script标签里的内容
<script>
import WorkIcon from '@/assets/icons/workIcon.svg?inline'
export default {
data() {
return{
WorkIcon
}
}
}
</script>
注意点:Icon 组件中图标渲染的优先级为 component > children > type, 传入 props 时,优先级高的直接生效,优先级低的则失效。
3.场景:iframe标签打开文件链接,因为网络问题及文件较大,请求时页面会显示空白,这时需要加一些动画特效
目的:监听iframe标签内部事件
template标签里的内容
<a-spin
:spinning="isPreviewSpin"
size="large"
tip="正在请求中,请稍等..."
:style="{ height: iframeHeight, top: iframeTop }"
>
<iframe
class="iframe-page-main"
ref="iframe"
:src="filePreview.frameSrc"
:style="{ height: iframeHeight }"
></iframe>
</a-spin>
script标签里的内容
<script>
import WorkIcon from '@/assets/icons/workIcon.svg?inline'
export default {
data() {
return{
//动画loading居中
iframeTop: '25%',
//预览状态
isPreviewSpin: false,
//赋值iframe的高度
iframeHeight: document.documentElement.clientHeight - 50 + 'px',
// 文件预览
filePreview: {
visible: false,
title: '文件预览',
frameSrc: 'http://124.70.15.209/admin-h5/pages/filePreview/index?suffix=png&previewSrc=%2Fmicro-test%2Ffamily%2Fabc333%2F%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20220509100716_20221015142600057.png',
},
}
}
created() {
this.iframeLoad()
}
methods:{
//监听iframe标签里onload事件,执行停止loading动画
iframeLoad() {
this.isPreviewSpin = true
//this.$nextTick等待dmo渲染完成
this.$nextTick(() => {
const iframe = this.$refs.iframe
//以下是重点代码
if (iframe.attachEvent) {
//iE
iframe.attachEvent('onload', () => {
this.isPreviewSpin = false
this.iframeTop = '0'
})
} else {
iframe.onload = () => {
this.isPreviewSpin = false
this.iframeTop = '0'
}
}
})
},
}
}
</script>
4.vue 重置 data()中的数据 Object.assign(this. d a t a , t h i s . data, this. data,this.options.data())
5.H5 禁止浏览器下拉刷新以及左右滑动(适用于移动端签名手写板)
// #ifdef H5 H5 禁止浏览器下拉
document.body.addEventListener("touchmove",
function (e) {
e.preventDefault();
},{ passive: false });
// #endif
6.base64 图片旋转
// src 是 base64 ,edg 是旋转的角度需要是 90 的倍数
rotateBase64Img(src, edg) {
return new Promise((resolve) => {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var imgW; //图片宽度
var imgH; //图片高度
var size; //canvas初始大小
if (edg % 90 != 0) {
console.error("旋转角度必须是90的倍数!");
throw "旋转角度必须是90的倍数!";
}
edg < 0 && (edg = (edg % 360) + 360);
const quadrant = (edg / 90) % 4; //旋转象限
const cutCoor = { sx: 0, sy: 0, ex: 0, ey: 0 }; //裁剪坐标
var image = new Image();
image.crossOrigin = "anonymous";
image.src = src;
image.onload = function () {
imgW = image.width;
imgH = image.height;
size = imgW > imgH ? imgW : imgH;
canvas.width = size * 2;
canvas.height = size * 2;
switch (quadrant) {
case 0:
cutCoor.sx = size;
cutCoor.sy = size;
cutCoor.ex = size + imgW;
cutCoor.ey = size + imgH;
break;
case 1:
cutCoor.sx = size - imgH;
cutCoor.sy = size;
cutCoor.ex = size;
cutCoor.ey = size + imgW;
break;
case 2:
cutCoor.sx = size - imgW;
cutCoor.sy = size - imgH;
cutCoor.ex = size;
cutCoor.ey = size;
break;
case 3:
cutCoor.sx = size;
cutCoor.sy = size - imgW;
cutCoor.ex = size + imgH;
cutCoor.ey = size + imgW;
break;
}
ctx.translate(size, size);
ctx.rotate((edg * Math.PI) / 180);
ctx.drawImage(image, 0, 0);
var imgData = ctx.getImageData(
cutCoor.sx,
cutCoor.sy,
cutCoor.ex,
cutCoor.ey
);
if (quadrant % 2 == 0) {
canvas.width = imgW;
canvas.height = imgH;
} else {
canvas.width = imgH;
canvas.height = imgW;
}
ctx.putImageData(imgData, 0, 0);
resolve({ data: canvas.toDataURL() });
};
});
},
7.判断图片链接是否为无效链接
在util.js文件封装
export const checkImgExists = (imgurl) => {
return new Promise(function (resolve, reject) {
var ImgObj = new Image()
ImgObj.src = imgurl
ImgObj.onload = function (res) {
resolve(res)
}
ImgObj.onerror = function (err) {
reject(err)
}
})
}
在vue页面使用
<script>
import { checkImgExists } from '@/utils/util'
export default {
methods:{
checkImgExists(imgUrl)
.then(() => {
console.log('有效链接')
})
.catch(() => {
console.log('无效链接')
})
}
}
</script>
8.文件链接转文件流下载–主要针对pdf 解决谷歌浏览器a标签下载pdf直接打开的问题
在util.js文件封装
/**
* 文件链接转文件流下载--主要针对pdf 解决谷歌浏览器a标签下载pdf直接打开的问题
* @param url :文件链接
* @param fileName :文件名;
* @param type :文件类型;
*/
export const fileLinkToStreamDownload = (url, fileName, type) => {
var xhr = new XMLHttpRequest()
xhr.open('get', url, true)
xhr.setRequestHeader('Content-Type', `application/${type}`)
xhr.responseType = 'blob'
xhr.onload = function () {
if (this.status == 200) {
//接受二进制文件流
var blob = this.response
downloadExportFile(blob, fileName, type)
}
}
xhr.send()
}
/**
*下载导出文件
* @param blob :返回数据的blob对象或链接
* @param tagFileName :下载后文件名标记
* @param fileType :文件类 word(docx) excel(xlsx) ppt等
*/
export const downloadExportFile = (blob, tagFileName, fileType) => {
var downloadElement = document.createElement('a')
var href = blob
if (typeof blob == 'string') {
downloadElement.target = '_blank'
} else {
href = window.URL.createObjectURL(blob) //创建下载的链接
}
downloadElement.href = href
if (fileType) {
downloadElement.download = tagFileName + '.' + fileType //下载后文件名
} else {
downloadElement.download = tagFileName //下载后文件名
}
document.body.appendChild(downloadElement)
downloadElement.click()
//点击下载
document.body.removeChild(downloadElement) //下载完成移除元素
if (typeof blob != 'string') {
window.URL.revokeObjectURL(href) //释放掉blob对象
}
}
在vue页面使用
<script>
import { fileLinkToStreamDownload } from '@/utils/util'
export default {
created(){
fileLinkToStreamDownload('这里输入url链接', '文件填文件名称', '这里填文件类型,比如png')
}
}
</script>
9.防抖函数
在util.js文件封装
// 防抖函数
export function debounce(fn, delay = 300) {
//默认300毫秒
var timer
return function () {
var args = arguments
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, args) // this 指向vue
}, delay)
}
}
在vue页面使用
<script>
import { debounce } from '@/utils/util'
export default {
methods:{
//防抖调用引擎页面的显隐
treeNodeModelShow: debounce(function () {
//延迟500毫秒执行方法,500入参可以根据需求替换
}, 500),
}
}
</script>