VNode 动态生成表单项的核心是将表单结构转为数据驱动的 JavaScript 逻辑,通过配置化字段、用 h 函数手动实现 v-model、封装渲染函数并在 render 中动态调用,确保响应式更新。

用 VNode 动态生成表单项,核心在于把表单结构从模板中“解放”出来,转为数据驱动的 JavaScript 逻辑。不是写一堆 v-if 套娃,而是让字段配置决定渲染什么、怎么绑定、如何校验——真正实现“配置即 UI”。
表单字段配置化:先定义可执行的数据结构
每个字段应是一个对象,明确类型、绑定字段、校验规则、UI 属性等:
-
type:如
'input'、'select'、'date-picker'、'switch' -
model:对应响应式变量的 key(如
'username'),用于双向绑定 - label:显示文本
-
props:透传给组件的属性(如
{ clearable: true, placeholder: '请输入' }) -
rules:校验规则数组(可直接对接 Element Plus 的
el-form规则格式)
示例配置:
const formConfig = [
{ type: 'input', model: 'username', label: '用户名', props: { maxlength: 12 } },
{ type: 'select', model: 'role', label: '角色', props: { options: ['admin', 'user'] } },
{ type: 'date-picker', model: 'joinDate', label: '入职日期' }
]
用 h 函数精准创建组件 VNode:注意事件与 v-model 的等效写法
Vue 3 中,v-model 是语法糖,本质是 modelValue prop + onUpdate:modelValue 事件。动态渲染时必须手动还原:
- 对
ElInput:传modelValue: data[field.model]和onUpdate:modelValue: val => data[field.model] = val - 对
ElSelect:同样处理modelValue和onUpdate:modelValue,再额外传options等 props - 事件监听统一用
onXxx形式(如{ onClick: handler }),不能写@click
关键点:所有响应式值必须在 render() 函数体内读取(如 data[field.model]),才能建立依赖追踪,触发重渲染。
使用一条命令部署ProbeChain Rydberg测试网代理节点。自动注册为Agent(NodeType=1),免gas,支持macOS/Linux/Windows。触发词:/r
封装字段渲染逻辑:避免重复判断,提升可维护性
不要在 render 主体里堆 if-else,把每种类型抽成独立函数:
const renderField = (h, field, data, update) => {
const value = data[field.model]
const commonProps = {
modelValue: value,
'onUpdate:modelValue': val => update(field.model, val),
...field.props
}
const handlers = {
input: () => h(ElInput, commonProps),
select: () => h(ElSelect, { ...commonProps, options: field.props?.options || [] }),
'date-picker': () => h(ElDatePicker, commonProps)
}
return handlers[field.type]?.() || h('span', `不支持的类型: ${field.type}`)
}
在主 render 中调用:
render() {
return h('el-form', { model: data, rules },
formConfig.map(field =>
h('el-form-item', { label: field.label },
renderField(h, field, data, (key, val) => data[key] = val)
)
)
)
}
解决“能聚焦但无法输入”的常见陷阱
这是动态渲染表单最典型的失败现象,根本原因是 VNode 创建时机错误:
- ❌ 错误:在
setup顶层直接调用h()生成静态 VNode,它只执行一次,后续数据变化不触发更新 - ✅ 正确:把 VNode 创建逻辑包装成函数,在
render()内每次调用,确保访问响应式变量时建立新依赖 - ✅ 衍生建议:使用
shallowRef包裹大型表单数据,避免深度响应式开销;用computed预处理字段映射关系,减少 render 中计算
本质上,render 函数不是“生成一次就完事”,而是“每次需要视图更新时,都重新运行一遍”。只要逻辑在函数体内,Vue 就能捕获变化并重绘。

















