本篇探讨当父组件通过属性给子组件传数据时, 子组件如果不通过 props 属性进行接收, 那数据会挂载到哪里, 以及子组件如何能使用这些数据.
正常的父子组件传值
<!DOCTYPE html>
<html lang="en">
<head>
<title>正常-父子组件传值</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
// 1. 父组件通过 msg 属性给子组件传递一个 "hello, youge" 的数据
template: `
<div>
<Son msg="hello, youge" />
</div>
`
})
app.component('Son', {
// 2. 正常逻辑就是子组件通过 props 进行接收
props: ['msg'],
template: `<div>son</div>`
})
const vm = app.mount('#root')
</script>
</body>
</html>
现在, 如果子组件 Son 不写 props 属性的话, 则这个数据会自动挂载的子组件 Son 的最外层 dom 上如下:
<div msg="hello, youge">son</div>
当然, 子组件也可选择就不接收父组件数据, 则在子组件中设置 inheritAttrs: false 即可.
app.component('Son', {
inheritAttrs: false,
template: `<div>son</div>`
})
non-props 应用
当父组件要给子组件传递一个样式的时候, 就可直接自动应用到子组件最外层 dom 啦.
<!DOCTYPE html>
<html lang="en">
<head>
<title>nop-props 传样式过去</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
template: `
<div>
<Son style="color: orange;" />
</div>
`
})
app.component('Son', {
template: `<div>son</div>`
})
const vm = app.mount('#root')
</script>
</body>
</html>
则可看到父组件传递的样式在子组件上就直接生效了, 这还是有使用场景的. 但当我们的子组件最外层有多个 dom 节点时, 则可通过 v-bind="$attrs" 的来指定作用于谁.
app.component('Son', {
template: `
<div>son</div>
<div v-bind="$attrs">son</div>
<div>son</div>
`
})
这就表明样式的这个 nop-props 就作用于上图第二个节点了.
$attrs 就是用来存储父子局传过来的所有属性, 则就可以按需使用了.
<!DOCTYPE html>
<html lang="en">
<head>
<title>传多值 $attrs</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
template: `
<div>
<Son style="color: orange;" />
</div>
`
})
app.component('Son', {
template: `
<div>son</div>
<div v-bind="$attrs">son</div>
<div>son</div>
`
})
const vm = app.mount('#root')
</script>
</body>
</html>
当然更多的应用配置是, 我能自己去通过 $attrs 对父组件传过来的多数据进行自己随意应用.
<!DOCTYPE html>
<html lang="en">
<head>
<title>传多值 $attrs</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
template: `
<div>
<Son msg="hello" msg1="youge" />
</div>
`
})
app.component('Son', {
template: `
<div :msg="$attrs.msg">{{$attrs.msg}}</div>
<div>啥都不接收</div>
<div :cj="$attrs.msg1">{{$attrs.msg1}}</div>
`
})
const vm = app.mount('#root')
</script>
</body>
</html>
对于这些 nop-props 的属性数据, 则子组件可通过 v-bind="$ attrs.xxx" 进行应用即可. 同时它也是可以直接在其他地方用的, 比如生命周期函数:
<script>
const app = Vue.createApp({
template: `
<div>
<Son msg="hello" msg1="youge" />
</div>
`
})
app.component('Son', {
mounted () {
console.log(this.$attrs.msg)
},
template: '<div>son</div>'
})
</script>
小结
- 父子组件传值常规操作是父组件通过属性传数据给子组件, 子组件通过 props 进行接收
- non-props 即当子组件不通过 props 接收父组件传的数据时, 其都会存在 $attrs 这个属性中
- 子组件可通过 v-bind=$attrs.xxx 的方式对 non-props 的数据进行应用
- 在很多地方如生命周期函数都是可以直接访问 $attrs 的数据, 即 this.s.attrs.xxx