天天看点

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 ( ) 中对数据进行一个拷贝副本, 然后对副本依然可以为所欲为