Im trying render template of vue component from string. I test it on simple html but I would like to render komplex string including another components.
我正在尝试从字符串中呈现vue组件的模板。我在简单的html上测试了它,但我想渲染包含其他组件的komplex字符串。
I use vuejs version 3.3.4 and for compilation import { compile } from 'vue-template-compiler';
I can't use Vue from vue because in my version it doesn't exist.
我使用vuejs 3.3.4版本,并从“vue模板编译器”进行编译导入{compile};我不能从Vue中使用Vue,因为在我的版本中它不存在。
I tried few versions and I get to the point, where i can compile string to object with render function that Im not able use.
我尝试了几个版本,我已经到了关键的地步,我可以用我不能使用的render函数将字符串编译成对象。
I made component with render method which call compile method on string and return object with render function. Problem is that render function can't be called.
First it is because it is string of function and not a function.
Second problem is that when i convert it to function by new Function() and call it, it crash to not defined functions like _c(), _v() which are in generated function.
我用render方法制作了一个组件,它调用字符串上的compile方法,并用render函数返回对象。问题是无法调用呈现函数。首先是因为它是函数的字符串,而不是函数。第二个问题是,当我通过new function()将其转换为函数并调用它时,它会崩溃为生成函数中未定义的函数,如_c()、_v()。
My component:
我的组件:
<FsDynamicHtml :html="content"></FsDynamicHtml>
content="<h1> Test </h1>"
content=“
测试
”
<script lang="ts">
import { defineComponent } from 'vue'
import { compile } from 'vue-template-compiler';
export default defineComponent({
name: "FsDynamicHtml",
components: { compile },
props: {
html: { type: String},
},
computed: {
},
methods: {
template: function (){
if (this.html) {
const compiled = compile(this.html); //returns object with render (string) "with(this){return _c('h1',[_v(" Test ")])}"
return compiled;
}
return null;
},
},
render(createElement) {
if (this.template) {
const render = this.template().render
const fnc = new Function(render);
return fnc(); //Uncaught (in promise) ReferenceError: _c is not defined
//I tried bind createElement and this to function like (new Function(render).bind(this))
//return render; //write text: with(this){return _c('h1',[_v(" Test ")])}
//return this.template(); //[Vue warn]: Invalid VNode type: undefined (undefined) at <FsDynamicHtml html = "<h1>Test</h1>">
//return new Function(this.template().render)(); //Uncaught (in promise) ReferenceError: _c is not defined
}
return null;
}
})
</script>
<style scoped>
</style>
I commented in code some tried ways with results.
我在代码中评论了一些尝试过的方法和结果。
I dont really know what should i return from render function, i expected result of function render of compilated html.
我真的不知道我应该从render函数返回什么,我期望编译后的html的函数render的结果。
Thank you for help.
谢谢你的帮助。
Edit:
Working version for Me (thx Ali Bahrami):
编辑:我的工作版本(thx Ali Bahrami):
<script lang="ts">
import { defineComponent, compile } from 'vue';
export default defineComponent({
name: "FsDynamicHtml",
props: {
html: { type: String },
},
computed: {
compiledRenderFn() {
if (this.html) {
var render = compile("<span style='color: red'>zzz</span>"+this.html);
return render;
}
return null;
},
},
render() {
if (this.compiledRenderFn) {
return this.compiledRenderFn(this);
}
return null;
},
});
</script>
Compile returns function (below) which require _ctx parameter and for that must be this.compiledRenderFn(this); called with this parameter or any parameter.
Compile返回函数(如下),该函数需要_ctx参数,并且必须是this.compiledRenderFn(this);使用此参数或任何参数调用。
(function anonymous(Vue
) {
const _Vue = Vue
const { createElementVNode: _createElementVNode } = _Vue
const _hoisted_1 = /*#__PURE__*/_createElementVNode("span", { style: {"color":"red"} }, "zzz", -1 /* HOISTED */)
const _hoisted_2 = /*#__PURE__*/_createElementVNode("h1", null, " Test ", -1 /* HOISTED */)
return function render(_ctx, _cache) {
with (_ctx) {
const { createElementVNode: _createElementVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock(_Fragment, null, [
_hoisted_1,
_hoisted_2
], 64 /* STABLE_FRAGMENT */))
}
}
})
更多回答
It seems like you're trying to compile a Vue template at runtime using the vue-template-compiler
. However, you're using Vue 3
, and vue-template-compiler
is meant for Vue 2
. In Vue 3
, the equivalent package is called @vue/compiler-sfc
.
您似乎正在尝试使用Vue模板编译器在运行时编译Vue模板。然而,您使用的是Vue3,而Vue模板编译器适用于Vue2。在Vue3中,等效的包被称为@Vue/compiler-sfc。
So, install it:
因此,安装它:
npm install @vue/compiler-sfc
Then update your script to import the compile function from the vue package and use it to compile your template to a render function:
然后更新脚本,从vue包导入编译函数,并使用它将模板编译为渲染函数:
<script lang="ts">
import { defineComponent, compile } from 'vue';
export default defineComponent({
name: "FsDynamicHtml",
props: {
html: { type: String },
},
computed: {
compiledRenderFn() {
if (this.html) {
const { render } = compile(this.html);
return render;
}
return null;
},
},
render() {
if (this.compiledRenderFn) {
return this.compiledRenderFn();
}
return null;
},
});
</script>
Hope this helps!
希望这能有所帮助!
更多回答
Oh god, thank you. After with@vue/compiler-sfc it works. I edited a function compiledRenderFn a bit. Compile render was returned undefined and compile returns function which expected parameter to with function. I will write it to main thread.
天啊,谢谢你。之后with@vue/编译器sfc它工作。我编辑了一个函数compiledRenderFn。编译呈现返回了未定义的结果,而编译返回的函数应为带函数的参数。我会把它写在主线上。
我是一名优秀的程序员,十分优秀!