前段時間我一直在設計和研究低代碼搭建平臺,也開源了幾款可視化編輯器框架,最近在 github 上發現了一款很是強大的基於天然流佈局的頁面搭建框架 GrapesJS,接下來我就帶你們摸索一下這款框架。javascript
按照我一貫的寫做風格,我會在下面列出文章的大綱,以便你們有選擇且高效率的閱讀和學習:css
GrapesJS 框架基本介紹html
如何使用 GrapesJS 構建 web 編輯器前端
基於 GrapesJS 構建的開源網頁編輯器 craft.jsjava
更多可視化編輯器推薦react
乍眼一看咱們可能會認爲它只是一個頁面/HTML 編輯器,但它能作的不只僅如此。GrapesJS 是一個多用途的 Web 頁面搭建框架,這意味着它容許咱們輕鬆建立一個支持拖放的任何具備相似 HTML 結構的構建器。它所包含的內容遠不止網頁。咱們使用相似 HTML 的結構的場景有:git
而且 GrapesJS 附帶的功能和工具使咱們可以製做易於使用的編輯器。這使用戶無需任何編碼知識便可建立複雜的相似 HTML 的模板。github
同時 GrapesJS 官網上還給咱們提供了3個不一樣場景的案例, 咱們能夠參考這些案例快速製做屬於咱們本身的web編輯器:web
那麼至於這些搭建框架的實現原理, 我以前的文章中也作了不少剖析和設計, 你們若是感興趣能夠參考研究一下, 接下來咱們看看如何安裝和使用它.chrome
咱們能夠用 umd
的方式來導入:
<link rel="stylesheet" href="//unpkg.com/grapesjs/dist/css/grapes.min.css">
<script src="//unpkg.com/grapesjs"></script>
複製代碼
也能夠經過 npm
來安裝:
npm i grapesjs -S
複製代碼
以後咱們能夠經過以下方式導入到項目:
import 'grapesjs/dist/css/grapes.min.css';
import grapesjs from 'grapesjs';
複製代碼
在安裝完以後, 咱們先實現一個基本的頁面編輯demo:
相關代碼以下:
<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>
複製代碼
這樣就實現了一個簡單的編輯器, 是否是很簡單呢? 咱們接下來繼續探索更強大的功能。
咱們都知道網頁編輯器須要提供很是豐富的組件, 這樣能幫助用戶更輕鬆的搭建頁面, 一樣 grapesjs 支持添加各類自定義組件, 也內置了經常使用的基礎組件, 咱們來看一個 demo :
由以上 demo
咱們能夠看到添加了3個基本組件: 區塊, 文本, 圖片。基本實現代碼以下:
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,
}
]
},
});
複製代碼
由代碼咱們能夠發現咱們只須要在 blockManager
的 blocks
裏添加指定的組件便可。同時咱們還能夠動態的添加組件:
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>',
}
]
}
})
複製代碼
至於更詳細的組件配置文檔, 你們能夠參考文檔: grapesjs組件如何工做
僅僅實現組件添加還不夠, 一個有尊嚴的編輯器還應該有各類功能按鈕, 來實現不一樣用戶的需求。
如今咱們有了畫布和自定義組件,讓咱們看看如何建立一個功能面板,裏面有按鈕(使用Panels API)。
咱們能夠看到頂部有3個功能按鈕:
首先咱們須要定義用來展現功能面板的元素(樣式能夠自定義):
<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();
},
}
],
});
複製代碼
咱們能夠定義更多的功能, 你們能夠參考文檔來學習使用。
在處理 Web
元素時,咱們可能會發現另外一個常見的工具是圖層管理器。它是樹狀結構的,使咱們可以輕鬆地對頁面元素進行管理。要啓用它,咱們只需指定要渲染它的位置:
const editor = grapesjs.init({
// ...
layerManager: {
appendTo: '.layers-container'
},
// 咱們能定義一個默認的面板做爲側邊圖層管理器
panels: {
defaults: [{
id: 'layers',
el: '.panel__right',
// 定義面板可否拖拽
resizable: {
maxDim: 350,
minDim: 200,
tc: 0,
cl: 1, // 左側可拖拽
cr: 0,
bc: 0,
keyWidth: 'flex-basis',
},
}]
}
});
複製代碼
效果以下:
咱們能夠看到右側的圖層面板, 能夠輕鬆管理咱們頁面上的元素。
樣式面板也很簡單, 咱們先定義對應的容器:
<div class="panel__right">
<div class="layers-container"></div>
<div class="styles-container"></div>
</div>
複製代碼
而後初始化對應的配置腳本:
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';
},
});
複製代碼
咱們能夠看看配置後的效果:
除了以上介紹的功能, 咱們還能實現:
這裏就不一一介紹了, 咱們直接看一下配置後的演示效果:
那麼 GrapesJS 還有不少有意思的功能咱們能夠挖掘, 接下來我和你們分享一款基於GrapesJS 二次封裝的一個開源編輯器框架 craft.js。
咱們可使用它插件化的搭建咱們本身的編輯器, 以下是一個應用在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> // 可編輯的區域 <Frame resolver={TextComponent, Container}> <Canvas> <TextComponent text="趣談前端 - 徐小夕" /> </Canvas> </Frame> </Editor> </div>
)
}
複製代碼
後期我會在數據可視化和工程化上輸出更多實用的開源項目和框架,若是有其餘問題或需求,能夠和筆者交流學習。若是這篇文章對你有幫助,但願能給筆者 點贊+收藏 以此鼓勵做者繼續創做前端硬核文章。也能夠關注做者公衆號 趣談前端 第一時間推送前端好文。