vue组件传值之props和$emit

2,340 阅读2分钟

vue组件传值之Props$emit

前言

上次我们谈了$refs$parent传值,发完之后我发现还有种传值方式$attrs$listeners,小Q可能一时间想不起来那么多,希望大家见谅,有错误的地方也欢迎大家指正😁

今天我们就来说说目前比较常用props$emit😎

正文

首先props是什么?怎么用?我们来看官方文档

image.png

有小伙伴说这个解释看不懂啊,简单来说就是组件间传值,我们再来看官方文档传值的方法

image.png

很显然,可以传数组和对象嘛,但是这里小Q要说一下,数组方式目前已经不推荐了,尽量少用

那这玩意到底怎么用呢,废话不多说上码

<template>
  <div class="father">
    <h2>父组件</h2>
    <!-- 01.基本使用 -->
    <son info="你好吗?" skill="不,我不好" food="吃西兰花可以平复心情哦"></son>
  </div>
</template>

<script>
// 导入子组件
import son from './components/01.son.vue'
export default {
// 注册子组件
  components: {
    son
  }
}
</script>

<style>
body {
  margin: 0;
}
.father {
  height: 100vh;
  background-color: skyblue;
  /* 去除 因为h2 造成的塌陷 */
  overflow: hidden;
}
</style>

<template>
  <div class="son">
    <h3>子组件</h3>
    <p>{{ info }}</p>
  </div>
</template>

<script>
export default {
  name: 'son',
  // 定义props 数组 基本用法
  props: ['info', 'skill', 'food']
}
</script>

<style>
.son {
  border: 3px solid hotpink;
  width: 300px;
  height: 300px;
  background-color: orange;
}
</style>

这种是简单的父组件传值给子组件父组件中的值要与props中的值要相对应,不然无法取到,那么对象用法怎么用呢?

对象的用法相比于数组的用法多了类型校验

<template>
  <div class="son">
    <h3>子组件</h3>
    <p>{{ info }}</p>
  </div>
</template>

<script>
export default {
  name: 'son',
  props: {
    info: {
      // 类型
      type: String,
      // 默认值
      default: '喜洋洋,美羊羊'
    },
    food: {
      type: String,
      // 必填项
      required: true,
      validator (value) {
        // console.log('value:', value)
        // 返回 true 成功 false 失败
        // return false
        // 必须传
        const res = ['鲱鱼罐头', '黑蒜', '榴莲', '逆风十里臭豆腐'].includes(
          value
        )
        // 存在 true 反之就是false
        return res
      }
    }
  }
}
</script>

<style>
.son {
  border: 3px solid hotpink;
  width: 300px;
  height: 300px;
  background-color: orange;
}
</style>

type是定义类型,常见的有(Number,String,Boolean,Array,Object)

required是否必填 validator是自定义验证函数

小Q提醒大家子组件中获取过来的值不建议去修改(虽然可以修改)因为子组件中的值是父组件流过来的,如果子组件修改了值,父组件中出现了数据变化,子组件中的值也会随之改变(单项数流)

$emit使用:

子组件:

  1. 子组件这次叫做emit-use

  2. 通过$emit('事件名'),触发事件

  3. 事件名可以随便写,有意义即可

<template>
  <div class="emit-container">
      <input @click="add" type="button" value="点击累加">
  </div>
</template>

<script>
  export default {
    name: 'emit-use',
    methods:{
        add(){
            // 触发add事件
            this.$emit('add')
        }
    }
  }
</script>

<style></style>

父组件:

  1. 注册并实现add事件

  2. 可以实现一个计数功能

<template>
  <div>
    <!-- emit基本使用 -->
    <h2>你点了:{{ num }} 次</h2>
    <emit-use @add="fatherAdd"></emit-use>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        num:0
      }
    },
    methods:{
      fatherAdd(){
        console.log('fatherAdd')
        this.num++
      }
    }
  }
</script>

有的时候,我们不仅仅要触发事件,还需要传递自定义的参数,只需要在emit方法的后面依次写上需要的参数即可

语法:emit('事件名',参数1,参数2....)

子组件:

  1. 子组件这次叫做emit-param

  2. 子组件中通过双击事件来触发emit

  3. 同时传递数据

<template>
  <div class="emit-container">
      <input @dblclick="add" type="button" value="双击加2">
  </div>
</template>

<script>
  export default {
    name: 'emit-param',
    methods:{
        add(){
          	// 触发add事件,同时传递参数
            this.$emit('add',2)
        }
    }
  }
</script>

<style></style>

父组件

  1. 注册事件,并定义参数

  2. 获取并使用参数

  3. 这里为了对比,上一步不传递数据的组件也一起保留作为对比

  4. 点击第一个组件,一次加1

  5. 双击第二个组件,一次加2

<template>
  <div>
    <!-- emit传递参数 -->
    <h2>你点了:{{ num }} 次</h2>
    <!-- 不传递参数 -->
    <emit-use @add="fatherAdd"></emit-use>
    <!-- 传递参数 -->
    <emit-param @add="fatherAdd"></emit-param>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        num: 0
      }
    },
    methods: {
      fatherAdd(num) {
        console.log('fatherAdd')
        console.log(`num:${num}`)
        // 如果有参数,获取并累加
        if(num){
          this.num+=num
        }else{
          // 如果没有参数,累加1
          this.num++
        }
      }
    }
  }
</script>

<style></style>

注意:

  1. 如果要传递多个参数,用逗号分隔,继续向后写

  2. 父组件注册事件时,也定义对应个参数即可

  3. 如果不想挨个传递,可以把多个数据放到一个对象中,也是可以的

END

这就是props$emit的使用了,多在测试代码中摸索,找到属于自己的理解方式,这样对这种传值的方法理解能更深一些。如果有什么问题可以直接私我,欢迎大家和我一块学习进步。

我是还在学习的前端小Q😘