Makes sense because htmlspecialchars() doesn't protect against malicious Vue template expressions, it only converts characters that are used to represent html tags, entities or attributes (<>"'&) IIRC.
I think another solution (besides v-pre) to "fixing" it (though you might say that relying on htmlspecialchars() to protect against user-supplied {{vue expressions}} was unwise to begin with) is to replace { and } with { and } after using htmlspecialchars/htmlentities.
EDIT: Another solution would be to pass a different set of delimiters to Vue that uses characters that would be escaped by htmlspecialchars, like demonstrated in [1] or like so:
Vue.options.delimiters = ['<%', '%>'];
[1]: https://stackoverflow.com/a/40538194/4522571