Templates for Vue Functional Components On the Fly

Denny Headrick
Jan 8, 2018 · 2 min read

Recently, the Vue.js team pushed out an update that would allow for templates to be used for functional components. I was disappointed to find out that this change appears to only be useful for the Vue-Loader (Webpack).

I wrote a quick function to compile my templates and make them useful for functions. The biggest hurdle was dealing with the static functions which introduced some scoping issues that I could not get a grasp of.

Vue.functionalComponent = function(componentName, options){  function rewriteFn(fn, ctx){      var fnString = fn.toString()
.replace('with(this)', 'with(ctx)')
.replace('anonymous()', 'anonymous(_c, ctx)');
var newFn = eval('(' + fnString + ')');
return newFn.bind(ctx);
}
var options = options || {};
options.functional = true;
var template;
if(options.template.charAt(0) === '#'){
template = document.getElementById(options.template.substr(1)).innerHTML;
} else {
template = options.template;
}
template = avoidStaticRender(template);
var renderFns = Vue.compile(template);
var render = rewriteFn(renderFns.render, options);
options.render = render;
return Vue.component(componentName, options);
}

These helpers help me avoid the compiler making static render functions

Vue.directive("nothing",{});
function avoidStaticRender(template){
var templateEl = document.createElement("div");
templateEl.innerHTML = template;
var everyEl = templateEl.getElementsByTagName("*");
for(var i = 0; i < everyEl.length; i++){
everyEl[i].setAttribute("v-nothing", true);
}
return templateEl.innerHTML;
}

Demo:

The functional templates are faster than the normal templates in the demo sparing 500 ms, on average, with 10000 rendered elements. The ratio seemed to be fairly similar as I increased the numbers.

This code hasn’t been heavily tested, but it succeeded in dealing with the couple of things that I threw at it.

Denny Headrick loves working with and writing about Vue.js. You can follow him on Twitter at @dennythecoder. If you enjoyed the article, please share on your favorite social media platform. Thanks for reading!

Denny Headrick

Written by

https://dennyheadrick.com

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade