我经常看到 CompositionAPI 中使用 props 的模式, 即使用 toRefs 来制作 props 的所有条目
ref
。
我对此感到有点困惑。
例如,来自 Vue 3 官方指南:
export default {
props: {
user: {
type: String,
required: true
}
},
setup(props) {
const { user } = toRefs(props)
//... use user's value
}
}
我有 2 个场景的 2 个问题:
当 props.user 已经反应时
如果它在任何祖先中发生改变,它的值也会改变,那么为什么我们需要使用
toRefs
呢?不是已经反应了吗?
如果它不是响应式的,它只是一个原始字符串值
使其具有反应性是否意味着我们要改变它的值?
我认为使一个对象成为响应式也意味着它的价值值得改变。
但所有指南和 linter 都警告我们最好不要更改 props 值。(因为不写入计算值或其他内容)
如果我可以直接在组件中更改 props 值,我就不再需要每次都向父组件发出更改。 这很方便,但我不知道什么时候在我们确定它变为反应性后更改 props 值是一个好主意?
由于 props 不应该被改变,这对于文档中解释的特定情况很有用;从 prop 计算出的 ref 需要作为参数传递:
const { user } = toRefs(props)
// or
// const user = computed(() => props.user)
someFunction(user);
函数使用组合 API 或由于其工作方式而只需要通过引用而不是通过值传递参数,例如:
function someFunction(val) {
setTimeout(() => {
console.log('Up-to-date value:', unref(val));
}, 1000);
}
道具不应被分配
toRef
(有一些有限的例外:)
(均来自 vuejs.org,请参阅下面的链接)
在 VueJS toRef 文档中明确指出:
当 toRef 与组件 props 一起使用时,有关改变 props 的通常限制仍然适用。 尝试为 ref 分配新值相当于尝试直接修改 prop,这是不允许的。在这种情况下,您可能需要考虑使用带有 get 和 set 的计算来代替。有关更多信息,请参阅将 v-model 与组件一起使用的指南。
所以,回答你的问题:
只有父级应该能够修改提供给子级 props 的变量。道具只是孩子的吸气剂,仅此而已。如果你让它在孩子身上发生反应,你可能会在父母不知情的情况下对父母造成副作用。 这就是为什么我们明确使用事件发射来让父级清楚发生了什么以及何时
但不要将“改变 prop”与“改变 prop 的对象属性”混淆,请参阅 https://github.com/orgs/vuejs/discussions/9256?sort=old#discussioncomment-9606035 - 整个讨论很值得一读