[Vue JS] toast ui editor 사용하기

유나니·2020년 10월 10일
1

vue_til

목록 보기
7/7
post-custom-banner

toast.png_1597826057297

Intro

NHN이 제공하는 toast ui 에디터를 vue에 붙여보고자 한다. 기본적인 마크다운 에디터는 물론 syntex highlight 기능, 드래그앤드랍 이미지 업로드 등의 플러그인과 훅을 지원하니 게시판 형태의 프로젝트를 진행할 때 사용하기 좋다.

설치

$ npm i @toast-ui/editor --save
$ npm install @toast-ui/editor-plugin-code-syntax-highlight

2버전 이후부터는 플러그인은 별도 설치가 필요하게 업데이트 되었기 때문에 플러그인 역시 설치해주어야 한다.

그 외 차트 그리기 등 다양한 플러그인은 공식 홈페이지를 참조하길 바란다.

Vue에 적용하기

에디터(editor.vue)

템플릿
<template>
	<div id="editor"/>
  <button id="submit">submit</button>
</template>

다음과 같이 에디터 클래스가 적용될 div를 잡아주어야 한다.

script

dependancy

import 'codemirror/lib/codemirror.css'; // codemirror 스타일
import '@toast-ui/editor/dist/toastui-editor.css'; // Editor's Style
import Editor from '@toast-ui/editor';
import 'highlight.js/styles/github.css'; // code block highlight 스타일

// toast ui 설치 시 highlight js 역시 자동으로 설치된다.
import codeSyntaxHightlight from '@toast-ui/editor-plugin-code-syntax-highlight';
import hljs from 'highlight.js';

mounted hook

  • 가상 DOM이 마운트 되는 시점에 모듈화된 에디터를 불러온다.
  • 에디터 설정들을 함께 정의해주고 버튼 클릭 시 에디터에 적힌 마크다운 내용 그대로를 부모 컴포넌트로 넘겨준다.
mounted() {
    const editor = new Editor({
      el: document.querySelector("#editor"),
      initialEditType: "markdown",
      previewStyle: "vertical",
      height: "500px",
      plugins: [[codeSyntaxHightlight, { hljs }]],
      hooks: {
        // 이미지 드래그앤 드랍 시 작동할 콜백 함수를 정의한다.
        // 드래그인 드랍 시 스토리지 저장 방법은 파이어베이스 포스팅 참조
        addImageBlobHook: (blob, callback) => {}
      }
      const btn = document.querySelector("#submit")
      btn.addEventListener("click", () => {
        const editContent = editor.getMarkdown()
        this.$emit("submitContent",editContent)
      })
    })
  }

ArticleCreate.vue

  • 사용자가 작성한 내용을 넘겨받아 백앤드와 협의된 형식으로 비동기 요청을 전송한다.
<div class="editor">
  <Editor @submitContent="submitArticle" />
</div>

<script>
  import Editor from "@/components/Editor.vue";
  ...
  methods: {
    submitArticle(data) {
      this.content.content = data;

      var preview = validateMarkdown(data);
      const params = {
        nickname: this.$store.state.nickname,
        title: this.content.title,
        content: this.content.content,
        keyword: this.content.keywords,
        preview: preview,
        ispublic: this.content.ispublic
      };
      // 이후 백앤드로 비동기 요청을 위한 코드를 작성한다. 
  }
</script>

뷰어(articleDetail.vue)

뷰어에서 주의해야 할 점은 DB에서 게시글을 불러오는 요청은 비동기 요청이라는 것이다. 따라서 뷰어를 불러오는 시점에 내용이 아직 들어오지 않았다면 반드시 에러가 발생한다.

이를 방지하기 위해서는 (1) 비동기로 데이터를 불러오고 해당 데이터가 완전히 DOM의 데이터에 붙은 이후에 (2) 뷰어를 마운트 해야 한다.

template

<template>
  <div v-if='article'>
    <div id="viewer"/>
  </div>
</template>

script

import '@toast-ui/editor/dist/toastui-editor-viewer.css';
import 'highlight.js/styles/github.css';
import Viewer from '@toast-ui/editor/dist/toastui-editor-viewer';
import codeSyntaxHightlight from '@toast-ui/editor-plugin-code-syntax-highlight';
import hljs from 'highlight.js';

mounted: {
  getViewer() {
      this.getArticle().then((res) => {
        new Viewer({
          el: document.querySelector('#viewer'),
          // 표시하고자 하는 내용은 여기에 들어간다.
          initialValue: res,
          plugins: [[codeSyntaxHightlight, { hljs }]],
        });
      });
    },
}
profile
User First, Mobile Friendly
post-custom-banner

0개의 댓글