<div id="app">
</div>
const templates = [];
const templatesContainer = document.getElementById('app');

// We iterate through each custom templates and precompile them
for (var i = 0; i < templatesContainer.children.length; i++) {
  const template = templatesContainer.children.item(i);
  templates.push({
    name: template.nodeName.toLowerCase(),
    renderFunction: Vue.compile(template.innerHTML),
  });
}

// This component is going to have a custom render function that will check if there's a custom template
Vue.component('overridable', {
  props: ['name'],
  render(createElement) {
    const template = templates.find(x => x.name === this.name);

    // We return the default content using the default slot.
    if (!template) {
      return this.$slots.default[0];
    }
    
    // Using the precompiled render function
    return template.renderFunction.render.call(this.$parent, createElement);
  }
});

Vue.component('heading', {
  props: ['title'],
  template: `
  <overridable name="heading">
    <h1>
      {{ title }}
    </h1>
  </overridable>`
});

new Vue({
  el: '#app',
  template: `<heading title="Hello world"></heading>`
});
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdn.jsdelivr.net/npm/vue