这款国外开源框架, 让你轻松构建自己的页面编辑器

开源
乍眼一看我们可能会认为它只是一个页面/HTML 编辑器,但它能做的不仅仅如此。GrapesJS 是一个多用途的 Web 页面搭建框架,这意味着它允许我们轻松创建一个支持拖放的任何具有类似 HTML 结构的构建器。它所包含的内容远不止网页。

[[416380]]

按照我一向的写作风格,我会在下面列出文章的大纲,以便大家有选择且高效率的阅读和学习:

  • GrapesJS 框架基本介绍
  • 如何使用 GrapesJS 构建 web 编辑器
  • 基于 GrapesJS 构建的开源网页编辑器 craft.js
  • 更多可视化编辑器推荐

基本介绍

chrome-capture.gif

乍眼一看我们可能会认为它只是一个页面/HTML 编辑器,但它能做的不仅仅如此。GrapesJS 是一个多用途的 Web 页面搭建框架,这意味着它允许我们轻松创建一个支持拖放的任何具有类似 HTML 结构的构建器。它所包含的内容远不止网页。我们使用类似 HTML 的结构的场景有:

  • 时事通讯(例如 MJML)
  • 原生移动应用程序(例如 React Native)
  • 本机桌面应用程序(例如 Vuido)
  • PDF (例如 React PDF)

并且 GrapesJS 附带的功能和工具使我们能够制作易于使用的编辑器。这使用户无需任何编码知识即可创建复杂的类似 HTML 的模板。

同时 GrapesJS 官网上还给我们提供了3个不同场景的案例, 我们可以参考这些案例快速制作属于我们自己的web编辑器:

  • Webpage Builder
  • Newsletter Builder
  • Newsletter Builder with MJML

那么至于这些搭建框架的实现原理, 我之前的文章中也做了很多剖析和设计, 大家如果感兴趣可以参考研究一下, 接下来我们看看如何安装和使用它.

如何使用 GrapesJS 构建 web 编辑器

1. 安装

我们可以用 umd 的方式来导入:

  1. <link rel="stylesheet" href="//unpkg.com/grapesjs/dist/css/grapes.min.css"
  2. <script src="//unpkg.com/grapesjs"></script> 

也可以通过 npm 来安装:

  1. npm i grapesjs -S 

之后我们可以通过如下方式导入到项目:

  1. import 'grapesjs/dist/css/grapes.min.css'
  2. import grapesjs from 'grapesjs'

2. 第一个demo

在安装完之后, 我们先实现一个基本的页面编辑demo:

chrome-capture (1).gif

相关代码如下:

  1. <html> 
  2.   <head> 
  3.     <link rel="stylesheet" href="//unpkg.com/grapesjs/dist/css/grapes.min.css"
  4.     <script src="//unpkg.com/grapesjs"></script> 
  5.     <style> 
  6.         #gjs { 
  7.           border: 3px solid #444; 
  8.         } 
  9.         .gjs-cv-canvas { 
  10.           top: 0; 
  11.           width: 100%; 
  12.           height: 100%; 
  13.         } 
  14.     </style> 
  15.   </head> 
  16.   <body> 
  17.     <div id="gjs"
  18.       <h1>Hello World Component!</h1> 
  19.     </div> 
  20.     <script> 
  21.        const editor = grapesjs.init({ 
  22.           container: '#gjs'
  23.           // 我们也可以使用可选的: `components: '<h1>Hello World Component!</h1>'`, 
  24.           fromElement: true
  25.           // 编辑器尺寸 
  26.           height: '300px'
  27.           width: 'auto'
  28.           // 禁用存储管理, 下面的文章我会介绍 
  29.           storageManager: false
  30.           panels: { defaults: [] }, 
  31.          }); 
  32.     </script> 
  33.   </body> 
  34. </html> 

这样就实现了一个简单的编辑器, 是不是很简单呢? 我们接下来继续探索更强大的功能。

3. 添加和定义组件

我们都知道网页编辑器需要提供非常丰富的组件, 这样能帮助用户更轻松的搭建页面, 同样 grapesjs 支持添加各种自定义组件, 也内置了常用的基础组件, 我们来看一个 demo :

chrome-capture (2).gif

由以上 demo 我们可以看到添加了3个基本组件: 区块, 文本, 图片。基本实现代码如下:

  1. const editor = grapesjs.init({ 
  2.   // ...其他配置 
  3.   blockManager: { 
  4.     appendTo: '#blocks'
  5.     blocks: [ 
  6.       { 
  7.         id: 'section'
  8.         label: '<b>Section</b>',  
  9.         attributes: { class:'gjs-block-section' }, 
  10.         content: `<section
  11.           <h1>H5-Dooring</h1> 
  12.           <div>积木式搭建H5页面</div> 
  13.         </section>`, 
  14.       }, { 
  15.         id: 'text'
  16.         label: 'Text'
  17.         content: '<div data-gjs-type="text">My Baby</div>'
  18.       }, { 
  19.         id: 'image'
  20.         label: 'Image'
  21.         selecttrue
  22.         content: { type: 'image' }, 
  23.         activate: true
  24.       } 
  25.     ] 
  26.   }, 
  27. }); 

由代码我们可以发现我们只需要在 blockManager 的 blocks 里添加指定的组件即可。同时我们还可以动态的添加组件:

  1. editor.BlockManager.add('my-block-id', { 
  2.     // ...其他配置如label 
  3.     content: { 
  4.         tagName: 'div'
  5.         draggable: false
  6.         attributes: { 'some-attribute''some-value' }, 
  7.         components: [ 
  8.           { 
  9.             tagName: 'span'
  10.             content: '<b>DooringX</b>'
  11.           }, { 
  12.             tagName: 'div'
  13.             components: '<span>无限可能</span>'
  14.           } 
  15.         ] 
  16.       } 
  17. }) 

至于更详细的组件配置文档, 大家可以参考文档: grapesjs组件如何工作

image.png

4. 添加功能面板

仅仅实现组件添加还不够, 一个有尊严的编辑器还应该有各种功能按钮, 来实现不同用户的需求。

现在我们有了画布和自定义组件,让我们看看如何创建一个功能面板,里面有按钮(使用Panels API)。

chrome-capture (3).gif

我们可以看到顶部有3个功能按钮:

  • 是否显示组件边线
  • 显示源码
  • 显示json

首先我们需要定义用来展示功能面板的元素(样式可以自定义):

  1. <div class="panel__top"
  2.     <div class="panel__basic-actions"></div> 
  3. </div> 

其次我们来定义挂载功能面板:

  1. editor.Panels.addPanel({ 
  2.   id: 'panel-top'
  3.   el: '.panel__top'
  4. }); 
  5. editor.Panels.addPanel({ 
  6.   id: 'basic-actions'
  7.   el: '.panel__basic-actions'
  8.   buttons: [ 
  9.     { 
  10.       id: 'visibility'
  11.       active: true
  12.       className: 'btn-toggle-borders'
  13.       label: '<u>B</u>'
  14.       command: 'sw-visibility'
  15.     }, { 
  16.       id: 'export'
  17.       className: 'btn-open-export'
  18.       label: 'Exp'
  19.       command: 'export-template'
  20.       context: 'export-template',  
  21.     }, { 
  22.       id: 'show-json'
  23.       className: 'btn-show-json'
  24.       label: 'JSON'
  25.       context: 'show-json'
  26.       command(editor) { 
  27.         editor.Modal.setTitle('Components JSON'
  28.           .setContent(`<textarea style="width:100%; height: 250px;"
  29.             ${JSON.stringify(editor.getComponents())} 
  30.           </textarea>`) 
  31.           .open(); 
  32.       }, 
  33.     } 
  34.   ], 
  35. }); 

我们可以定义更多的功能, 大家可以参考文档来学习使用。

5. 添加图层管理面板

在处理 Web 元素时,我们可能会发现另一个常见的工具是图层管理器。它是树状结构的,使我们能够轻松地对页面元素进行管理。要启用它,我们只需指定要渲染它的位置:

  1. const editor = grapesjs.init({ 
  2.   // ... 
  3.   layerManager: { 
  4.     appendTo: '.layers-container' 
  5.   }, 
  6.   // 我们能定义一个默认的面板作为侧边图层管理器 
  7.   panels: { 
  8.     defaults: [{ 
  9.       id: 'layers'
  10.       el: '.panel__right'
  11.       // 定义面板能否拖拽 
  12.       resizable: { 
  13.         maxDim: 350, 
  14.         minDim: 200, 
  15.         tc: 0, 
  16.         cl: 1, // 左侧可拖拽 
  17.         cr: 0, 
  18.         bc: 0, 
  19.         keyWidth: 'flex-basis'
  20.       }, 
  21.     }] 
  22.   } 
  23. }); 

效果如下:

chrome-capture (4).gif

我们可以看到右侧的图层面板, 可以轻松管理我们页面上的元素。

6. 添加样式配置面板

样式面板也很简单, 我们先定义对应的容器:

  1. <div class="panel__right"
  2.     <div class="layers-container"></div> 
  3.     <div class="styles-container"></div> 
  4. </div> 

然后初始化对应的配置脚本:

  1. const editor = grapesjs.init({ 
  2.   // ... 
  3.   panels: { 
  4.     defaults: [ 
  5.       // ... 
  6.       { 
  7.         id: 'panel-switcher'
  8.         el: '.panel__switcher'
  9.         buttons: [{ 
  10.             id: 'show-layers'
  11.             active: true
  12.             label: 'Layers'
  13.             command: 'show-layers'
  14.             // Once activated disable the possibility to turn it off 
  15.             togglable: false
  16.           }, { 
  17.             id: 'show-style'
  18.             active: true
  19.             label: 'Styles'
  20.             command: 'show-styles'
  21.             togglable: false
  22.         }], 
  23.       } 
  24.     ] 
  25.   }, 
  26.   selectorManager: { 
  27.     appendTo: '.styles-container' 
  28.   }, 
  29.   styleManager: { 
  30.     appendTo: '.styles-container'
  31.     sectors: [{ 
  32.         name'Dimension'
  33.         openfalse
  34.         buildProps: ['width''min-height''padding'], 
  35.         properties: [ 
  36.           { 
  37.             type: 'integer'
  38.             name'The width'
  39.             property: 'width',  
  40.             units: ['px''%'],  
  41.             defaults: 'auto',  
  42.             min: 0,  
  43.           } 
  44.         ] 
  45.       },{ 
  46.         name'Extra'
  47.         openfalse
  48.         buildProps: ['background-color''box-shadow''custom-prop'], 
  49.         properties: [ 
  50.           { 
  51.             id: 'custom-prop'
  52.             name'Custom Label'
  53.             property: 'font-size'
  54.             type: 'select'
  55.             defaults: '32px'
  56.             options: [ 
  57.               { value: '12px'name'Tiny' }, 
  58.               { value: '18px'name'Medium' }, 
  59.               { value: '32px'name'Big' }, 
  60.             ], 
  61.          } 
  62.         ] 
  63.       }] 
  64.   }, 
  65. }); 
  66.  
  67. // 定义指令 
  68. editor.Commands.add('show-layers', { 
  69.   getRowEl(editor) { return editor.getContainer().closest('.editor-row'); }, 
  70.   getLayersEl(row) { return row.querySelector('.layers-container') }, 
  71.  
  72.   run(editor, sender) { 
  73.     const lmEl = this.getLayersEl(this.getRowEl(editor)); 
  74.     lmEl.style.display = ''
  75.   }, 
  76.   stop(editor, sender) { 
  77.     const lmEl = this.getLayersEl(this.getRowEl(editor)); 
  78.     lmEl.style.display = 'none'
  79.   }, 
  80. }); 
  81. editor.Commands.add('show-styles', { 
  82.   getRowEl(editor) { return editor.getContainer().closest('.editor-row'); }, 
  83.   getStyleEl(row) { return row.querySelector('.styles-container') }, 
  84.  
  85.   run(editor, sender) { 
  86.     const smEl = this.getStyleEl(this.getRowEl(editor)); 
  87.     smEl.style.display = ''
  88.   }, 
  89.   stop(editor, sender) { 
  90.     const smEl = this.getStyleEl(this.getRowEl(editor)); 
  91.     smEl.style.display = 'none'
  92.   }, 
  93. }); 

我们可以看看配置后的效果:

chrome-capture (5).gif

7. 更多用法演示

除了以上介绍的功能, 我们还能实现:

  • 定义响应模式(pc, 移动, ipad),
  • 设置存储和加载数据的模式
  • 自定义主题
  • 国际化 i18n 支持

这里就不一一介绍了, 我们直接看一下配置后的演示效果:

chrome-capture (6).gif

基于 GrapesJS 构建的开源网页编辑器 craft.js

那么 GrapesJS 还有很多有意思的功能我们可以挖掘, 接下来我和大家分享一款基于GrapesJS 二次封装的一个开源编辑器框架 craft.js。

chrome-capture (7).gif

我们可以使用它插件化的搭建我们自己的编辑器, 如下是一个应用在React中的例子:

  1. import {Editor, Frame, Canvas, Selector} from "@craftjs/core"
  2. // 定义本文组件 
  3. import {useNode} from "@craftjs/core"
  4.  
  5. const TextComponent = ({text}) => { 
  6.   const { connectors: {drag} } = useNode(); 
  7.  
  8.   return ( 
  9.     <div ref={drag}> 
  10.       <h2>{text}</h2> 
  11.     </div> 
  12.   ) 
  13.  
  14. // 初始化编辑器 
  15. const App = () => { 
  16.   return ( 
  17.     <div> 
  18.       <Editor> 
  19.         // 可编辑的区域 
  20.         <Frame resolver={TextComponent, Container}> 
  21.           <Canvas> 
  22.             <TextComponent text="趣谈前端 - 徐小夕" /> 
  23.           </Canvas> 
  24.         </Frame> 
  25.       </Editor> 
  26.     </div> 
  27.   ) 

更多可视化编辑器推荐

  • h5-Dooring | H5编辑器, 积木式搭建H5页面
  • v6.dooring | 可视化大屏搭建解决方案
  • craft | 基于React的拖拽页面生成器
  • dooringx-lib | 快速高效搭建可视化拖拽平台

最后

后期我会在数据可视化和工程化上输出更多实用的开源项目和框架,如果有其他问题或需求,可以和笔者交流学习。

本文转载自微信公众号「趣谈前端」,可以通过以下二维码关注。转载本文请联系趣谈前端公众号。

 

责任编辑:武晓燕 来源: 趣谈前端
相关推荐

2021-01-21 16:03:15

Java文本编辑器编程语言

2020-04-09 14:23:44

PythonMarkdown编辑器

2022-01-10 18:16:24

编辑器Typora Markdown

2022-04-15 09:59:08

Lexical开源Meta

2020-09-18 06:00:51

开源Markdown编辑器

2020-10-14 12:29:51

开源图表 开发

2011-10-31 10:17:05

插件

2019-06-10 11:06:04

JavaScript编辑器HTML5

2017-05-23 19:19:16

开源Markdown编辑器

2023-12-15 09:59:14

开源GIF编辑器图片格式

2020-08-22 07:46:58

Photoflare开源图像编辑器

2019-06-14 15:28:13

程序员文本编辑器

2019-06-18 09:40:57

Graviton开源代码编辑器

2022-03-20 18:12:03

Shotcut开源视频编辑器

2020-12-21 13:33:00

medit编辑器Linux

2024-04-03 08:22:54

代码编辑器组件

2024-02-21 16:40:06

Web代码编辑器开源

2020-03-25 14:16:58

文本编辑器语言开发

2011-01-10 16:17:49

2024-01-16 18:13:46

开源AudacityAI 工具
点赞
收藏

51CTO技术栈公众号