Skip to content

Instantly share code, notes, and snippets.

@webuilder240
Last active January 8, 2024 12:37
Show Gist options
  • Save webuilder240/9f7fc6e5394bffdf957a13b092df4a0d to your computer and use it in GitHub Desktop.
Save webuilder240/9f7fc6e5394bffdf957a13b092df4a0d to your computer and use it in GitHub Desktop.
tiny island Architecture Codes (not SSR
module ApplicationHelper
def vue_island(name, init_props: {}, mount: false , &block)
content_tag("vue-island", '', "data-name": name, "data-init-props": init_props.to_json, "data-mount-mode": mount) do
yield if block_given?
end
end
def vue2_island(name, init_props: {}, mount: false , &block)
content_tag("vue2-island", '', "data-name": name, "data-init-props": init_props.to_json, "data-mount-mode": mount) do
yield if block_given?
end
end
end
import Vue from 'vue';
class Vue2Island extends HTMLElement {
constructor() {
super();
this.vueInstance = null;
}
connectedCallback() {
this.name = this.dataset.name
this.mountMode = this.dataset.mountMode === 'true'
this.loadVueInstance();
}
kebabToPascalCase(str) {
return str.split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('');
}
async loadVueInstance() {
const props = this.initalProps()
const hasProps = (Object.keys(props).length > 0)
if (!this.vueInstance) {
// カスタムエレメントの名前を元にVueコンポーネントを特定
const componentName = this.kebabToPascalCase(this.name);
const componentModule = await import(`../components/${componentName}.vue`);
const AsyncComponent = Vue.extend(componentModule.default);
if (hasProps) {
this.vueInstance = new Vue({
render: h => h(AsyncComponent, {props: props}),
}).$mount();
} else {
this.vueInstance = new Vue({
render: h => h(AsyncComponent),
}).$mount();
}
this.appendChild(this.vueInstance.$el);
}
}
unloadVueInstance() {
if (this.vueInstance) {
this.vueInstance.$destroy();
this.vueInstance = null;
}
}
initalProps() {
return JSON.parse(this.dataset.initProps || '{}');
}
disconnectedCallback() {
this.unloadVueInstance();
}
}
customElements.define("vue2-island", Vue2Island)
import { h, createApp, defineAsyncComponent } from 'vue/dist/vue.esm-bundler';
class VueIsland extends HTMLElement {
constructor() {
super()
this.vueInstance = null
}
connectedCallback() {
this.name = this.dataset.name
this.mountMode = this.dataset.mountMode === 'true'
this.loadVueInstance()
}
kebabToPascalCase(str) {
return str.split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('');
}
async loadVueInstance() {
const props = this.initalProps()
if (!this.vueInstance) {
if (this.mountMode) {
const componentName = this.kebabToPascalCase(this.name);
// const componentModule = await import(`../components/${componentName}.js`);
const componentModule = await import(`../components/${componentName}`);
this.vueInstance = createApp(componentModule.default)
this.vueInstance.mount(this);
} else {
const componentName = this.kebabToPascalCase(this.name);
const componentModule = await import(`../components/${componentName}.vue`);
const AsyncComponent = componentModule.default;
const hasProps = (Object.keys(props).length > 0)
if (hasProps) {
this.vueInstance = createApp({
render() {
return h(AsyncComponent, props);
}
});
} else {
this.vueInstance = createApp({
render() {
return h(AsyncComponent);
}
});
}
this.vueInstance.mount(this);
}
}
}
initalProps() {
return JSON.parse(this.dataset.initProps || '{}');
}
unloadVueInstance() {
if (this.vueInstance) {
this.vueInstance.unmount();
this.vueInstance = null;
}
}
disconnectedCallback() {
this.unloadVueInstance();
}
}
customElements.define("vue-island", VueIsland)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment