這款國外開源框架, 讓你輕松構(gòu)建自己的頁面編輯器
按照我一向的寫作風(fēng)格,我會在下面列出文章的大綱,以便大家有選擇且高效率的閱讀和學(xué)習(xí):
- GrapesJS 框架基本介紹
- 如何使用 GrapesJS 構(gòu)建 web 編輯器
- 基于 GrapesJS 構(gòu)建的開源網(wǎng)頁編輯器 craft.js
- 更多可視化編輯器推薦
基本介紹
chrome-capture.gif
乍眼一看我們可能會認(rèn)為它只是一個頁面/HTML 編輯器,但它能做的不僅僅如此。GrapesJS 是一個多用途的 Web 頁面搭建框架,這意味著它允許我們輕松創(chuàng)建一個支持拖放的任何具有類似 HTML 結(jié)構(gòu)的構(gòu)建器。它所包含的內(nèi)容遠(yuǎn)不止網(wǎng)頁。我們使用類似 HTML 的結(jié)構(gòu)的場景有:
- 時事通訊(例如 MJML)
- 原生移動應(yīng)用程序(例如 React Native)
- 本機桌面應(yīng)用程序(例如 Vuido)
- PDF (例如 React PDF)
并且 GrapesJS 附帶的功能和工具使我們能夠制作易于使用的編輯器。這使用戶無需任何編碼知識即可創(chuàng)建復(fù)雜的類似 HTML 的模板。
同時 GrapesJS 官網(wǎng)上還給我們提供了3個不同場景的案例, 我們可以參考這些案例快速制作屬于我們自己的web編輯器:
- Webpage Builder
- Newsletter Builder
- Newsletter Builder with MJML
那么至于這些搭建框架的實現(xiàn)原理, 我之前的文章中也做了很多剖析和設(shè)計, 大家如果感興趣可以參考研究一下, 接下來我們看看如何安裝和使用它.
如何使用 GrapesJS 構(gòu)建 web 編輯器
1. 安裝
我們可以用 umd 的方式來導(dǎo)入:
- <link rel="stylesheet" href="//unpkg.com/grapesjs/dist/css/grapes.min.css">
- <script src="//unpkg.com/grapesjs"></script>
也可以通過 npm 來安裝:
- npm i grapesjs -S
之后我們可以通過如下方式導(dǎo)入到項目:
- import 'grapesjs/dist/css/grapes.min.css';
- import grapesjs from 'grapesjs';
2. 第一個demo
在安裝完之后, 我們先實現(xiàn)一個基本的頁面編輯demo:
chrome-capture (1).gif
相關(guān)代碼如下:
- <html>
- <head>
- <link rel="stylesheet" href="//unpkg.com/grapesjs/dist/css/grapes.min.css">
- <script src="//unpkg.com/grapesjs"></script>
- <style>
- #gjs {
- border: 3px solid #444;
- }
- .gjs-cv-canvas {
- top: 0;
- width: 100%;
- height: 100%;
- }
- </style>
- </head>
- <body>
- <div id="gjs">
- <h1>Hello World Component!</h1>
- </div>
- <script>
- const editor = grapesjs.init({
- container: '#gjs',
- // 我們也可以使用可選的: `components: '<h1>Hello World Component!</h1>'`,
- fromElement: true,
- // 編輯器尺寸
- height: '300px',
- width: 'auto',
- // 禁用存儲管理, 下面的文章我會介紹
- storageManager: false,
- panels: { defaults: [] },
- });
- </script>
- </body>
- </html>
這樣就實現(xiàn)了一個簡單的編輯器, 是不是很簡單呢? 我們接下來繼續(xù)探索更強大的功能。
3. 添加和定義組件
我們都知道網(wǎng)頁編輯器需要提供非常豐富的組件, 這樣能幫助用戶更輕松的搭建頁面, 同樣 grapesjs 支持添加各種自定義組件, 也內(nèi)置了常用的基礎(chǔ)組件, 我們來看一個 demo :
chrome-capture (2).gif
由以上 demo 我們可以看到添加了3個基本組件: 區(qū)塊, 文本, 圖片。基本實現(xiàn)代碼如下:
- const editor = grapesjs.init({
- // ...其他配置
- blockManager: {
- appendTo: '#blocks',
- blocks: [
- {
- id: 'section',
- label: '<b>Section</b>',
- attributes: { class:'gjs-block-section' },
- content: `<section>
- <h1>H5-Dooring</h1>
- <div>積木式搭建H5頁面</div>
- </section>`,
- }, {
- id: 'text',
- label: 'Text',
- content: '<div data-gjs-type="text">My Baby</div>',
- }, {
- id: 'image',
- label: 'Image',
- select: true,
- content: { type: 'image' },
- activate: true,
- }
- ]
- },
- });
由代碼我們可以發(fā)現(xiàn)我們只需要在 blockManager 的 blocks 里添加指定的組件即可。同時我們還可以動態(tài)的添加組件:
- editor.BlockManager.add('my-block-id', {
- // ...其他配置如label
- content: {
- tagName: 'div',
- draggable: false,
- attributes: { 'some-attribute': 'some-value' },
- components: [
- {
- tagName: 'span',
- content: '<b>DooringX</b>',
- }, {
- tagName: 'div',
- components: '<span>無限可能</span>',
- }
- ]
- }
- })
至于更詳細(xì)的組件配置文檔, 大家可以參考文檔: grapesjs組件如何工作
image.png
4. 添加功能面板
僅僅實現(xiàn)組件添加還不夠, 一個有尊嚴(yán)的編輯器還應(yīng)該有各種功能按鈕, 來實現(xiàn)不同用戶的需求。
現(xiàn)在我們有了畫布和自定義組件,讓我們看看如何創(chuàng)建一個功能面板,里面有按鈕(使用Panels API)。
chrome-capture (3).gif
我們可以看到頂部有3個功能按鈕:
- 是否顯示組件邊線
- 顯示源碼
- 顯示json
首先我們需要定義用來展示功能面板的元素(樣式可以自定義):
- <div class="panel__top">
- <div class="panel__basic-actions"></div>
- </div>
其次我們來定義掛載功能面板:
- editor.Panels.addPanel({
- id: 'panel-top',
- el: '.panel__top',
- });
- editor.Panels.addPanel({
- id: 'basic-actions',
- el: '.panel__basic-actions',
- buttons: [
- {
- id: 'visibility',
- active: true,
- className: 'btn-toggle-borders',
- label: '<u>B</u>',
- command: 'sw-visibility',
- }, {
- id: 'export',
- className: 'btn-open-export',
- label: 'Exp',
- command: 'export-template',
- context: 'export-template',
- }, {
- id: 'show-json',
- className: 'btn-show-json',
- label: 'JSON',
- context: 'show-json',
- command(editor) {
- editor.Modal.setTitle('Components JSON')
- .setContent(`<textarea style="width:100%; height: 250px;">
- ${JSON.stringify(editor.getComponents())}
- </textarea>`)
- .open();
- },
- }
- ],
- });
我們可以定義更多的功能, 大家可以參考文檔來學(xué)習(xí)使用。
5. 添加圖層管理面板
在處理 Web 元素時,我們可能會發(fā)現(xiàn)另一個常見的工具是圖層管理器。它是樹狀結(jié)構(gòu)的,使我們能夠輕松地對頁面元素進(jìn)行管理。要啟用它,我們只需指定要渲染它的位置:
- const editor = grapesjs.init({
- // ...
- layerManager: {
- appendTo: '.layers-container'
- },
- // 我們能定義一個默認(rèn)的面板作為側(cè)邊圖層管理器
- panels: {
- defaults: [{
- id: 'layers',
- el: '.panel__right',
- // 定義面板能否拖拽
- resizable: {
- maxDim: 350,
- minDim: 200,
- tc: 0,
- cl: 1, // 左側(cè)可拖拽
- cr: 0,
- bc: 0,
- keyWidth: 'flex-basis',
- },
- }]
- }
- });
效果如下:
chrome-capture (4).gif
我們可以看到右側(cè)的圖層面板, 可以輕松管理我們頁面上的元素。
6. 添加樣式配置面板
樣式面板也很簡單, 我們先定義對應(yīng)的容器:
- <div class="panel__right">
- <div class="layers-container"></div>
- <div class="styles-container"></div>
- </div>
然后初始化對應(yīng)的配置腳本:
- const editor = grapesjs.init({
- // ...
- panels: {
- defaults: [
- // ...
- {
- id: 'panel-switcher',
- el: '.panel__switcher',
- buttons: [{
- id: 'show-layers',
- active: true,
- label: 'Layers',
- command: 'show-layers',
- // Once activated disable the possibility to turn it off
- togglable: false,
- }, {
- id: 'show-style',
- active: true,
- label: 'Styles',
- command: 'show-styles',
- togglable: false,
- }],
- }
- ]
- },
- selectorManager: {
- appendTo: '.styles-container'
- },
- styleManager: {
- appendTo: '.styles-container',
- sectors: [{
- name: 'Dimension',
- open: false,
- buildProps: ['width', 'min-height', 'padding'],
- properties: [
- {
- type: 'integer',
- name: 'The width',
- property: 'width',
- units: ['px', '%'],
- defaults: 'auto',
- min: 0,
- }
- ]
- },{
- name: 'Extra',
- open: false,
- buildProps: ['background-color', 'box-shadow', 'custom-prop'],
- properties: [
- {
- id: 'custom-prop',
- name: 'Custom Label',
- property: 'font-size',
- type: 'select',
- defaults: '32px',
- options: [
- { value: '12px', name: 'Tiny' },
- { value: '18px', name: 'Medium' },
- { value: '32px', name: 'Big' },
- ],
- }
- ]
- }]
- },
- });
- // 定義指令
- editor.Commands.add('show-layers', {
- getRowEl(editor) { return editor.getContainer().closest('.editor-row'); },
- getLayersEl(row) { return row.querySelector('.layers-container') },
- run(editor, sender) {
- const lmEl = this.getLayersEl(this.getRowEl(editor));
- lmEl.style.display = '';
- },
- stop(editor, sender) {
- const lmEl = this.getLayersEl(this.getRowEl(editor));
- lmEl.style.display = 'none';
- },
- });
- editor.Commands.add('show-styles', {
- getRowEl(editor) { return editor.getContainer().closest('.editor-row'); },
- getStyleEl(row) { return row.querySelector('.styles-container') },
- run(editor, sender) {
- const smEl = this.getStyleEl(this.getRowEl(editor));
- smEl.style.display = '';
- },
- stop(editor, sender) {
- const smEl = this.getStyleEl(this.getRowEl(editor));
- smEl.style.display = 'none';
- },
- });
我們可以看看配置后的效果:
chrome-capture (5).gif
7. 更多用法演示
除了以上介紹的功能, 我們還能實現(xiàn):
- 定義響應(yīng)模式(pc, 移動, ipad),
- 設(shè)置存儲和加載數(shù)據(jù)的模式
- 自定義主題
- 國際化 i18n 支持
這里就不一一介紹了, 我們直接看一下配置后的演示效果:
chrome-capture (6).gif
基于 GrapesJS 構(gòu)建的開源網(wǎng)頁編輯器 craft.js
那么 GrapesJS 還有很多有意思的功能我們可以挖掘, 接下來我和大家分享一款基于GrapesJS 二次封裝的一個開源編輯器框架 craft.js。
chrome-capture (7).gif
我們可以使用它插件化的搭建我們自己的編輯器, 如下是一個應(yīng)用在React中的例子:
- import {Editor, Frame, Canvas, Selector} from "@craftjs/core";
- // 定義本文組件
- import {useNode} from "@craftjs/core";
- const TextComponent = ({text}) => {
- const { connectors: {drag} } = useNode();
- return (
- <div ref={drag}>
- <h2>{text}</h2>
- </div>
- )
- }
- // 初始化編輯器
- const App = () => {
- return (
- <div>
- <Editor>
- // 可編輯的區(qū)域
- <Frame resolver={TextComponent, Container}>
- <Canvas>
- <TextComponent text="趣談前端 - 徐小夕" />
- </Canvas>
- </Frame>
- </Editor>
- </div>
- )
- }
更多可視化編輯器推薦
- h5-Dooring | H5編輯器, 積木式搭建H5頁面
- v6.dooring | 可視化大屏搭建解決方案
- craft | 基于React的拖拽頁面生成器
- dooringx-lib | 快速高效搭建可視化拖拽平臺
最后
后期我會在數(shù)據(jù)可視化和工程化上輸出更多實用的開源項目和框架,如果有其他問題或需求,可以和筆者交流學(xué)習(xí)。
本文轉(zhuǎn)載自微信公眾號「趣談前端」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系趣談前端公眾號。