单向数据流要求子组件不得直接修改props,须通过$emit通知父组件更新;需本地编辑时应深拷贝初始化副本;只读加工用computed,慎用watch避免循环。

单向数据流在 Options API 中体现为“父组件传数据、子组件用数据、子组件不能改数据”,核心是让数据流向清晰可溯。它不是限制,而是为了防止状态混乱——比如多个子组件同时改同一个 prop,父组件就再也搞不清谁动了哪部分。
Prop 是只读的,改它会报错
Vue 在开发模式下会对 props 做只读代理:你在子组件的 data、methods 或 mounted 里直接赋值,比如 this.msg = '新内容',控制台立刻警告“Avoid mutating a prop directly”。这不是 Vue 小气,而是它在帮你拦截危险操作。
- props 对象本身不可赋值(
this.$props = {}不行) - props 里的对象属性也不能直接改(
this.user.name = '李四'看似没报错,但破坏了单向语义,父组件无法感知) - 数组方法如
push、splice同样属于违规(引用未变,但内部已变)
正确做法:用事件通知父组件更新
子组件不改数据,只发“请求”。父组件收到后,自己决定怎么改、要不要改。
- 子组件调用
this.$emit('update:xxx', newValue),比如this.$emit('update:title', '新标题') - 父组件用
v-model:title或显式监听:@update:title="title = $event" - 若用普通事件名(如
@change),父组件需在 methods 中写逻辑处理,再更新自身 data
需要本地编辑时,别复制 props,要初始化副本
如果子组件要做表单编辑,又不想影响父组件原始数据,就该在 data() 里声明独立变量,初始值来自 props,但后续变更与 props 脱钩。
- 写法:
data() { return { localTitle: this.title } } - 编辑时只改
localTitle,提交时再通过$emit把最终值交还给父组件 - 注意:不要写成
localUser: this.user(浅拷贝对象仍共享引用),要用JSON.parse(JSON.stringify(this.user))或structuredClone深拷贝
避免陷阱:计算属性和 watch 的配合使用
有些场景需要基于 props 衍生展示状态,比如把用户名转大写、按条件过滤列表。这类只读加工应该用 computed,而不是在 data 里存一份可变副本。
- 推荐:
computed: { upperName() { return this.name?.toUpperCase() } } - 慎用
watch监听 props 并反向写入 data —— 容易引发循环或覆盖,除非你明确需要响应式同步且能控制节奏 - watch 回调里不要直接改 props,只能触发 emit 或更新本地 data
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











