在 Vue 中要求 v-html 中的图像

Require image inside v-html in Vue

我正在使用 Tiptap 编辑器编写内容,然后通过 v-html 指令附加由它生成的数据。

我知道 v-html 可以处理像 'https://something/file.jpg' 这样具有绝对来源的图像,但我需要一个通过 Webpack 并在其名称中获取哈希值的图像。并且要求图像似乎在 v-html 中不起作用。有人解决过这样的问题吗?

更新 代码如下:

<div v-html="someData"></div>

someData 作为对异步请求的响应出现,看起来像这样:

<p> kjfdkf </p> <p> kfdfk </p> <div> kdfjdkf </div>

这是文本编辑器的标准输出。为了不使用标签显示它,我将它传递给 v-html。问题是如何处理通过 webpack 的图像。我不知道。

我不确定我是否正确理解了你的问题,但考虑到你有一个像这样的 HTML 字符串:

<p> kjfdkf </p>
<img src="PATH" />
<p> kfdfk </p> 
<img src="PATH" /> 
<div> kdfjdkf </div>

...内部有随机图像元素,您可能可以解析 HTML 以将图像元素的来源更改为其原始数据,而不是当前的相对路径。

DOMParser 似乎是解析 HTML 最简单的选项,因为您可以在一行中解析它:

let el = new DOMParser().parseFromString(this.html, "text/html");

然后找到所有图像元素:

let imgs = el.getElementsByTagName("img");

...将其来源更改为原始形式:

imgs.forEach((img) => (img.src = require(img.src)));

...select el 的正文(因为那是你的 HTML 所在的位置):

let body = el.body;

...并且return其内部HTML:

return body.innerHTML;

你可以将这一切包装在一个计算 属性:

computed: {
  processedHtml() {
    let el = new DOMParser().parseFromString(this.html, "text/html"),
      imgs = el.getElementsByTagName("img");
    imgs.forEach((img) => (img.src = require(img.src)));
    let body = el.body;
    return body.innerHTML;
  },
}

完整代码如下:

<template>
  <div id="app">
    <div v-html="processedHtml"></div>
  </div>
</template>

<script>

export default {
  name: "App",
  data() {
    return {
      html: `<p> kjfdkf </p><img src="PATH" /> <p> kfdfk </p> <img src="PATH" /> <div> kdfjdkf </div>`,
    };
  },
  computed: {
    processedHtml() {
      let el = new DOMParser().parseFromString(this.html, "text/html"),
        imgs = el.getElementsByTagName("img");
      imgs.forEach((img) => (img.src = require(img.src)));
      let body = el.body;
      return body.innerHTML;
    },
  },
};
</script>

或者,如果您将图像移动到您的 public 目录,它们的名称将不会被 webpack 修改,因此您可以避免这一切。

我不得不在 marsnebulasoup 的回答中添加一点

首先,当我们在 Tiptap 编辑器中保存图像源时,如果我输入 @/assets/img/someImg.jpg,它会将其保存为 'http://localhost:8080/@/assets/img/someImg.jpg',这不是我想要的。所以我添加了一行来提取图像名称:

const src = img.src.slice(img.src.lastIndexOf('/') + 1);

第二个require不接受变量,所以我没能做到

imgs.forEach((img) => (img.src = require(img.src)));

我不得不这样做:

const imgSrc = require(`@/assets/img/${src}`);
img.src = imgSrc;