JSFiddle - React, Tailwind, and code Playground
by simati
HTML
<div id="app">
<Child title="level 1">
<section>
<p>Not a child</p>
<Child title="level 2">
<Child title="level 3"/>
</Child>
</section>
</Child>
</div>
CSS
section {
background: rgba(0,0,0,.1);
margin-left: 20px;
padding: 20px;
position: relative;
}
input {
position: absolute;
top: 0;
right: 0;
}
Babel + JSX
const Child = {
props: ['title'],
provide() {
return {
injectedContext: this.context
};
},
inject: ['injectedContext'],
data() {
return {
titleData: this.title,
$private: {
context: this.computeContext()
}
}
},
computed: {
context: {
get() {
return this.$data.$private.context;
}
}
},
watch: {
// Update context when local properties change
titleData() { this.updateContext(); }
},
methods: {
computeContext() {
const leadingBreadcrumb = this.injectedContext ? `${this.injectedContext.breadcrumb} > ` : '';
return {
breadcrumb: `${leadingBreadcrumb}${this.titleData}`
}
},
updateContext() {
const computed = this.computeContext();
this.$data.$private.context.breadcrumb = computed.breadcrumb;
}
},
created() {
// Update context when inherited context changes
this.$watch('injectedContext', () => this.updateContext(), { deep: true, immediate: true });
},
template: `<section>{{ context.breadcrumb }}<input type="text" v-model="titleData"/><slot name="default"/></section>`
}
new Vue({
el: '#app',
provide() {
return {
injectedContext: null
}
},
components: { Child }
})