It can certainly be done, but I don’t know if someone has done it before like what’s been done with the React4XP library and starter, or if you need to implement this yourself.
You mention that Vue makes it difficult to use the
data-portal-component attribute because of “how Vue injects content into the body”. To that I will add that it’s not so much how Vue injects content, but rather when Vue injects content.
Image shamelessly copied from the Enonic XP site engine documentation:
The data-portal-component is the link between the “Page renderer” bubble and the “Component Renderer” bubble. But all this is happening server-side before the HTML document is delivered to the browser, while Vue.js is running client-side, i.e. after the Common pipeline in the end of the diagram above. So you have three options:
- Skip the whole Component Renderer step, and instead just have a simple Page Renderer and then write your own component renderer from scratch that extracts data from Enonic XP and will do the rest of the rendering client-side. I foresee relatively quick results if you go this route, but also lots of things that will no longer work, such as all the portal URL’s, macros, and not to forget the live edit mode inside Content Studio where you can drag and edit layouts, parts, and other components onto a page. All of that will no longer work. Therefore, I really don’t recommend this at all!
- Dual and redundant logic, both server-side and client-side. The server-side logic would render your pages and components using regular Enonic XP methodology, but only as a static markup that looks just like your Vue app when the page is loaded in the browser. The client-side logic would then replace this initial static placeholder markup with the actual Vue application, similar to how the Vue app typically replaces everything inside the
<div id="app"></div> container. This should not be that difficult for you to implement quickly, but is harder to maintain because it’s very specific to your app and you need to do a lot of the same things twice because server-side and client-side JS can’t access the same data model.
So if nobody else in this forum has any experience with integrating Vue with enonic that they can share here, I would recommend first trying a simple hard-coded proof of concept of option #3, and then either continue along that route or if you feel inspired: go for the more elegant option #2 similar to what has been done with React4XP.
I hope these answers have been useful, even though I don’t have experience with Vue myself.