Last active
January 8, 2024 12:37
-
-
Save webuilder240/9f7fc6e5394bffdf957a13b092df4a0d to your computer and use it in GitHub Desktop.
tiny island Architecture Codes (not SSR
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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