天天看點

vue3 基礎-non-props 特性

父子元件傳值, 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

耐心和恒心, 總會獲得回報的.