У меня есть теневое dom, которое содержит корневой элемент и компонент vue.
<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>
Внутри vue-component.js
выглядит примерно так:
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'
// })
Все работает отлично, если я использую этот материал вне теневого домика (как обычные люди). Однако, похоже, что Vue не может обрабатывать теневое хранилище. Я считаю, что он не должен вызывать document.querySelector
если он находится внутри тени. Вместо этого должен быть запущен shadowRoot.querySelector
.
Пожалуйста, дайте мне знать, если это сбивает с толку, я в необычном сценарии использования, поэтому немного сложно объяснить.
---Обновить---
Если вы передадите ссылку на элемент вместо селектора, Vue будет использовать этот элемент.
let element = document.querySelector('#host-element').shadowRoot.querySelector('#your-future-vue-component');
new Vue({
el: element,
...
})
---Old Stuff---
У меня есть половина решения для вас, используя vue-custom-element. Я говорю наполовину, потому что он добавляет ваш компонент vue в веб-компонент и дает вам возможность использовать теневую DOM. Это означает, что элемент Vue Custom также должен быть вашим shadowRoot. Надеюсь, это соответствует вашим потребностям.
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);
Единственный другой вариант, который, как мне кажется, - изменить код Vue. Вы можете сделать это и создать запрос на растяжение, или просто взломать его для себя.
const shadowRoot = this.attachShadow({ mode: "closed" })
, затем передайте shadowRoot в el
в компоненте vue.