什么是IDE?

集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器调试器和图形用户界面等工具。

我们这里指的IDE其实是指富文本编辑器。

富文本编辑器的分类

相信很多人都使用过多种富文本编辑器
富文本编辑器常用于编辑博客、用户交互,富文本编辑器分为两种:
所见即所得、非所见即所得。当然,两种富文本编辑器的实现原理是不相同的。

所见即所得富文本编辑器

这种编辑器的实现原理很简单,用textarea元素就可以实现,假如要实现粗体、斜体、下划线、颜色字、图片的效果,只需在字的中间加上自定义标签即可。

例如:
[b]富文本编辑器[b] ,[img]src=”http://www.google.com.hk/intl/zh-CN/images/logo_cn.png
[img]当然这些规则你得自己通过js进行定制,当POST提交后,再把这些标签转换为html标签。

非所见即所得富文本编辑器

前面提到的效果,我们无法在textarea中见到立竿见影的效果(所见即所得),而文本域本身也只是支持一些字符的输入,并不支持显示html。

富文本编辑器实现原理

如何做到编辑像文本域,又能够即时所见呢?答案就是使用iframe作为内容编辑区域。iframe本身也是一个嵌套页面,它如何能够被编辑呢?这里有一些关键的属性,它们可以做到让iframe可以被编辑。

  1. <!DOCTYPE HTML>
  2. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>KF富文本编辑器</title>
  6. <script type="text/javascript" src="jquery.min.js">
  7. </script>
  8. <script type="text/javascript">
  9. $(function () {
  10. $d = $("#editor")[0].contentWindow.document; // IE、FF都兼容
  11. $d.designMode = "on";
  12. $d.contentEditable = true;
  13. $d.open();
  14. $d.close();
  15. $("body", $d).append("<div>A</div><div>B</div><div>C</div>");
  16. $('#insert_img').click(function () {
  17. // 在iframe中插入一张图片
  18. var img = '<img src="' + $('#path').val() + '" />';
  19. $("body", $d).append(img);
  20. });
  21. $('#preview').click(function () {
  22. // 获取iframe的body内容,用于显示或者插入到数据库
  23. alert($('#editor').contents().find('body').html());
  24. $('#preview_area').html($('#editor').contents().find('body').html());
  25. });
  26. });
  27. </script>
  28. </head>
  29. <body>
  30. <p><iframe id="editor" width="600px" height="200px" style="border:solid 1px;"></iframe></p>
  31. <input type="text" id="path" value="http://www.google.com.hk/intl/zh-CN/images/logo_cn.png" />
  32. <input type="button" id="insert_img" value="插入图片" />
  33. <input type="button" id="preview" value="预览" />
  34. <p style="border: 1px dashed #ccc;" id="preview_area"></p>
  35. </body>
  36. </html>

代码关键点:

  • designMode属性为 “on”
  • contentEditable属性为 “true”,让iframe可编辑

效果如下图:
201112210019429412.png

原型展示

实训平台在线IDE效果原型:
20180904192321893.png

功能介绍

Vue-Quill-Editor

🍡Quill editor component for Vue, support SPA and SSR.

  • 基于 Quill
  • 适用于 Vue 的富文本编辑器
  • 支持服务端渲染
  • 支持单页应用。

    开发环境

  • Chrome

  • Cmder
  • Electron: 9.3.3
  • Chrome: 83.0.4103.122
  • Node.js: 12.14.1
  • V8: 8.3.110.13-electron.0
  • OS: Darwin x64 20.1.0

    开发流程

  1. 下载vue-quill-editor

    1. npm install vue-quill-editor --save
  2. 下载quill(vue-quill-editor所需依赖)

    1. npm install quill --save
  3. 代码

    1. <template>
    2. <div class="edit_container">
    3. <quill-editor
    4. v-model="content"
    5. ref="myQuillEditor"
    6. :options="editorOption"
    7. @blur="onEditorBlur($event)" @focus="onEditorFocus($event)"
    8. @change="onEditorChange($event)">
    9. </quill-editor>
    10. </div>
    11. </template>
    12. <script>
    13. import { quillEditor } from "vue-quill-editor"; //调用编辑器
    14. import 'quill/dist/quill.core.css';
    15. import 'quill/dist/quill.snow.css';
    16. import 'quill/dist/quill.bubble.css';
    17. export default {
    18. components: {
    19. quillEditor
    20. },
    21. data() {
    22. return {
    23. content: `<p></p><p><br></p><ol><li><strong><em>Or drag/paste an image here.</em></strong></li><li><strong><em>rerew</em></strong></li><li><strong><em>rtrete</em></strong></li><li><strong><em>tytrytr</em></strong></li><li><strong><em>uytu</em></strong></li></ol>`,
    24. editorOption: {}
    25. }
    26. },
    27. methods: {
    28. onEditorReady(editor) { // 准备编辑器
    29. },
    30. onEditorBlur(){}, // 失去焦点事件
    31. onEditorFocus(){}, // 获得焦点事件
    32. onEditorChange(){}, // 内容改变事件
    33. },
    34. computed: {
    35. editor() {
    36. return this.$refs.myQuillEditor.quill;
    37. },
    38. }
    39. }
    40. </script>
  4. 自定义toolbar

    1. {
    2. placeholder: "请在这里输入",
    3. modules:{
    4. toolbar:[
    5. ['bold', 'italic', 'underline', 'strike'], //加粗,斜体,下划线,删除线
    6. ['blockquote', 'code-block'], //引用,代码块
    7. [{ 'header': 1 }, { 'header': 2 }], // 标题,键值对的形式;1、2表示字体大小
    8. [{ 'list': 'ordered'}, { 'list': 'bullet' }], //列表
    9. [{ 'script': 'sub'}, { 'script': 'super' }], // 上下标
    10. [{ 'indent': '-1'}, { 'indent': '+1' }], // 缩进
    11. [{ 'direction': 'rtl' }], // 文本方向
    12. [{ 'size': ['small', false, 'large', 'huge'] }], // 字体大小
    13. [{ 'header': [1, 2, 3, 4, 5, 6, false] }], //几级标题
    14. [{ 'color': [] }, { 'background': [] }], // 字体颜色,字体背景颜色
    15. [{ 'font': [] }], //字体
    16. [{ 'align': [] }], //对齐方式
    17. ['clean'], //清除字体样式
    18. ['image','video'] //上传图片、上传视频
    19. ]
    20. }
    21. }
  5. 存储编码

    1. function escapeStringHTML(str) {
    2. str = str.replace(/&lt;/g,'<');
    3. str = str.replace(/&gt;/g,'>');
    4. return str;
    5. }

    技术点和解决方案

    兼容

  • ie10+
  • chrome 22+
  • safari 35+
  • firefox 8+

    性能

  • 全局引入 ```javascript import Vue from ‘vue’ import VueQuillEditor from ‘vue-quill-editor’

// require styles import ‘quill/dist/quill.core.css’ import ‘quill/dist/quill.snow.css’ import ‘quill/dist/quill.bubble.css’

Vue.use(VueQuillEditor, / { default global options } /)

  1. - 局部引入
  2. ```javascript
  3. import 'quill/dist/quill.core.css'
  4. import 'quill/dist/quill.snow.css'
  5. import 'quill/dist/quill.bubble.css'
  6. import { quillEditor } from 'vue-quill-editor'
  7. export default {
  8. components: {
  9. quillEditor
  10. }
  11. }
  • 按需加载
    1. npm i --save babel-plugin-import

服务器渲染

根据环境配置SSR:

  1. if (process.browser) {
  2. const VueQuillEditor = require('vue-quill-editor/dist/ssr')
  3. Vue.use(VueQuillEditor, /* { default global options } */)
  4. }

直接上代码:

  1. <template>
  2. <!-- bidirectional data binding(双向数据绑定) -->
  3. <div class="quill-editor"
  4. v-model="content"
  5. v-quill:myQuillEditor="editorOption">
  6. </div>
  7. <!-- Or manually control the data synchronization(手动控制数据流) -->
  8. <div class="quill-editor"
  9. :content="content"
  10. @change="onEditorChange($event)"
  11. v-quill:myQuillEditor="editorOption">
  12. </div>
  13. </template>
  14. <script>
  15. export default {
  16. data() {
  17. return {
  18. content: '<p>example content</p>',
  19. editorOption: { /* quill options */ }
  20. }
  21. },
  22. mounted() {
  23. console.log('this is current quill instance object', this.myQuillEditor)
  24. },
  25. methods: {
  26. onEditorChange(event) {
  27. console.log('onEditorChange')
  28. }
  29. },
  30. }
  31. </script>

总结