react-grapesjs——开源代码学习与修改(初出茅庐)

文章目录

    • ⭐前言
    • ⭐grapesjs初始化过程
      • [💖 渲染大体流程](#💖 渲染大体流程 "#x1F496__16")
        • [💖 Editor对象 创建](#💖 Editor对象 创建 "#x1F496__Editor__17")
        • [💖 EditorModel 对象创建](#💖 EditorModel 对象创建 "#x1F496__EditorModel__34")
        • [💖 load modules 加载定义的目录模块Module](#💖 load modules 加载定义的目录模块Module "#x1F496_load_modules_Module_87")
        • [💖 StyleManager渲染过程](#💖 StyleManager渲染过程 "#x1F496_StyleManager_120")
    • ⭐修改grapesjs配置项
    • ⭐总结
    • ⭐结束

⭐前言

大家好,我是yma16,本文分享关于react-grapesjs------源码学习。

该系列往期文章:
react搭建在线编辑html的站点------引入grapes实现在线拖拉拽编辑html

结果演示:
yongma16.xyz/react-mjml/

⭐grapesjs初始化过程

源码:github.com/GrapesJS/gr...

目录结构

运行源码

💖 渲染大体流程

💖 Editor对象 创建
  1. new Editor进入 Editor对象
  2. class Editor implements IBaseModule<EditorConfig> 执行构造函数 constructor
javascript 复制代码
  constructor(config: EditorConfig = {}, opts: any = {}) {
    this.config = {
      ...defaults,
      ...config,
      pStylePrefix: config.stylePrefix ?? defaults.stylePrefix,
    };
    this.em = new EditorModel(this.config);
    this.$ = opts.$;
    this.em.init(this);
    this.editor = this.em;
  }
💖 EditorModel 对象创建
  1. class EditorModel extends Model 执行构造函数
javascript 复制代码
  constructor(conf: EditorConfig = {}) {
   super();
   this._config = conf;
   const { config } = this;
   this.set('Config', conf);
   this.set('modules', []);
   this.set('toLoad', []);
   this.set('storables', []);
   this.set('selected', new Selected());
   this.set('dmode', config.dragMode);
   const { el, log } = config;
   const toLog = log === true ? keys(logs) : isArray(log) ? log : [];
   bindAll(this, 'initBaseColorPicker');

   if (el && config.fromElement) {
     config.components = el.innerHTML;
   }

   this.attrsOrig = el
     ? toArray(el.attributes).reduce((res, next) => {
         res[next.nodeName] = next.nodeValue;
         return res;
       }, {} as Record<string, any>)
     : '';

   // Move components to pages
   if (config.components && !config.pageManager) {
     config.pageManager = { pages: [{ component: config.components }] };
   }

   // Load modules
   deps.forEach(constr => this.loadModule(constr));
   storableDeps.forEach(constr => this.loadStorableModule(constr));
   this.on('change:componentHovered', this.componentHovered, this);
   this.on('change:changesCount', this.updateChanges, this);
   this.on('change:readyLoad change:readyCanvas', this._checkReady, this);
   toLog.forEach(e => this.listenLog(e));

   // Deprecations
   [{ from: 'change:selectedComponent', to: 'component:toggled' }].forEach(event => {
     const eventFrom = event.from;
     const eventTo = event.to;
     this.listenTo(this, eventFrom, (...args) => {
       this.trigger(eventTo, ...args);
       this.logWarning(`The event '${eventFrom}' is deprecated, replace it with '${eventTo}'`);
     });
   });
 }
💖 load modules 加载定义的目录模块Module

deps的类型

javascript 复制代码
const deps: (new (em: EditorModel) => IModule)[] = [
  UtilsModule,
  I18nModule,
  KeymapsModule,
  UndoManagerModule,
  StorageManager,
  DeviceManager,
  ParserModule,
  StyleManager,
  SelectorManager,
  ModalModule,
  CodeManagerModule,
  PanelManager,
  RichTextEditorModule,
  TraitManager,
  LayerManager,
  CanvasModule,
  CommandsModule,
  BlockManager,
];
javascript 复制代码
    // Load modules
    deps.forEach(constr => this.loadModule(constr));
💖 StyleManager渲染过程

路径 src/style_manager

构造函数

javascript 复制代码
constructor(em: EditorModel) {
    super(em, 'StyleManager', new Sectors([], { em }), stylesEvents, defaults);
    bindAll(this, '__clearStateTarget');
    const c = this.config;
    const ppfx = c.pStylePrefix;
    if (ppfx) c.stylePrefix = ppfx + c.stylePrefix;
    this.builtIn = new PropertyFactory();
    this.properties = new Properties([], { em, module: this });
    this.sectors = this.all; // TODO check if (module: this) is required
    const model = new Model({ targets: [] });
    this.model = model;

    // Triggers for the selection refresh and properties
    const ev = 'component:toggled component:update:classes change:state change:device frame:resized selector:type';
    this.upAll = debounce(() => this.__upSel(), 0);
    model.listenTo(em, ev, this.upAll as any);
    // Clear state target on any component selection change, without debounce (#4208)
    model.listenTo(em, 'component:toggled', this.__clearStateTarget);

    // Triggers only for properties (avoid selection refresh)
    const upProps = debounce(() => {
      this.__upProps();
      this.__trgCustom();
    }, 0);
    model.listenTo(em, 'styleable:change undo redo', upProps);

    // Triggers only custom event
    const trgCustom = debounce(() => this.__trgCustom(), 0);
    model.listenTo(em, `${evLayerSelect} ${evTarget}`, trgCustom);

    // Other listeners
    model.on('change:lastTarget', () => em.trigger(evTarget, this.getSelected()));
  }

⭐修改grapesjs配置项

屏蔽 views的两个按钮

原来的样式

panels/config配置

更改配置项 注释不需要的配置

javascript 复制代码
import { PanelProperties } from '../model/Panel';

const swv = 'sw-visibility';
const expt = 'export-template';
const osm = 'open-sm';
const otm = 'open-tm';
const ola = 'open-layers';
const obl = 'open-blocks';
const ful = 'fullscreen';
const prv = 'preview';

interface ButtonProps {
  id?: string;
  active?: boolean;
  togglable?: boolean;
  className?: string;
  command?: string | (() => any);
  context?: string;
  attributes?: Record<string, any>;
}

interface PanelProps extends Omit<PanelProperties, 'id' | 'buttons'> {
  id?: string;
  buttons?: ButtonProps[];
}

export interface PanelsConfig {
  stylePrefix?: string;

  /**
   * Default panels.
   */
  defaults?: PanelProps[];
}

const config: PanelsConfig = {
  stylePrefix: 'pn-',
  defaults: [
    {
      id: 'commands',
      buttons: [{}],
    },
    {
      id: 'options',
      buttons: [
        {
          active: true,
          id: swv,
          className: 'fa fa-square-o',
          command: 'core:component-outline',
          context: swv,
          attributes: { title: 'View components' },
        },
        {
          id: prv,
          className: 'fa fa-eye',
          command: prv,
          context: prv,
          attributes: { title: 'Preview' },
        },
        {
          id: ful,
          className: 'fa fa-arrows-alt',
          command: ful,
          context: ful,
          attributes: { title: 'Fullscreen' },
        },
        {
          id: expt,
          className: 'fa fa-code',
          command: expt,
          attributes: { title: 'View code' },
        },
      ],
    },
    {
      id: 'views',
      buttons: [
        {
          id: osm,
          className: 'fa fa-paint-brush',
          command: osm,
          active: true,
          togglable: false,
          attributes: { title: 'Open Style Manager' },
        },
        // {
        //   id: otm,
        //   className: 'fa fa-cog',
        //   command: otm,
        //   togglable: false,
        //   attributes: { title: 'Settings' },
        // },
        // {
        //   id: ola,
        //   className: 'fa fa-bars',
        //   command: ola,
        //   togglable: false,
        //   attributes: { title: 'Open Layer Manager' },
        // },
        {
          id: obl,
          className: 'fa fa-th-large',
          command: obl,
          togglable: false,
          attributes: { title: 'Open Blocks' },
        },
      ],
    },
  ],
};

export default config;

修改成功!

同理合并配置项也是合并配置module的代码可以实现

⭐总结

⭐ 如何修改开源代码

修改开源代码的步骤如下:

  1. 首先要获取并安装开发环境。这包括编译器、文本编辑器和版本控制软件等。
  2. Fork开源项目,即在GitHub或其他代码托管平台上复制一份项目,这样你就有了自己的独立分支。
  3. 在你的本地机器上克隆你所Fork的项目。通过clone命令将整个项目下载到你的本地机器上。
  4. 创建新的分支。你需要创建一个新的分支,以便你可以在不影响其他贡献者的情况下进行更改。
  5. 对代码进行修改。使用你的文本编辑器打开项目文件并进行所需的更改,完成后保存文件。
  6. 运行测试。运行项目的测试套件,确保你的修改没有破坏现有代码的功能。
  7. 提交修改。使用git提交修改到你的本地分支并将这些更改推送到你的Fork仓库。
  8. 发送一个合并请求。你可以向原始项目的所有者发送一个请求,请求将你的分支合并到他们的主分支上。

以上是修改开源代码的基本步骤,需要结合实际情况进行具体操作。在修改开源代码时,不仅要尊重原作者的版权,还要了解开源授权协议及相应的规定。

⭐如何高效阅读开源代码

阅读开源代码可以帮助你学习其他程序员的技术,尤其是在你遇到类似的问题时,可以参考开源代码中的解决方案。以下是一些高效阅读开源代码的技巧:

  1. 了解项目结构:先了解项目的目录结构和代码风格,可以帮助你更快地定位代码位置和理解代码。
  2. 建立索引:可以使用工具或者手动建立索引,以便于更快地查找关键代码和内容。
  3. 浅阅读:先快速浏览代码,了解项目的整体结构和大致流程。
  4. 深度阅读:对于关键的代码部分,进行深度阅读,仔细理解其实现和作用。
  5. 调试代码:在自己的环境中运行代码,通过调试来理解代码的执行过程和实际效果。
  6. 参考文档:阅读开源项目的文档和介绍,可以更好地理解代码和项目。
  7. 学习工具:学习使用开源代码的工具,如IDE、版本控制软件等,可以更好地理解和使用开源代码。

最重要的是,在阅读开源代码时,要注重理解代码的思路和设计方式,而不是仅仅复制代码。

⭐结束

本文分享到这结束,如有错误或者不足之处欢迎指出!

👍 点赞,是我创作的动力!

⭐️ 收藏,是我努力的方向!

✏️ 评论,是我进步的财富!

💖 最后,感谢你的阅读!

相关推荐
余道各努力,千里自同风2 分钟前
前端 vue 如何区分开发环境
前端·javascript·vue.js
PandaCave9 分钟前
vue工程运行、构建、引用环境参数学习记录
javascript·vue.js·学习
软件小伟11 分钟前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾33 分钟前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧41 分钟前
TypeScript 的发展与基本语法
前端·javascript·typescript
疯狂的沙粒2 小时前
对 TypeScript 中高级类型的理解?应该在哪些方面可以更好的使用!
前端·javascript·typescript
旭日猎鹰2 小时前
Flutter踩坑记录(二)-- GestureDetector+Expanded点击无效果
前端·javascript·flutter
一条晒干的咸魚3 小时前
【Web前端】创建我的第一个 Web 表单
服务器·前端·javascript·json·对象·表单
花海少爷3 小时前
第十章 JavaScript的应用课后习题
开发语言·javascript·ecmascript
sinat_384241094 小时前
在有网络连接的机器上打包 electron 及其依赖项,在没有网络连接的机器上安装这些离线包
javascript·arcgis·electron