Search code examples
javascriptreactjsgrapesjs

Difference between script filed and life cycle methods in Grapesjs?


I am new to Grapesjs, and i find the intro in Grapesjs doc website:

so if we have code like this:

editor.BlockManager.add('test-block', {
  label: 'Test block',
  attributes: {class: 'fa fa-text'},
  content: {
    script: "alert('Hi'); console.log('the element', this)",
    // Add some style just to make the component visible
    style: {
      width: '100px',
      height: '100px',
      'background-color': 'red',
    }
  }
});

On the doc website it says:

If you check now the generated HTML coded by the editor (via Export button or editor.getHtml()), you might see something like this:

<div id="c764"></div>
<script>
  var items = document.querySelectorAll('#c764');
  for (var i = 0, len = items.length; i < len; i++) {
    (function(){
      // START component code
      alert('Hi');
      console.log('the element', this)
      // END component code
    }.bind(items[i]))();
  }
</script>

It looks like all the stuff defined in script tag will be executed after the component mount, on the other way, considering Grapesjs provide view.init() and view.onRender() such life cycle methods, I was thinking we can probably achieve exactly the same effect using such life cycle methods.

So my question would be: what's difference between the script and component own life cycle methods?

BTW, I use React before, and i did most state initialization and data fetching in componentDidMount() such life cycle, so i personally could not get what could be the scenario for script in Grapesjs(Especially when i comparing those two libs.)?


Solution

  • As you should know Grapes uses backbone.js, which is pretty different to react.

    Now, talking about how it works for grapesjs.

    • Lifecycle hooks will allow you to interact with model and editor instance during website building process.

    • Script will contain javascript your component needs to be useful in and outside the editor (Obviously, having limited (read-only) access to model properties).

    Here you can see a very basic, and probably dummy example of both cases.

    1. Setting listener on init: You'll probably won't need to alert changes in component attributes in resulting page...
    2. Add animation class: script will run when render in editor, but also will run at published page, so you can see the animation out of grapes' editor.
        const editor = grapesjs.init({
          height: "100%",
          container: "#gjs",
          showOffsets: true,
          fromElement: true,
          noticeOnUnload: false,
          storageManager: false,
          canvas: {
            styles: [
              "https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.0.0/animate.min.css"
            ]
          }
        });
        editor.DomComponents.addType("MagicBox", {
          model: {
            defaults: {
              tagName: "div",
              attributes: {
                alert: ""
              },
              traits: ["alert"]
            },
            init() {
              this.listenTo(this, "change:attributes:alert", this.handleChange);
            },
            handleChange(a) {
              alert(this.get("attributes").alert);
            }
          }
        });
    
        const blockManager = editor.BlockManager;
        blockManager.add("magic-box", {
          label: "MagicBox",
          content: {
            type: "MagicBox",
            tagName: "div",
            style: {
              width: "100px",
              height: "100px",
              background: "blue"
            },
            script: 'this.className+="animate__animated animate__bounce"'
          },
          category: "Basic",
          attributes: {
            title: "Magic Box"
          }
        });