Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Vue to work in shadow dom

I have a shadow dom which contains the root element and a vue component.

<template>
    <div class="container">
        <div id="app"></div>
    </div>
    <script src="http://my-site.com/app/js/vue-component.js"></script>
</template>

<div id="hostElement"></div>
<script>
// create shadow DOM on the <p> element above
const shadow = document.querySelector('#hostElement').attachShadow({mode: 'open'});
const template = document.querySelector('template');
shadow.appendChild(document.importNode(template.content, true));
</script>

Inside the vue-component.js looks something like this:

import Vue from 'vue';

const shadow = document.querySelector('#hostElement').shadowRoot;

new Vue({
    el: shadow.querySelector('#app'),
    // ...
})

// this doesn't work because I think Vue is using document.querySelector('#app')
// instead of the required document.querySelector('#hostElement').shadowRoot.querySelector('#app')
// new Vue ({
//     el: '#app'
// })

Everything works fine if I use this stuff outside the shadow dom (like regular people do). However, it seems like Vue isn't able to handle shadow dom stuff. I believe it shouldn't be calling document.querySelector if it's inside the shadow dom. Instead, it should be running shadowRoot.querySelector.

Please let me know if this is confusing at all, I'm in a uncommon use case scenario so it is a little hard to explain.

like image 790
Jeff Avatar asked Oct 22 '17 22:10

Jeff


People also ask

Does Vue use Shadow DOM?

Vue. js and React both use Virtual DOM so it is a known concept by many but often it is confused with Shadow Dom. For this reason, an article about which problem Shadow DOM tries to solve and how it differs from Virtual DOM was created by @develoger, made available here.

How do I enable Shadow DOM?

Click on 3 vertical dots on the top right corner of dev tools before close button. Now click on settings there you will find “Show user agent shadow DOM” checkbox under the Elements section in General Tab. By checking that button it will enable shadow dom on one's browser.

Can I use DOM in Vue?

If a ref attribute is added to an HTML element in your Vue template, you'll then be able to reference that element or even a child element in your Vue instance. You can also access the DOM element directly, too; it is a read-only attribute and returns an object.

How do you handle Shadow DOM elements?

Work with Shadow DOM elements using RemoteWebDriver To access these Shadow DOM elements, we need to use the JavascriptExecutor executeScript() function. If you look at the DOM structure, every element that includes Shadow DOM also has a shadowRoot property that describes the underlying elements.


1 Answers

---Update---

If you pass a reference to an element instead of a selector, Vue will use the element.

let element = document.querySelector('#host-element').shadowRoot.querySelector('#your-future-vue-component');
new Vue({
  el: element,
  ...
})

---Old Stuff---

I have half a solution for you using vue-custom-element. I say half, because it puts your vue component into a webcomponent and gives you the option to have it use the shadow DOM. This means that the Vue Custom element will also have to be your shadowRoot. Hopefully this suits your needs.

https://github.com/karol-f/vue-custom-element

import Vue from 'vue';
import vueCustomElement from 'vue-custom-element';
import app from './app.vue';

Vue.use(vueCustomElement);
Vue.customElement("my-element", app, {shadow: true});
myShadowElement = document.createElement('my-element');
document.body.appendChild(myShadowElement);

The only other option I think you have is to go modify Vue's code. You could do so and create a pull request, or just hack it for yourself.

like image 177
SethWhite Avatar answered Oct 25 '22 22:10

SethWhite