动态Vue组件
动态Vue组件允许您通过字符串形式的Vue单文件组件(SFC)内容来动态创建和渲染Vue组件。该组件支持完整的Vue SFC语法,包括template、script和style部分,并提供了样式隔离和错误处理机制。
基础使用
基本渲染
通过传入Vue单文件组件字符串来动态渲染组件:
js
const vueContent = `
<template>
<div class="dynamic-component">
<h3>{{ title }}</h3>
<p>{{ message }}</p>
<button @click="handleClick">点击我</button>
</div>
</template>
<script>
export default {
data() {
return {
title: '动态组件',
message: '这是一个动态渲染的Vue组件'
}
},
methods: {
handleClick() {
this.message = '按钮被点击了!'
}
}
}
</script>
<style scoped>
.dynamic-component {
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
}
</style>
`在FormCreate中使用
js
const rule = [
{
type: 'dynamic-render',
field: 'dynamicComponent',
props: {
vueContent: vueContent
}
}
]配置项
动态Vue组件提供了以下配置选项:
| 属性名 | 类型 | 默认值 | 必需 | 说明 |
|---|---|---|---|---|
| vueContent | String | - | 是 | Vue单文件组件字符串内容 |
事件
动态Vue组件提供了丰富的事件,方便您监听组件状态变化:
| 事件名 | 参数 | 说明 |
|---|---|---|
| mounted | element | 组件挂载完成事件,当动态组件渲染完成时触发 |
| error | error | 组件解析错误事件,当Vue内容解析失败时触发 |
| update:modelValue | value | 双向绑定值更新事件,当组件值变化时触发 |
事件使用示例
监听组件挂载:
js
function handleMounted(element) {
console.log('动态组件已挂载:', element);
// 可以在这里进行DOM操作或初始化
}监听解析错误:
js
function handleError(error) {
console.error('组件解析失败:', error);
// 显示错误提示给用户
showErrorMessage('组件内容解析失败,请检查语法');
}监听值变化:
js
function handleValueChange(value) {
console.log('组件值变化:', value);
// 可以实时保存数据或触发其他操作
}方法
动态Vue组件提供了多种方法,方便您进行程序化控制:
| 方法名 | 参数 | 说明 | 返回值 |
|---|---|---|---|
| reRender | - | 重新渲染组件 | - |
| removeStyle | id | 移除指定样式 | Boolean |
| clearAllStyles | - | 清除所有动态添加的样式 | Number |
方法使用示例
重新渲染组件:
js
function refreshComponent($inject) {
const dynamicRender = $inject.api.el('ref_dynamic_render');
dynamicRender.reRender();
}清除样式:
js
function clearStyles($inject) {
const dynamicRender = $inject.api.el('ref_dynamic_render');
const removedCount = dynamicRender.clearAllStyles();
console.log(`清除了 ${removedCount} 个样式`);
}支持的Vue语法
Template语法
支持完整的Vue模板语法:
vue
<template>
<!-- 条件渲染 -->
<div v-if="showContent">内容显示</div>
<!-- 列表渲染 -->
<ul>
<li v-for="item in list" :key="item.id">
{{ item.name }}
</li>
</ul>
<!-- 事件处理 -->
<button @click="handleClick">点击</button>
<!-- 属性绑定 -->
<input v-model="inputValue" :placeholder="placeholder" />
</template>Script语法
支持两种script语法:
Vue 2 Options API:
vue
<script>
export default {
data() {
return {
count: 0
}
},
computed: {
doubleCount() {
return this.count * 2
}
},
methods: {
increment() {
this.count++
}
},
watch: {
count(newVal) {
console.log('count changed:', newVal)
}
}
}
</script>Vue 3 Composition API (setup):
vue
<script setup>
import { ref, computed, watch } from 'vue'
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
const increment = () => {
count.value++
}
watch(count, (newVal) => {
console.log('count changed:', newVal)
})
</script>Style语法
支持CSS样式:
vue
<style>
.component-wrapper {
padding: 20px;
background: #f5f5f5;
}
.component-wrapper h3 {
color: #333;
margin-bottom: 10px;
}
</style>高级用法
与FormCreate集成
动态组件可以完美集成到FormCreate表单中:
js
const rule = [
{
type: 'dynamic-render',
field: 'customComponent',
props: {
vueContent: `
<template>
<div>
<el-input v-model="inputValue" placeholder="请输入内容" />
<el-button @click="submit">提交</el-button>
</div>
</template>
<script>
export default {
data() {
return {
inputValue: ''
}
},
methods: {
submit() {
console.log('提交值:', this.inputValue)
}
}
}
</script>
`
},
on: {
mounted: (element) => {
console.log('自定义组件已挂载')
}
}
}
]动态更新组件内容
js
function updateComponentContent($inject, newContent) {
const dynamicRender = $inject.api.el('ref_dynamic_render');
// 更新vueContent属性会触发重新渲染
dynamicRender.vueContent = newContent;
}错误处理
组件内置了完善的错误处理机制:
js
const rule = [
{
type: 'dynamic-render',
field: 'errorHandling',
props: {
vueContent: invalidVueContent
},
on: {
error: (error) => {
console.error('组件解析错误:', error);
// 可以显示友好的错误提示
showErrorToast('组件内容有误,请检查语法');
}
}
}
]注意事项
注意
该组件需要导入完整的 Vue 版本才能正常工作,请确保在构建配置中正确设置 Vue 别名。
1. Vue 版本配置
动态组件需要完整的 Vue 版本支持,请在构建配置中添加以下别名设置:
Vue 3 配置:
js
// vite.config.js
export default {
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js'
}
}
}js
// webpack.config.js
module.exports = {
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js'
}
}
}Vue 2 配置:
js
// vite.config.js
export default {
resolve: {
alias: {
vue: 'vue/dist/vue.esm.js'
}
}
}js
// webpack.config.js
module.exports = {
resolve: {
alias: {
vue: 'vue/dist/vue.esm.js'
}
}
}2. 外部资源限制
限制
动态组件内部不能通过 import 或 require 导入外部资源,包括:
- 外部 JavaScript 模块
- CSS 文件
- 图片资源
- 字体文件
不支持的用法:
vue
<script>
// ❌ 不支持外部模块导入
import { someFunction } from './utils'
import axios from 'axios'
// ❌ 不支持外部样式导入
import './styles.css'
export default {
data() {
return {}
}
}
</script>
<style>
/* ❌ 不支持外部资源引用 */
@import url('https://fonts.googleapis.com/css2?family=Roboto');
</style>推荐的替代方案:
vue
<script>
export default {
data() {
return {}
},
methods: {
// ✅ 使用内联代码
someFunction() {
// 函数实现
},
// ✅ 使用全局变量
getApi() {
return window.axios || fetch
}
}
}
</script>
<style>
/* ✅ 使用内联样式 */
.component {
font-family: 'Arial', sans-serif;
color: #333;
}
</style>

