uni-app父子组件传值仅有props(父→子)和$emit(子→父)两条主路;props须带冒号绑定且子组件必须显式声明,引用类型修改会同步影响父组件;$emit事件名须用短横线,v-model需严格配对value/input或update:xxx,nvue端不支持v-model。

uni-app 里父子组件传值只有两条主路:props(父→子)和 $emit(子→父),别指望 ref 或 v-model 自动兜底——它们要么受限于平台,要么需要严格配对规则。
父组件怎么把数据传给子组件:冒号和声明缺一不可
绑定必须带冒号,否则传的是字符串字面量::title="parentTitle" ✅,title="parentTitle" ❌。Vue 3 版本下 :title="{{parentTitle}}" 已废弃,直接报错或静默失败。
子组件必须显式声明 props,哪怕只写 props: ['title']。不声明就直接在模板里用 {{title}},H5 可能正常,小程序端大概率白屏——各端对未声明 props 的处理策略不一致。
- 引用类型(如
Object、Array)传入后,子组件内部修改会同步影响父组件数据。这不是 bug,是 JS 引用特性 - 避免方式:浅拷贝用
Object.assign({}, props.config)或[...props.list];深层嵌套推荐lodash.cloneDeep(需 npm 构建引入,小程序不支持require直接调用) - 更稳妥做法:所有修改都通过
$emit抛出去,由父组件决定是否更新自身data
子组件怎么把数据回传给父组件:事件名必须用短横线
子组件触发 this.$emit('update-user', payload),父组件监听 @update-user="handler"。这是全平台兼容写法。
别用驼峰:this.$emit('updateUser') ❌ —— 微信小程序会转成小写,父组件得监听 @updateuser 才能收到,极难排查;也别用下划线:this.$emit('update_user') ❌ —— 某些平台支持不稳定。
- 子组件内部不要在
data里定义和props同名的变量,比如props: ['value']却又写data() { return { value: '' } },会导致响应式丢失,Vue 会警告 “Avoid mutating a prop directly”,但 uni-app 某些版本只是静默忽略 - Vue 3
setup中用defineProps接收时,切勿解构:const { modelValue } = defineProps(['modelValue'])❌ —— 解构后丢失响应性;应保持props.modelValue原样访问
v-model 怎么配才不白忙:value/input 或 update:xxx 必须手动对齐
v-model 不是自动生效的,得按规则配对。默认只认 value prop 和 input 事件。写 <my-input v-model="text"></my-input>,子组件必须:
- 声明
props: ['value']
- 触发
this.$emit('input', newValue)
想换 key,比如用 msg,就得显式写:
- 父组件:
<my-input v-model:msg="text"></my-input> - 子组件:
props: ['msg']+this.$emit('update:msg', val)
注意:App 端(nvue)不支持 v-model,必须退回到手动绑定::msg="text" @update:msg="text = $event"。
跨端兼容最容易被忽略的点:nvue 端能力阉割严重
nvue 渲染模式下,以下能力全部不支持:
-
v-model(包括v-model:xxx语法) -
uni.$on/uni.$off(全局事件总线) - 具名
slot(只支持默认<slot></slot>) -
ref调用子组件方法(无法获取实例)
这意味着,一旦你写了 v-model 并测试于 H5 或小程序,上线到 App 端就会静默失效;用 uni.$on 做登录状态广播,在 App 端根本收不到。最稳的做法是:在 nvue 页面中,所有通信回归原始路径——URL 参数 + onLoad 回调,或父组件显式传递回调函数。










