vue2+Canvas-Editor 实现world在线预览和编辑

4,169 阅读3分钟
  • 公司项目迭代新功能有个模块要求实现world文档的在线预览及编辑,又是一个没有涉及到的领域,在网上找到的大部分方案都是使用付费的,那么又有一个新的问题那就是预算不够市面上类似的产品几乎都是5-6k/年,公司预算1-2k/年。最后领导发话“先给3天时间研究一下实在不行再讨论其他方案”,所以我赶紧将手头上的工作做完马不停蹄的开始找方案。
  • 很快就看到了Canvas-Editor,开开心心的打开文档结果发现它是基于V3写的且不能开箱即用要自己动手集成到项目里,而我手上的项目是几年前其他同事写的老项目用的是V2。而网上关于Canvas-Editor如何在V2中使用的文章很少,所以只能自己一点点尝试了。
  • . 首先来看一下效果图是否是你想要的,如果是那么你可以继续往下看了。

image.png

  • 已知Canvas-Editor是基于V3的那么想要在V2中使用必须要让V2项目支持V3的语法。所以第一步要先让我们的项目兼容ts。具体做法如下:
  1. 安装ts-loader(有的人可能会报错可以看看自己的node版本是不是太低我的是14.17.6,强烈推荐大家都安装一个nvm用来管理node版本非常方便!)
npm i ts-loader@8.2.0 typescript --save-dev

2.chainWebpack添加对应loader配置(vue.config.js)

config.module
    .rule('tsx')
    .test(/.tsx?$/)
    .use('ts-loader')
    .loader('ts-loader')
    .options({
        appendTsSuffixTo: [/.vue$/]
    })
    .tap(options => {
        return options;
    });

这里贴一下我代码里的截图

image.png

3.项目根目录添加tsconfig.json文件,直接复制下面的代码。

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": "node",
    "lib": ["dom","es2016"],
    "baseUrl": "./",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "src/**/*.d.ts"
  ],
  "exclude": ["node_modules"]
}

  1. 重启项目,让webpack配置生效就可以使用ts了。
  2. 开始集成,先安装 Canvas-Editor
npm i @hufe921/canvas-editor --save

6. 然后在自己的项目中新建CanvasEditor文件夹再去将官方代码下载下来。

自己的项目目录

image.png

官方目录

image.png

  1. 从官方代码中将以下文件拷贝到自己的项目中

image.png

image.png

其中 canvas.js 和 index.vue 文件是根据源代码中的 main.ts 和 index.html进行了变化, 用于服务当前的项目;

  1. 到这里就基本结束了,直接在需要用到的页面引入注册组件就可以了,下面是我的代码(可以直接复制)
<template>
  <div>
    <CanvasEditor  ref="canvasEditor" :parentContent="parentContent" @save-content="handleSaveCanvasEditorContent"/>
    <button style="width: 160px;height: 80px; border: 2px solid #2b4b6b;margin-right: 20px;" @click="handleSaveContent">保 存</button>
  </div>
</template>
  
  <script>
  import CanvasEditor from "../../../src/views/CanvasEditor/index.vue";
  export default {
    name: 'ParentComponent',
    components: {
      CanvasEditor
    },
    data() {
      return {
        parentContent:undefined, // 存放父组件传递的数据
        content:undefined, // 存放子组件数据
      }
    },
    mounted() {
      console.log("模拟父组件向后端请求数据, 传递给子组件");
      this.parentContent = {
        header:[
        ],
        main:[
          {
            value: "编号:",
            size: 14,
            bold: false,
            color: "rgb(33, 53, 71)",
            italic: false,
          },
        {
            value: "附件",
            size: 14,
            bold: false,
            color: "rgb(33, 53, 71)",
            italic: false,
          },
          
          {
            value: "父类传递的数据 通过后端获取",
            size: 40,
            bold: true,
          }
        ]
      }
    },
    methods:{
      handleSaveContent(){
        console.log("父组件保存数据时即触发点击事件,执行 saveContent 方法获取子组件的数据");
        this.$refs.canvasEditor.saveContent();
        // 将获取到的子组件数据 this.content 入库处理
      },
  
      handleSaveCanvasEditorContent(data){
        console.log("从子组件接收到的数据:", data);
        // 将data数据转换为 json 格式的数据, 方便入库处理
        this.content = JSON.stringify(data);
        console.log("转换后的数据 this.content 为: ", this.content)
      }
    },
  }
  </script>
  
  1. 到这里前端页面的展示及编辑就彻底结束了,但是还有一个令人头疼的问题那就是后端要传给我以及前端保存后传给后端的数据结构不是我们往常使用的数据流而是一个json串,导致这个文档预览编辑后无法下载。这个我们目前还在商议中如果大家有好的想法请及时告知我们,非常感谢!