uni-app父子组件v-model传值需遵循value/input规范,自定义key用v-model:xxx;app端nvue不支持v-model和uni.$on;props引用类型需深拷贝;跨组件通信优先url参数+onload,避免ref调用。

uni-app 父子组件用 v-model 传值最省事,但得写对绑定逻辑
uni-app 的 v-model 不是原生 Vue 那套的简单糖衣——它默认只认 value prop 和 input 事件。如果你自定义组件里用的是 props: ['msg'] + this.$emit('change', val),v-model 就会静默失效,没报错也没反应。
实操建议:
- 父组件写
<my-input v-model="searchText"></my-input> - 子组件必须声明
props: ['value'],且触发this.$emit('input', newValue) - 如果想换 key(比如用
msg代替value),得显式写v-model:msg="text"+ 子组件props: ['msg']+this.$emit('update:msg', val) - H5 和小程序平台都支持,但 App 端(nvue)不支持
v-model,得切回@input+:value手动绑定
跨层级或非父子组件用 uni.$emit / uni.$on,但别忘了销毁
uni-app 提供了全局事件总线 uni.$emit 和 uni.$on,适合页面跳转后、兄弟组件间、或者从 uni-app 页面向自定义组件传参这种“不好直接引用”的场景。
常见错误现象:页面 A 发送事件,页面 B 的组件监听了,但 B 被关闭后监听器还在内存里,下次进 A 再发一次,B 的旧实例就又响应一遍——结果数据错乱、重复请求、甚至报 Cannot read property 'xxx' of null。
实操建议:
- 在组件
mounted里用uni.$on('login-success', handler)监听 - 必须在
beforeDestroy(Vue 2)或onUnload(uni-app 生命周期)里调用uni.$off('login-success', handler) - 不要用匿名函数监听:
uni.$on('x', () => {...})→ 后续无法off - App 端 nvue 页面不支持
uni.$on,得改用uni.$emit+ 页面级onLoad中监听(仅限页面)
props 传对象或数组时,子组件改了父组件数据会意外同步
这是 JS 引用类型的老问题,但在 uni-app 里更容易被忽略——因为 template 里看不出深浅拷贝,props 又是只读警告(开发时可能关了提示),结果子组件一改 props.list.push(),父组件的数据就变了。
使用场景:表单组件接收一个 config 对象做初始设置,用户操作后子组件想更新它并同步给父组件。
实操建议:
- 子组件内部要用
JSON.parse(JSON.stringify(props.obj))或Object.assign({}, props.obj)做浅拷贝(仅一层) - 深层嵌套对象推荐用
lodash.cloneDeep,但注意小程序端不能直接 require,得用 npm 构建后引入 - 更稳妥的做法是:父组件传原始数据,所有修改都通过
$emit抛出去,由父组件决定是否更新自身 data - App 端 nvue 中,props 是深拷贝传递的,不会出现这个问题;但 H5 和微信小程序仍是引用传递
页面和自定义组件之间传值,优先走 url 参数 + onLoad,别硬绑 ref
有人想在页面里 ref 一个自定义组件然后直接调它的方法,比如 this.$refs.child.doSubmit()。这在 H5 上能跑,但微信小程序里 ref 指向的是虚拟节点,不是真实组件实例,调方法会报 doSubmit is not a function;App 端 nvue 更干脆,ref 根本不生效。
实操建议:
- 页面跳转传参统一走
uni.navigateTo({ url: '/pages/list/list?category=1&keyword=test' }) - 目标页面在
onLoad里取options.category,再通过props传给子组件 - 如果需要反向触发(比如子组件要通知页面刷新),用
uni.$emit+ 页面监听,比ref兼容性高得多 - 真要调子组件方法?只在 H5 场景下考虑,并加运行时判断:
if (uni.getSystemInfoSync().platform === 'h5') { this.$refs.child?.doX() }










