父子元件傳值, non-props 屬性
本篇探讨當父元件通過屬性給子元件傳資料時, 子元件如果不通過 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
耐心和恒心, 總會獲得回報的.