Messing with Vue.compile()

Abusing the internal compile API

by Thorsten

HTML

<div id="app">
  <button @click="index = 0">First</button>
  <button @click="index = 1">Second</button>
  <button @click="index = 2">I work, no staticRenderFns here</button>
  <dynamic v-bind:template="html[index]"></dynamic>
</div>

JavaScript

// Reference array sent to dynamic staticRenderFns
var staticRenderFns = [];

var dynamic = {
  props: ['template'],
  data() {
    return {
      templateRender: null,
    };
  },
  render(h) {
    if (!this.templateRender) {
      return h('div', 'loading...');
    } else { // If there is a template, I'll show it
      return this.templateRender();
    }
  },
  watch: {
  	// Every time the template prop changes, I recompile it to update the DOM
  	template:{
    	immediate: true, // makes the watcher fire on first render, too.
      handler() {
        var res = Vue.compile(this.template);

        this.templateRender = res.render;
        
        // staticRenderFns belong into $options, 
        // appearantly
        this.$options.staticRenderFns = []
        
        // clean the cache of static elements
        // this is a cache with the results from the staticRenderFns
        this._staticTrees = []
        
        // Fill it with the new staticRenderFns
        for (var i in res.staticRenderFns) {
          //staticRenderFns.push(res.staticRenderFns[i]);
          this.$options.staticRenderFns.push(res.staticRenderFns[i])
        }
      }
    }
  },
};

new Vue({
  el: "#app",
  data: {
    html: [
    	'<div><span>First template</span></div>',
			'<div><span>Second template</span></div>',
			'<div>Working template, no staticRenderFns here</div>'],
    index: 0,
  },
  components: {
    dynamic
  },
});