使用Vue Composition API / Vue 3监听props变化

使用Vue Composition API / Vue 3监听props变化

技术背景

在Vue 3中引入了Composition API,它提供了更灵活的方式来组织和复用组件逻辑。在开发过程中,经常需要监听组件props的变化以执行相应的操作,但Vue Composition API RFC参考站点和相关文档中并没有明确给出监听props变化的示例。

实现步骤

1. 直接监听单个prop

通过传入一个返回prop值的函数作为watch的第一个参数来监听单个prop的变化。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { watch } from 'vue';

export default {
props: {
selected: {
type: [String, Number],
required: true
}
},
setup(props) {
watch(() => props.selected, (newValue, oldValue) => {
console.log('Watch props.selected function called with args:', newValue, oldValue);
});

return {};
}
};

2. 监听多个prop

可以传入一个包含多个返回prop值的函数的数组来监听多个prop的变化。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { watch } from 'vue';

export default {
props: {
prop1: {
type: String,
required: true
},
prop2: {
type: Number,
required: true
}
},
setup(props) {
watch([() => props.prop1, () => props.prop2], ([newProp1, newProp2], [oldProp1, oldProp2]) => {
console.log('Prop1 changed from', oldProp1, 'to', newProp1);
console.log('Prop2 changed from', oldProp2, 'to', newProp2);
});

return {};
}
};

3. 监听复杂类型的prop

对于对象或数组类型的prop,可以使用deep选项来进行深度监听。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { watch } from 'vue';

export default {
props: {
complexType: {
type: Object,
default: () => ({})
}
},
setup(props) {
watch(() => props.complexType, (newValue, oldValue) => {
console.log('Complex type prop changed:', newValue, oldValue);
}, { deep: true });

return {};
}
};

4. 将props对象转换为Ref对象

使用toRefsprops对象转换为Ref对象,然后可以直接将Ref对象作为watch的第一个参数。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { watch, toRefs } from 'vue';

export default {
props: {
title: {
type: String,
required: true
}
},
setup(props) {
const { title } = toRefs(props);

watch(title, (newValue, oldValue) => {
console.log('Title prop changed from', oldValue, 'to', newValue);
});

return {};
}
};

核心代码

以下是一个完整的示例,展示了如何在Vue 3中使用Composition API监听props的变化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<div>
<p>Prop value: {{ selected }}</p>
</div>
</template>

<script>
import { watch } from 'vue';

export default {
props: {
selected: {
type: [String, Number],
required: true
}
},
setup(props) {
watch(() => props.selected, (newValue, oldValue) => {
console.log('Prop changed from', oldValue, 'to', newValue);
});

return {};
}
};
</script>

最佳实践

  • 避免不必要的监听:大多数情况下,直接在模板或setup函数中使用props即可,Vue会自动处理响应式更新,无需手动监听。
  • 使用toRefstoRef:当需要保留props的响应式时,可以使用toRefstoRefprops转换为Ref对象。
  • 深度监听要谨慎:对于复杂类型的prop,使用deep选项进行深度监听可能会影响性能,应谨慎使用。

常见问题

1. 监听props时传入错误类型的参数

在使用watch监听props时,如果直接传入props对象或prop的值,而不是一个返回prop值的函数,会导致监听失败。例如:

1
2
3
4
// 错误示例
watch(props.selected, (newValue, oldValue) => {
console.log('Watch props.selected function called with args:', newValue, oldValue);
});

正确的做法是传入一个返回prop值的函数:

1
2
3
4
// 正确示例
watch(() => props.selected, (newValue, oldValue) => {
console.log('Watch props.selected function called with args:', newValue, oldValue);
});

2. 监听复杂类型的prop时未使用deep选项

如果要监听对象或数组类型的prop的内部变化,需要使用deep选项,否则只有当prop的引用发生变化时才会触发监听回调。例如:

1
2
3
4
5
6
7
8
9
// 未使用deep选项,只有当props.complexType的引用发生变化时才会触发回调
watch(() => props.complexType, (newValue, oldValue) => {
console.log('Complex type prop changed:', newValue, oldValue);
});

// 使用deep选项,可以监听props.complexType内部属性的变化
watch(() => props.complexType, (newValue, oldValue) => {
console.log('Complex type prop changed:', newValue, oldValue);
}, { deep: true });

使用Vue Composition API / Vue 3监听props变化
https://119291.xyz/posts/watch-props-change-with-vue-composition-api/
作者
ww
发布于
2025年4月14日
许可协议