Skip to content

Instantly share code, notes, and snippets.

@treshugart
Last active April 11, 2018 12:57
Show Gist options
  • Save treshugart/b27bf304a5cba2f79b5eafa5436c414e to your computer and use it in GitHub Desktop.
Save treshugart/b27bf304a5cba2f79b5eafa5436c414e to your computer and use it in GitHub Desktop.
Vue renderer for SkateJS. In action: https://www.webpackbin.com/bins/-Ksoy2D-9EEMXzJU6BH_.
<x-vue yell>World</x-vue>
import { props, withProps } from 'skatejs/esnext/with-props';
import { withRender } from 'skatejs/esnext/with-render';
import Vue from 'vue';
// The base Vue component renderer.
//
// Since vue doesn't have an imperative re-render
// (at least I don't think it does) we only allow
// rendering the template once and subsequent prop
// sets don't actually render, but just update the
// instance it has stored from the first render.
const withVue = Base => class extends withRender(withProps(Base || HTMLElement)) {
rendererCallback(renderRoot, renderCallback) {
const { props } = this;
if (this._vue) {
Object.assign(this._vue, props);
} else {
// Vue calls cloneNode() so we can't use the
// shadowRoot directly as "el" because you can't
// clone a shadow root.
const vueRoot = document.createElement('div');
vueRoot.innerHTML = renderCallback();
renderRoot.appendChild(vueRoot);
this._vue = new Vue({
el: vueRoot,
data: props
});
}
}
}
// Simple custom element that uses the Vue renderer
// to show both slotted content via the real-slot
// and props.
class XVue extends withVue() {
static props = {
yell: props.boolean
}
renderCallback() {
return `
Hello,
<strong v-if="yell"><real-slot></real-slot></strong>
<real-slot v-else></real-slot>!
`;
}
}
// Vue eats <slot /> elements because it uses them
// for their internal distirbution algorithm, so we
// must work around it somehow. This just bypasses
// Vue and uses a custom element to render a real
// slot as light DOM. We can't do it as shadow DOM
// because it needs to appear in the context of the
// parent shadow root.
class RealSlot extends HTMLElement {
connectedCallback() {
this.innerHTML = '<slot></slot>';
}
}
customElements.define('real-slot', RealSlot);
customElements.define('x-vue', XVue);
@piyushchauhan2011
Copy link

I think the above bin is broken for skatejs 5.1.x onwards ? @treshugart . Is it possible to make it in sync with 5.1.1 ? Don't know how to make it work correctly with vuejs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment