天天看點

vue3 基礎-單項資料流

父子元件傳值, 單項資料流

本篇還是了解關于元件間傳值, 核心點是了解子元件隻能接收父元件傳遞的資料而不能反向修改進而影響到其他元件造成的混亂局面.

傳多值的問題

當我們要傳遞資料很多的時候, 可以将資料都存在一個對象中, 直接将整個對象傳過去, 這樣就不要逐個去 v-bind 啦, 對于子元件則也通過處理對象的文法, 按需享用.

<!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({
      data () {
        return { 
          // 直接将資料封裝在一個對象中傳過去
          obj: {
            num: 666,
            firstName: 'you',
            lastName: 'ge',
            job: 'marketing'
          }
        }
      },
      template: `
      <div>
        <Son :content="obj" />
      </div>
      `
    })

    app.component('Son', {
      props: [ 'content'],
      template: `
      <div>{{content}}--{{typeof content}}</div>
      <div>{{content.firstName}}<div>
      <div>{{content.lastName}}<div>
      <div>{{content.job}}<div>
      `
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>      

這種操作在在實際中應用是非常高頻的.

{ "num": 666, "firstName": "you", "lastName": "ge", "job": "marketing" }--object
you
ge
marketing      

屬性大小寫傳參問題

當屬性名特别長的時候, 基于 html 文法的渲染規則限定, 其屬性是不能識别大小寫, 即駝峰命名是無效的, 如:

<div dataAbc="666"></div>      

這裡的 "dataAbc" 在 html 中是不能識别的, 它會将其轉為小寫即 "dataabc". 那這樣就和 js 有不相容了. 基于此, vue 在底層有做了一個關于 "-" 和駝峰的轉化, 具體的約定則是:

  • 父元件在傳資料的時候, 屬性名稱用 "abc-de" 這種短橫線命名
  • 子元件在接資料的時候, 用 "abcDe" 來進行擷取
<!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({
      data () {
        return { num: 666 }
        
      },
      // 1. 傳資料的時候, 屬性名稱用 "abc-de" 這種短橫線命名
      template: `
      <div>
        <Son :content-num="num" />
      </div>
      `
    })

    // 2. 子元件在接資料的時候,  用 "abcDe" 來進行擷取
    app.component('Son', {
      props: [ 'contentNum'],
      template: `<div>{{contentNum}}--{{typeof contentNum}}</div>`
    })
    
    const vm = app.mount('#root')

  </script>
</body>

</html>      

單項資料流

即子元件隻能使用父元件傳過來的資料, 但不能反向修改. 不然就有倫理問題啦.

<script>
    const app = Vue.createApp({
      data () {
        return { num: 666 }
        
      },
      template: `
      <div>
        <Son :content-num="num" />
      </div>
      `
    })

  // 子元件可以使用父元件傳遞的資料, 但不能修改
    app.component('Son', {
      props: ['contentNum'],
      template: `<div @click="contentNum += 1">{{contentNum}}</div>`
    })
    
    const vm = app.mount('#root')

  </script>      

這樣是絕對行不通滴, 是以才叫單項資料流嘛, 如果能改那就混亂了. 一個皇帝多個兒子, 其中一個把皇帝幹掉了, 這種鬥争是很可怕的. 是以 vue 在設計上就不允許這種牛逼的兒子存在, 忤逆聖命.

那怎麼能實作自己的定制需求呢, 其實很簡單, 通過 data ( ) 來拷貝一個副本就不行啦.

<!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({
      data () {
        return { num: 666 }
        
      },
      template: `
      <div>
        <Son :content-num="num" />
      </div>
      `
    })

    app.component('Son', {
      props: ['contentNum'],
      // 但是可以拷貝一個副本就可為所欲為了哎呀
      data () {
        return { myNum: this.contentNum }
      },
      template: `<div @click="myNum += 1">{{myNum}}</div>`
    })
    
    const vm = app.mount('#root')

  </script>
</body>

</html>      

小結

  • 當父元件傳多值給子元件時, 可将資料都封裝在一個對象中, 整個傳遞過去
  • 父元件在傳資料的時候, 屬性名稱用 "abc-de" 這種短橫線命名
  • 子元件在接資料的時候, 用 "abcDe" 來進行擷取
  • 單項資料流即子元件隻能對父元件傳來的資料"可讀" 不能改, 不然就耦合亂倫了
  • 子元件可通過 data ( ) 中對資料進行一個拷貝副本, 然後對副本依然可以為所欲為