目录
Props声明
defineProps()
在<script setup>的单文件组件中使用defineProps()声明
<script setup>
const props = defineProps(['test'])
console.log(props.test)
</script>
//对象形式
defineProps({
test: String,
test2: Number
})
props选项
没有使用
script setup>的单文件组件时,使用props选项声明
export default {
props: ['test'],
setup(props) {
// setup() 接收 props 作为第一个参数
console.log(props.test)
}
}
// 对象形式
export default {
props: {
test: String,
test2: Number
}
}
响应式Props解构
Vue 的响应系统基于属性访问跟踪状态的使用情况。例如,在计算属性或侦听器中访问
props.foo时,foo属性将被跟踪为依赖项。
默认语法声明props默认值
const { foo = 'hello' } = defineProps<{ foo?: string }>()
将解构的 props 传递到函数中
const { test} = defineProps(['test'])
//侦听解构的prop
watch(() => foo, /* ... */)
Props的传递
格式
推荐使用kebab-case形式,更贴近HTML的书写格式,任何类型的值都可以作为props的值传递(Number,Boolean,Array,Object,String...)
<MyComponent test-message="hello" />
静态props
<MyComponent test-message="hello" />
动态props
<MyComponent :test-message="test" />
let test = ref('hello word')
一个对象绑定多个prop
将一个对象的所有属性都当作 props 传入,你可可以使用没有参数的v-bind,即只使用
v-bind而非:prop-name
const post = {
id: 1,
title: 'My Journey with Vue'
}
<BlogPost v-bind="post" />
等价于
<BlogPost :id="post.id" :title="post.title" />
使用
单项数据流
- 禁止直接修改 Props
- 正确做法:通过
emit事件让父组件修改
所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,所以不应该在子组件中去更改一个 prop
动态prop
<ChildComponent :[dynamicPropName]="value" />
修改prop的场景处理
prop用于初始值
prop 被用于传入初始值;而子组件想在之后将其作为一个局部数据属性
const props = defineProps(['test'])
// 将 props.test作为初始值
// 像下面这样做就使 prop 和后续更新无关了
const test1= ref(props.test)
prop进一步处理
需要对传入的 prop 值做进一步的转换。在这种情况中,最好是基于该 prop 值定义一个计算属性
const props = defineProps(['test'])
// 该 prop 变更时计算属性也会自动更新
const test1= computed(() => props.test.trim().toLowerCase())
面试重点
1. 为什么不要直接修改 Props?
- 破坏单向数据流,导致组件状态难以追踪
- 父组件更新时,子组件的本地修改会被覆盖
2. 如何传递复杂对象?
// 传递整个对象
<UserProfile :user="userData" />
// 解构传递(保持响应性需要 toRefs)
<UserProfile v-bind="userData" />
3. Props 的响应性原理
- Vue3 使用 Proxy 实现响应式
- 如果传递非响应式数据,子组件不会自动更新
// 错误示例:直接传递字面量对象
<UserProfile :user="{ id: 1, name: 'John' }" />
// 正确做法:使用 reactive/ref
const user = reactive({ id: 1, name: 'John' })
4. Props 和 Emits 的关系
- Props 向下传递数据
- Emits 向上传递事件
- 组合使用实现组件通信