Skip to content

卡片

效果

流程

  1. 安装插件 yarn add @wangeditor/plugin-link-card

  2. 注册

js
import { Boot } from "@wangeditor/editor";
import linkCardModule from "@wangeditor/plugin-link-card";

// 注册。要在创建编辑器之前注册,且只能注册一次,不可重复注册。
Boot.registerModule(linkCardModule);
  1. 配置
js
import { IEditorConfig } from "@wangeditor/editor";

const editorConfig: Partial<IEditorConfig> = {
  hoverbarKeys: {
    // 在编辑器中,选中链接文本时,要弹出的菜单
    link: {
      menuKeys: [
        "editLink",
        "unLink",
        "viewLink", // 默认的配置可以通过 `editor.getConfig().hoverbarKeys.link` 获取
        "convertToLinkCard", // 增加 '转为链接卡片'菜单
      ],
    },
  },

  MENU_CONF: {
    // '转为链接卡片'菜单的配置
    convertToLinkCard: {
      // 自定义获取 link-card 信息,可选
      // 返回 { title, iconImgSrc }
      async getLinkCardInfo(linkText: string, linkUrl: string) {
        // 1. 可通过 iframe 加载网页,然后获取网页 title 和其中的图片
        // 2. 服务端获取(有些网页会设置 `X-Frame-Options` ,无法通过 iframe 加载)
        // // 模拟异步返回
        // return new Promise(resolve => {
        //   setTimeout(() => {
        //     const info = { title: linkText, iconImgSrc: '' }
        //     resolve(info)
        //   }, 100)
        // })
      },
    },

    // 其他...
  },

  // 其他...
};

显示 HTML

html
<div
  data-w-e-type="link-card"
  data-w-e-is-void
  data-title="百度新闻"
  data-link="http://news.baidu.com/"
  data-iconImgSrc="https://news-bos.cdn.bcebos.com/mvideo/log-news.png"
>
  <div class="info-container">
    <div class="title-container">
      <p>百度新闻</p>
    </div>
    <div class="link-container"><span>http://news.baidu.com/</span></div>
  </div>
  <div class="icon-container">
    <img src="https://news-bos.cdn.bcebos.com/mvideo/log-news.png" />
  </div>
</div>

渲染样式

css
div[data-w-e-type="link-card"] {
  width: 450px;
  margin: 0 auto;
  background-color: #f1f1f1;
  border-radius: 10px;
  display: flex;
  padding: 10px 20px;
  cursor: pointer;
}
div[data-w-e-type="link-card"] .info-container {
  flex: 1;
  padding-right: 20px;
}
div[data-w-e-type="link-card"] .info-container p {
  margin-top: 5px;
  font-weight: bold;
}
div[data-w-e-type="link-card"] .info-container span {
  opacity: 0.5;
}
div[data-w-e-type="link-card"] .icon-container {
  width: 64px;
  overflow: hidden;
}
div[data-w-e-type="link-card"] .icon-container img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

代码

vue
<template>
  <div style="border: 1px solid #ccc">
    <Toolbar
      style="border-bottom: 1px solid #ccc"
      :editor="editorRef"
      :defaultConfig="toolbarConfig"
      :mode="mode"
    />
    <Editor
      style="height: 500px; overflow-y: hidden"
      v-model="valueHtml"
      :defaultConfig="editorConfig"
      :mode="mode"
      @onCreated="handleCreated"
    />
  </div>
  <button @click="getcontent">提交</button>
</template>

<script setup lang="ts">
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
import { onBeforeUnmount, ref, shallowRef, onMounted } from "vue";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { Boot, IEditorConfig } from "@wangeditor/editor";
import linkCardModule from "@wangeditor/plugin-link-card";

// 编辑器实例,必须用shallowRef包裹

const editorRef = shallowRef();

// 内容HTML

const valueHtml = ref("<p>hello</p>");

// 编辑器模式

const mode = ref("default"); // simple或者default;

// 模拟ajax异步获取数据内容

onMounted(() => {
  setTimeout(() => {
    valueHtml.value = "<p>模拟 Ajax 异步设置内容</p>";
  }, 1500);
});

// 工具栏配置

const toolbarConfig = {};

// 编辑器配置

const editorConfig = {
  placeholder: "请输入内容...",
  hoverbarKeys: {
    // 在编辑器中,选中链接文本时,要弹出的菜单
    link: {
      menuKeys: [
        "editLink",
        "unLink",
        "viewLink", // 默认的配置可以通过 `editor.getConfig().hoverbarKeys.link` 获取
        "convertToLinkCard", // 增加 '转为链接卡片'菜单
      ],
    },
  },
  MENU_CONF: {
    convertToLinkCard: {},
  },
};

editorConfig.MENU_CONF["convertToLinkCard"] = {
  // 自定义获取 link-card 信息,可选
  // 返回 { title, iconImgSrc }
  async getLinkCardInfo(linkText: string, linkUrl: string) {
    // 1. 可通过 iframe 加载网页,然后获取网页 title 和其中的图片
    // 2. 服务端获取(有些网页会设置 `X-Frame-Options` ,无法通过 iframe 加载)
    // // 模拟异步返回
    return new Promise((resolve) => {
      setTimeout(() => {
        const info = { title: linkText, iconImgSrc: "" };
        resolve(info);
      }, 100);
    });
  },
};

// 组件销毁的时候,也即时 销毁编辑器

onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});

// 编辑器示例

const handleCreated = (editor: any) => {
  editorRef.value = editor; // 记录editor实例
};

// 获取到编辑器内容

const getcontent = () => {
  console.log(valueHtml.value);
  window.alert(valueHtml.value);
};

// 仅仅注册一次

Boot.registerModule(linkCardModule);
</script>

<style lang="scss" scoped></style>