工作中遇到了一个问题,需要对接口返回的数据进行处理。
接口返回的:
<img src="http://www.test.com/1.png" ... />你好<img src="http://www.test.com/2.png" ... />你好,你好
实际需要的:
<ImgMsg url="http://www.test.com/1.png" />你好<ImgMsg url="http://www.test.com/2.png" />你好,你好
思考后,想到了一种方式,借助component
,将img替换为自己封装的ImgMsg组件(包含了占位图、算出最佳合适显示比例、预览功能等功能)。
具体实现需要进行如下步骤:
1. 配置项
// vue.config.js
module.exports = {
...
/* 是否使用包含运行时编译器的 Vue 构建版本。设置为 true 后你就可以在 Vue 组件中使用 template 选项了,但是这会让你的应用额外增加 10kb 左右。(默认false) */
runtimeCompiler: true,
}
2. 全局注册
// components/Common/index.js
import Vue from 'vue'
imoort ImgMsg from '@/components/ImgMsg'
const components = [ImgMsg];
components.forEach(component => {
Vue.component(component.name, component);
});
3. 组件中使用
<!-- MassMsg.vue -->
<template>
<div>
<component :is="massMsg"></component>
</div>
</template>
<script>
export default {
name: 'massMsg',
data() {
return {
regImg: /<img((?!class="biaoqing").)*?>/gi,
regDataSrc: /data-src="(.*?)"/,
};
},
props: {
item: {
type: Object,
default: () => {}
}
},
computed: {
massMsg() {
const msg = this.item.content.replace(this.regImg, result => {
let groups = this.regDataSrc.exec(result);
if (groups) {
return '<ImgMsg url="' + groups[1] + '"></ImgMsg>';
}
return result;
});
return {
template: `<div>${msg}</div>`
};
}
}
};
</script>
附:
ImgMsg组件代码
<!-- ImgMsg.vue -->
<template>
<img class="el-common-img" :src="imgSrc" @click="setPicPreviewVisible(url)" @load="loadImg($event, url)" @error="loadError" />
</template>
<script>
import M from '@store/mutations';
import imgLoading from '@assets/images/loading.gif';
import loadError from '@assets/images/loadError.png';
export default {
name: 'imgMsg',
data() {
return {
ImgMaxWidth: 170,
ImgMaxHeight: 170,
imgSrc: imgLoading
};
},
props: {
url: {
type: String,
default: ''
}
},
watch: {
url(newVal) {
if (newVal) this.imgSrc = newVal;
}
},
methods: {
/**
* 处理图片消息显示大小
*/
loadImg(e, url) {
let imgTarget = e.target,
img = document.createElement('img');
img.onload = e => {
let target = e.target;
let { w, h } = this.getImgSize(this.ImgMaxWidth, this.ImgMaxHeight, target.width, target.height);
imgTarget.width = w;
imgTarget.height = h;
this.imgSrc = url;
};
img.src = url || '';
},
getImgSize(mw, mh, w, h) {
if (w > mw && h <= mh) {
// 图片宽度大于最大值
h *= mw / w;
w = mw;
} else if (w <= mw && h > mh) {
// 图片宽度小于等于最大值
w *= mh / h;
h = mh;
} else if (w > mw && h > mh) {
// 图片宽度和高度均大于最大值
if (w / h >= mw / mh) {
// 宽高比大于默认比例
h *= mw / w;
w = mw;
} else {
// 宽高比小于等于默认比例
w *= mh / h;
h = mh;
}
}
return { w, h };
},
/**
* 预览图片
*/
setPicPreviewVisible(url) {
this.$store.commit(M.Chat.setPicPreviewVisible, true);
this.$store.commit(M.Chat.setPicPreviewSrc, url);
},
/**
* 加载错误占位图片
*/
loadError() {
this.imgSrc = loadError;
}
}
};
</script>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。