I tried helpers to mount react and vue components via webcomponents.
https://github.com/mizchi/wc-helpers
My goal is to try micro-frontend.
import {
vueElementFactory,
reactElementFactory,
encodeProps
} from "@mizchi/wc-helpers";
// register
customElements.define("my-react-component", reactElementFactory(MyReactApp));
customElements.define("my-vue-component", vueElementFactory(MyVueApp));
// run
const state = { a: 0 };
const encoded = encodeProps(state);
document.body.innerHTML = `
<my-react-component data-props="${encoded}"></my-react-component>
<my-vue-component data-props="${encoded}"></my-vue-component>
`;
Mount another platform
- my-react-component(depth=n) => my-vue-component(depth=n-1)
- my-vue-component(depth=n) => my-react-component(depth=n-1)
HTML
Code
import Vue from "vue";
import Component from "vue-class-component";
import React from "react";
import { vueElementFactory, reactElementFactory, encodeProps } from "..";
// Vue
@Component({
props: ["depth"]
})
class MyVueApp extends Vue {
now: number = Date.now();
render(h: any) {
const depth = parseInt(this.$props.depth, 10);
if (depth > 0) {
return h(
"div",
{
style: {
paddingLeft: "10px",
backgroundColor: "rgba(0, 255, 0, 0.3)"
}
},
[
h("p", {}, `vue: ${depth} createdAt:${this.now}`),
h("my-react-component", {
attrs: {
"data-props": encodeProps({ depth: depth - 1 })
}
})
]
);
} else {
return h(
"p",
{
style: {
paddingLeft: "10px",
backgroundColor: "rgba(0, 255, 0, 0.3)"
}
},
`vue: 0 - createtAt:${this.now}`
);
}
}
}
customElements.define("my-vue-component", vueElementFactory(MyVueApp));
// React
class MyReactApp extends React.PureComponent<{ depth: string }> {
now: number = Date.now();
render() {
const h = React.createElement;
const depth = parseInt(this.props.depth, 10);
if (depth > 0) {
return h(
"div",
{
style: {
paddingLeft: "10px",
backgroundColor: "rgba(255, 0, 0, 0.3)"
}
},
h("p", {}, `react: ${depth} createdAt: ${this.now}`),
h("my-vue-component", {
"data-props": encodeProps({ depth: depth - 1 })
})
);
} else {
return h(
"p",
{
style: {
paddingLeft: "10px",
backgroundColor: "rgba(255, 0, 0, 0.3)"
}
},
"react 0: createdAt " + this.now
);
}
}
}
customElements.define("my-react-component", reactElementFactory(MyReactApp));
// run
// const root = document.querySelector(".root");
let state = { depth: 4 };
const entry = document.createElement("my-react-component");
entry.setAttribute("data-props", state.depth.toString());
document.body.appendChild(entry);
setInterval(() => {
state = { depth: state.depth + 1 };
entry.setAttribute(
"data-props",
encodeProps({ depth: (state.depth % 6) + 3 })
);
}, 1000);
How it works
- Encode json to safe string
- Define Component
- Listen
data-props
'sattributeChangedCallback
- re-render
See implementation (114 lines) https://github.com/mizchi/wc-helpers/blob/master/index.ts
Why wc-helper
needs encode
WebComponents takes properties as string only. If you need to handle event handlers, try lit-html
and lit-html/lib/lit-extended
.
Top comments (0)