離れたコンポーネントにDOMをレンダリングできるライブラリ「PortalVue」
by kabanoki
HTML
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/portal-vue.umd.min.js"></script>
<div id="app">
<div class="container">
<card class="item left">
<portal-target name="head"></portal-target>
</card>
<card class="item right">
<span><a href="#" @click.preven="show = 'A'">コンポーネントAを表示</a></span> |
<span><a href="#" @click.preven="show = 'B'">コンポーネントBを表示</a></span> |
<span><a href="#" @click.preven="show = 'C'">コンポーネントCを表示</a></span>
<component-a v-if="show === 'A'"></component-a>
<component-b v-if="show === 'B'"></component-b>
<component-c v-if="show === 'C'"></component-c>
</card>
<card class="item left">
<portal-target name="footer"></portal-target>
</card>
</div>
</div>
<template id="A">
<div>
<p>
コンポーネントA のサイドバーパーツ
</p>
<portal to="head">
<h2>コンポーネントA</h2>
</portal>
<portal to="footer">
<h2>コンポーネントAのフッター</h2>
</portal>
</div>
</template>
<template id ="B">
<div>
<p>
コンポーネントB のサイドバーパーツ
</p>
<portal to="head">
<h2>コンポーネントB</h2>
</portal>
<portal to="footer">
<h2>コンポーネントBのフッター</h2>
</portal>
</div>
</template>
<template id ="C">
<div>
<p>
コンポーネントC のサイドバーパーツ
</p>
<portal to="head">
<h2>コンポーネントC</h2>
</portal>
<portal to="footer">
<h2>コンポーネントCのフッター</h2>
</portal>
</div>
</template>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/portal-vue.umd.min.js"></script>
CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
p{
margin-top: 15px;
margin-bottom: 15px;
}
Vue
const PortalVue = window['PortalVue'].default;
Vue.use(PortalVue);
Vue.component('card', {
template: `
<div class="item left">
<slot />
</div>
`,
})
Vue.component('component-a', {
template: '#A',
});
Vue.component('component-b', {
template: '#B',
});
Vue.component('component-c', {
template: '#C',
});
new Vue({
el: '#app',
data: {
show: 'A',
}
});