博客的图片点击放大是很常见的需求. 今天突发奇想有了实现这个功能的思路, 就先把它撸出来吧.
首先这个博客系统用的是markdown语法, 解析成html后得到一堆html字符串. 由于要在<img>上绑定事件, 就不可以简单的v-html插入了, 于是转换另一种思路实现.
捉摸了一下, 由于<img/>
不是固定的, 于是需要动态绑定, 而动态构建和动态组件可以让我实现这一功能.
以下是实现方法.
# 1. 创建模板字符串
const pattern = new RegExp('src=(\'.+\'|".+")');
const html = `${parser
.makeHtml(res.content) //原本的markdown字符串
.split(/[ ]/) //空格分开
.map(el => { //分开后遍历 寻找img标签
//正则匹配
if(pattern.test(el)) {
const urls = el.split('=');
const url = urls[urls.length - 1].substr(1, urls[urls.length - 1].length - 2);
// eslint-disable-next-line no-param-reassign
// 绑定事件
return `${el} @click="showImgDialog('${url};)"`;
}
//不是img标签则直接返回
return el;
})
.join(' ') //重新拼接成字符串
}
//增加模态框
<el-dialog
:visible.sync="dialog.visible"
width="80%">
<el-row type="flex" justify="center">
<span>
<img :src="dialog.url"/>
</span>
</el-row>
</el-dialog>`;
# 2. 构建组件
//构建
const compiled = Vue.compile(`<div>${html}</div>`);
const cmp = {
data() {
return {
dialog: {
url: '',
visible: false,
},
};
},
render: compiled.render,
staticRenderFns: compiled.staticRenderFns,
methods: {
showImgDialog(url) {
this.dialog = {
url,
visible: true,
};
},
},
};
//注册组件
this.component = Vue.component('htmlContent', cmp);
# 3. 使用
利用动态组件插入这个动态构建的组件就OK拉
<component v-bind:is="component " class="html-content" v-highlight/>
效果图, 直接点开有图片的博客就可以预览了