开源可视化页面框架GrapesJS开发教程(二) - 组件开发
本文是介绍可视化页面构建工具 GrapesJS开发教程系列篇之组件介绍,本系列主要是介绍GrapesJS以及与如何对接GrapesJS,如何与CMS整合等相关内容。
GrapesJS是一个可视化的、开源的网页构建工具,前几篇主要是对GrapesJS的基础介绍、代码结构、如何生成Twig模板等。本文重点是介绍Grapes的组件开、组件定义、组件具体代码案例等相关知识。

GrapesJS的组件基础概念
GrapesJS 的组件是指包含有关元素在画布中如何呈现(由 View 管理)以及其最终代码可能如何(由 Model 中的属性创建)的信息的对象,所有 Model 属性都会反映在 View 中。GrapesJS 支持添加各种自定义组件,也内置了常用的基础组件,例如区块、文本、图片等。
组件,在GrapesJS里面是一个重要的概念,是一等公民,我们看到的所见即所得就是对组件的拖拉拽以及属性配置操作,组件有一点需要特别注意一下,就是组件的性质。
如果我们构建的是HTML页面,那么组件就是HTML元素的拖拉拽。
如果我们是对邮件MJML的编辑,那么拖拽的就是MJML元素。
如果我们构建的是H5或者App,一个元素是一段JSON,那么拖拽的其实是JSON,而不是常见的HTML,这样可视化所见即所得相对要复杂很多。
GrapesJS的组件开发要点
GrapesJS 里开发组件,首先需要弄清楚两个核心概念:Component 和 Block。
Component 定义了一个组件的标签是什么,有什么属性、方法,在Canvas里如何展示,保存为HTML时又应该是什么结果。
Block 可以理解为是一个或多个 Component 组成的“代码片段”。
通常而言,用户在组件库里看到的东西就是Block,在用户将Block拖动到Canvas里之后,Grapes JS会经由解析器将它们转换成Component,这时候用户如果要编辑组件的样式、内容、属性等,就变成和Component交互了。
为了更好理解这两者之间的关系以及组件开发,我们来梳理一个典型的图片组件的开发流程。
1. 定义 Image Component
Component 分为Model和View,对于前端来说,这两个概念不陌生,一个定义了属性、方法和事件,一个定义了在canvas里展现的UI。具体代码可参考如下两个文件:
https://github.com/GrapesJS/grapesjs/blob/dev/src/dom_components/model/C... https://github.com/GrapesJS/grapesjs/blob/dev/src/dom_components/view/Co...
2. 注册 Image 到 DOM 组件
将 Image 注册到 DomComponent 里,此时GrapesJS已经可以识别image组件了,但是用户还无法在组件库找到并使用该组件。
{
id: 'image',
model: ComponentImage,
view: ComponentImageView,
}
3. 拖拽 Image 到可视区
通过 BlockManager 添加一个只包含Image的片段,这时候用户在组件库里可以看到一个新的组件Image,并且有个icon表示这是个图片组件。拖到这个Image到canvas里,可以看到生成了一张图片。
editor.BlockManager.add('image', {
...commonBlockProps,
activate: true,
label: 'Image',
media: `
`,
content: {
style: { color: 'black' },
type: 'image',
}
});
注意这里 content是block的内容,用了json的方式来构造内容,和virtul dom的概念十分接近。但block除了使用json格式以外,也支持直接用html的形式来构造内容,例如以下片段,就是包含了两张图片的block,比如下面的代码:
content: '<div><img src="https://placehold.it/400x400" /><img src="https://placehold.it/500x300" /></div>'
完整案例
我们找了一个计时器组件的完整代码,里面包含了每一个步骤的注释,通过整个代码示例,就可以完全理解GrapesJS组件开发的基本流程,具体参考如下:
// 定义component type
const timerModel = editor.DomComponents.addType('timer', {
model: {
defaults: {
// Default properties
tagName: 'div',
timer: 60, // seconds
script() {
// This script will be printed in the final HTML
const timerEl = this;
let timer = timerEl.getAttribute('data-timer');
const interval = setInterval(() => {
timerEl.innerHTML = timer;
timer--;
if (timer < 0) {
clearInterval(interval);
timerEl.innerHTML = 'Time is up!';
}
}, 1000);
},
// Show the timer value in the badge
badgeLabel() {
return this.getAttributes().timer;
},
},
},
});
// 给component type 定义 view
const timerView = editor.DomComponents.getType('default').view.extend({
events: {
// Listen to the click event and update the timer value
click: function () {
const model = this.model;
const timer = model.getAttributes().timer;
const newTimer = prompt('Enter the new timer value', timer);
if (newTimer) {
model.addAttributes({ timer: newTimer });
model.trigger('change:badgeLabel');
}
},
},
});
// 注册 component 和 view
editor.DomComponents.addType('timer', {
model: timerModel,
view: timerView,
});
// 注册 block
editor.BlockManager.add('timer', {
label: 'Timer',
content: { type: 'timer' },
});
创作不易,转载请注明出处!
Drupal与GrapesJS集成演示请点击这里>>
更多GrapesJS开发以及Drupal CMS相关内容,请参考我们其他相关文章,
3、开源CMS Drupal整合可视化构建工具GrapesJS(一)
4、开源可视化页面框架GrapesJS教程(二)- 组件开发
5、可视化页面框架GrapesJS开发教程(三)- 与Drupal CMS整合
6、开源可视化页面框架GrapesJS开发教程(四)- 创建 Block
QQ交谈客服1