• Vue2-父子组件传值


    在日常开发中,我们经常会在一个组件中嵌套另外一个组件,那么如果我们父组件要向子组件传值该怎么办?子组件向父组件通信又该怎么办?本文将详细举例说明这些问题。

    父向子通信

    问题描述

    现在我们有个需求,我们要分别显示父和子的信息,我们当然可以在一个组件中直接显示全部信息,但是万一以后又来一个需求:我们要在母和子的信息,那其实这里就存在冗余了,所以我们把子组件单独封装成一个新的组件。那么这里就会出现一个问题,子组件的信息该如何从父组件传过去呢?

    解决方案

    使用vue提供的prop属性,下面边看代码边分析:
    父组件定义

    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    子组件定义

    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    使用:attribute属性向子组件传入值

    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    子组件通过props属性接收父组件传过来的值,这里的名字要和父组件传的值对应

    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    测试
    在这里插入图片描述

    扩展

    上述的例子解决了父子组件传值的基本问题,当然prop的用法还有很多,我们可以在vue2官网上看到

    Prop的大小写

    camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名

    Vue.component('blog-post', {
      // 在 JavaScript 中是 camelCase 的
      props: ['postTitle'],
      template: '

    {{ postTitle }}

    ' })
    • 1
    • 2
    • 3
    • 4
    • 5
    
    
    
    • 1
    • 2

    Prop 类型

    我们之前使用以字符串数组形式列出的 prop

     props: ["sonInfo"]
    
    • 1

    我们也可以给每一个prop指定对应的值

    props: {
      title: String,//字符串
      likes: Number,//数字
      isPublished: Boolean,//布尔
      commentIds: Array,//数组
      author: Object,//对象
      callback: Function,//函数
      contactsPromise: Promise //异步延迟对象
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    传递静态或动态 Prop

    之前我们传递的是动态的Prop,可以动态赋值

     
    
    • 1

    我们也可以传递静态的

    
    
    • 1
      props: ["sonInfo", "sex"]
    
    • 1

    单向数据流

    所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
    额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

    官方这段话表明了,我们对于父组件传过来的值最不要直接修改,官方例举了两个常用的变更案例
    1.这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用

    props: ['initialCounter'],
    data: function () {
      return {
        counter: this.initialCounter
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.这个 prop 以一种原始的值传入且需要进行转换

    props: ['size'],
    computed: {
      normalizedSize: function () {
        return this.size.trim().toLowerCase()
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    类型校验

    之前我们使用字符串数组形式列出的 prop,父组件不知道子组件prop值的类型,可能传值的时候传错,所以我们可以给值指定类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你

    Vue.component('my-component', {
      props: {
        // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
        propA: Number,
        // 多个可能的类型
        propB: [String, Number],
        // 必填的字符串
        propC: {
          type: String,
          required: true
        },
        // 带有默认值的数字
        propD: {
          type: Number,
          default: 100
        },
        // 带有默认值的对象
        propE: {
          type: Object,
          // 对象或数组默认值必须从一个工厂函数获取
          default: function () {
            return { message: 'hello' }
          }
        },
        // 自定义验证函数
        propF: {
          validator: function (value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].includes(value)
          }
        }
      }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告

    子向父通信

    问题描述

    既然父可以向子传值,那么子是否可以通信父呢?当然可以,这时候我们要借助vue的 e m i t 和 emit和 emiton,下面我们看代码:

    解决方案

    子组件

    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    父组件

    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    测试
    点击按钮,控制台输出sayHi tom

    分析

    这里首先介绍一下vue提供的两个重要函数emit和on

    on

    监听当前实例上的自定义事件。事件可以由 $emit 触发。回调函数会接收所有传入事件触发函数的额外参数。
    上述例子的 @sayHi="sayHi"就是在监听sayHi事件,这里采用了简写形式,完整形式是v-on:sayHi=“sayHi”,我们平时用的比较多的就是监听点击事件,而这里我们就是监听了我们自定义的事件

    emit

    触发当前实例上的事件。附加参数都会传给监听器回调。
    当我们监听了自定义事件,我们就可以在子组件中触发事件,this.$emit(‘sayHi’,“tom”),这样就会调用监听的回调函数,并且将附加参数tom传入回调函数

    非父子通信

    除了上述的父子组件通信,我们最后还可以在非父子组件之间传值,某些场景下会用到。下面看代码:
    事件总线

    import Vue from "vue";
    export default new Vue;
    
    • 1
    • 2

    组件B

    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    组件A

    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    测试
    组件B的值由oldVal->newVal

    分析

    这里引入了事件总线(event bus)的概念,事件总线:事件发送者将事件消息发送到一个事件总线上,事件订阅者向事件总线订阅和接收事件,然后再处理接收到的事件
    而我们这里的事件总线的载体就是一个Vue的实例对象,因为在emit和on都是Vue的一个实例方法。
    当然我们还可以使用$attrs / listeners来实现类似效果,这里就不多做介绍了,有兴趣的读者可以自行了解
    但是如果学过Vuex的话,利用Vuex来传值会很方便,Vuex之后会慢慢讲,不急。学习是个漫长的过程,慢慢来

    由于作者能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!

  • 相关阅读:
    JDBC测试
    verilog实现AM调制及仿真验证
    【C#】C# 开发环境配置(Rider 一个.NET 跨平台集成开发环境)
    react 实现chatGPT的打印机效果 兼容富文本,附git地址
    模板、外观、观察者、建造者
    [创业-43]:公司的组织架构--所有者与决策机构(股东)
    API安全实战
    从看ahooks源码说起:源码准备阶段
    (02)Cartographer源码无死角解析-(10) 配置文件加载
    Mybatis的学习(一)只Mybatis的介绍和使用
  • 原文地址:https://blog.csdn.net/h13245/article/details/126822453