开源可视化页面框架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