1
votes

I’m integrating Vue with a CMS called AEM thats works basically as component base system like Vue works too. But instead of having a webpack and imports of .vue files, every component on this CMS is a new Vue instance (new Vue({…})). So on my page I have a lot of Veu instances that communicate with each other using the same store (vuex).

This is actually working fine, but I have a scenario when I need a CMS component inside another. Since both this components are a unique vue instance and the “el” property from the parent includes the “el” from the child, the child component doesn’t work.

I know that this is not the expected use of this lib, but is there any way that I can tell or share the same “context” on both vue instances or even another approach for this scenario.

Thx, Alexandre.

3
I know this is quite old, but there are currently two viable approaches to building AEM components with Vue, as suggested in helpx.adobe.com/experience-manager/kt/eseminars/ask-the-expert/… We also developed more advanced strategies to enhance using the "siloed" pattern. If needed, I can provide more info.ibanjo

3 Answers

1
votes

There should be only one instance of Vue.

  • I suggest you to create single empty Vue instance inside the body tag
  • All your existent Vue instances transform into components
  • Register all components in the root Vue instance

With this approach it will be fine to nest one component into another

1
votes

You should use only one Vue instance as @shrpne mentioned.

If you keep instantiating Vue instances for every component, you'll run into issues while debugging or with component communication and overall this becomes very missy and you miss out on parent-child communication and inheritance provided by Vue.

I don't know about your Vue architecture, but I am currently working on a manual for working with Vue in AEM.

The basic premise is to use Vue's inline-template and vanilla-js, No typescript, nodeJS build, jsx or anything else at build time, just vanilla-js so that when your page is loaded and even before your js bundle is present, the DOM is already there, you just need to mount components by instantiating one Vue instance that will mount all components. This is also great for SEO (unless you plan to server-side render Vue components in java... which is possible theoretically, but good luck!)

Here is a sample AEM/Vue component:

  <simple-counter inline-template>
    <button v-bind:style="style" v-on:click="add">${properties.clicksText || 'clicks: '} {{ counter }}</button>
  </simple-counter>

the JS:

notice how it does not have a template in the JS, because it's inlined above

Vue.component('simple-counter', {
  data: function() {
    return {
      counter: 0,
      style: {
        color: 'red',
        width: '200px'
      }
    }
  },
  methods: {
    add: function() {
      this.counter = this.counter + 1;
      this.style.color = this.style.color == 'red' ? 'green' : 'red';
    }
  }
})

You can build more AEM components in this fashion, then at the end of your clientlib when all your Vue components have been registered, you can run:

new Vue({ el: '#app'})

This, off course, assumes that your page body or some other parent element has the id: app.

The second part of this, how do you enable re-mount of components after authoring dialog is submitted, you could just refresh the page.

I have a question about how we can re-mount components without refreshing the page here The basic idea is to add an afteredit event to the component and run a new Vue instance only on the newly mutated component... still working on that

1
votes

Solution:

  1. Replace all new Vue(...) stuff into Vue.component(...) Vue.extend(...) etc for better interface management.

  2. Only use ONE Vue instance witch is new Vue({...options})

  3. Slice your vuex store into modules.
  4. Google teacher knows everything.