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