You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VueJS 3:如何重新渲染替换后的模板及替代方案咨询

问题解答

1. 如何渲染新模板?

你当前的核心问题是直接返回字符串模板给render函数时,Vue会将其识别为纯文本而非可解析的HTML/组件。要解决这个问题,需要把合并后的字符串模板编译成Vue可执行的渲染函数,生成VNode后再渲染。

具体实现步骤:

  1. 确保Vue项目启用运行时编译:Vue CLI项目可在vue.config.js中添加配置:
module.exports = {
  runtimeCompiler: true
}
  1. 在父组件中导入Vue的编译函数:
import { defineComponent, compile } from "vue";
  1. 修改父组件的data和方法,存储编译后的渲染函数而非字符串:
data() {
    return {
        currentFilterTemplate: null,
        currentRenderFn: null // 存储编译后的渲染函数
    }
},
render() {
    // 优先使用编译后的渲染函数,否则编译默认模板
    return this.currentRenderFn ? this.currentRenderFn(this) : compile(tpl)(this);
},
methods: {
    _mergeDefaultTemplateWithCurrentFilterTemplate() {
        const mergedTemplate = tpl.replace('<li class="dynamic-filters"></li>', this.currentFilterTemplate);
        // 将字符串模板编译为可执行的渲染函数
        this.currentRenderFn = compile(mergedTemplate);
    },
    // 保留其他原有方法
}

修改后,合并后的模板会被编译成能生成正确DOM节点的渲染函数,不会再显示纯文本。

2. 使用Slot/DynamicComponent的替代方案(推荐)

字符串替换模板的方式不符合Vue组件化思想,更推荐用**插槽(Slot)**实现父子组件模板的复用与填充,这是最适配场景的方案:

方案一:使用插槽(Slot)

父组件修改:

  • 父模板template.tpl改为预留命名插槽,将动态内容的控制权交给子组件:
<ul class="filters">
    <!-- 命名插槽,用于子组件填充filter项 -->
    <slot name="filter-items"></slot>
</ul>
  • 父组件删除模板替换相关方法,简化逻辑:
render() {
    return compile(tpl)(this);
},
// 删除setCustomFilterTemplate、_mergeDefaultTemplateWithCurrentFilterTemplate等方法

子组件修改:

  • 子模板template.tpl改为填充父组件的命名插槽:
<template #filter-items>
    <li v-for="filter in filterList">
        <div @click="$emit('filterCollection', filter.key)">
            {{ filter.name }}
        </div>
    </li>
</template>
  • 子组件删除setFilterTemplate方法,插槽会自动填充父组件对应位置,无需手动传递模板字符串:
methods: {
    setList():void {
        this.hasResults = true;
        this.filterList = {
            "filterA": {
                "id": "filter_a",
                "key": "filterA",
                "name": "Filter A"
            },
            "filterB": {
                "id": "filter_b",
                "key": "filterB",
                "name": "Filter B"
            }
        }
    }
}

这种方式完全利用Vue的插槽机制,自动处理指令解析与DOM渲染,既解决了纯文本问题,又让代码更简洁符合Vue设计理念。

方案二:使用DynamicComponent(动态组件)

如果需要动态切换不同的Filter组件,可采用动态组件方案:

  1. 父模板预留动态组件位置:
<ul class="filters">
    <component :is="currentFilterComponent"></component>
</ul>
  1. 父组件添加数据存储动态组件,子组件传递自身的Filter项组件:
// 父组件data
data() {
    return {
        currentFilterComponent: null
    }
}

// 子组件methods
setFilterTemplate() {
    // 导入封装好的Filter项独立组件
    import('./FilterItem.vue').then(module => {
        this.currentFilterComponent = module.default;
    });
}

该方案适合多组件动态切换场景,若只是固定父子模板填充,插槽方案更简单直接。


内容的提问来源于stack exchange,提问作者rammi22

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 06:25:20