Vue3的组件通信方式

 m一、父组件传递给子组件使用Props

什么是Props呢?

  • Props是你可以在组件上注册一些自定义的attribute;

  • 父组件给这些attribute赋值,子组件通过attribute的名称获取到对应的值;

Props有两种常见的用法:

方式一:字符串数组,数组中的字符串就是attribute的名称;

方式二:对象类型,对象类型我们可以在指定attribute名称的同时,指定它需要传递的类型、是否是必须的、默认值等等;

我用下面的综合案例来讲解组件之间的传递方式(该案例用到了props的数组用法)

首先创建一个MusicItem子组件

<template>
  <div class="box">
    <img :src="coverImgUrl" width="70px">
    <p>{{name}}</p>
   <button @click="filter()">删除</button>
  </div>
</template>
<script>
export default {
  name: 'MusicItem',
  props:["coverImgUrl","name","id"],
  data(){
    return {
      
    }
  },
  methods:{
    filter(){
      this.$emit("filter");
    }
  }
}
</script>
<style scoped>
</style>

其次创建一个MusicList组件

<template>
  <div class="box" v-for="(it,index) in playlists">
    <MusicItem :coverImgUrl="it.coverImgUrl":name="it.name":id="it.id" @filter="filter(index)"/>
  </div>
</template>
<script>
import MusicItem from './MusicItem.vue';
export default {
  name: '',
  data(){
    return {
      playlists:"",
    }
  },
  methods:{
    filter(index){
     this.playlists.splice(index,1)
    }
  },
  components:{
    MusicItem
  },
  created() {
      fetch("http://39.103.151.139:8000/music/playlist")
        .then((data) => data.json())
        .then((res) => {
          this.playlists = res.playlists;
        });
    },
}
</script>
<style scoped>

</style>

最后在App.vue文件中引用上面两个组件

<template>
  <div class="box">
  </div>
</template>
<script>
import MusicItem from './components/MusicItem.vue';
import MusicList from './components/MusicList.vue';
export default {
  name: '',
  data(){
    return {
        
    }
  },
  methods:{
​
  },
  components:{
    MusicItem,
    MusicList
  }
}
</script>
<style scoped>
​
</style>
Props的对象用法

数组用法中我们只能说明传入的attribute的名称,并不能对其进行任何形式的限制,接下来我们来看一下对象的写法是如何让我们的props变得更加完善的。

当使用对象语法的时候,我们可以对传入的内容限制更多:

  • 比如指定传入的attribute的类型

  • 比如指定传入的attribute是否是必传的

  • 比如指定没有传入时,attribute的默认值

 props:{
     name:{
         type:String,
         required:true,
         default:'无名氏'
     },
      age:{
            type:Number,
            required:true,
         },
},
细节
  1. 那么type的类型都可以是哪些呢?                                                                                     String Number Boolean Array Object Date Function Symbol

  2. Prop 名字格式

    如果一个 prop 的名字很长,应使用 camelCase 形式,因为它们是合法的 JavaScript 标识符,可以直接在模板的表达式中使用,也可以避免在作为属性 key 名时必须加上引号。

export default {
  props: {
    personSex: String
  }
}
​

<p>性别:{{personSex}}</p>

虽然理论上你也可以在向子组件传递 props 时使用 camelCase 形式 (使用 DOM 模板时例外),但实际上为了和 HTML attribute 对齐,我们通常会将其写为 kebab-case 形式:

 <Person name="李四" age="22" person-sex="男"/>

对于组件名我们推荐使用 PascalCase,因为这提高了模板的可读性,能帮助我们区分 Vue 组件和原生 HTML 元素。然而对于传递 props 来说,使用 camelCase 并没有太多优势,因此我们推荐更贴近 HTML 的书写风格。

单向数据流

所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。

另外,每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,这意味着你不应该在子组件中去更改一个 prop。若你这么做了,Vue 会在控制台上向你抛出警告:

export default {
  props: ['foo'],
  created() {
    // ❌ 警告!prop 是只读的!
    this.foo = 'bar'
  }
}

导致你想要更改一个 prop 的需求通常来源于以下两种场景:

  • prop 被用于传入初始值;而子组件想在之后将其作为一个局部数据属性。在这种情况下,最好是新定义一个局部数据属性,从 props 上获取初始值即可:

  • 需要对传入的 prop 值做进一步的转换。在这种情况中,最好是基于该 prop 值定义一计算属性

  1. 对象类型的其他写法

    export default {
      props: {
        // 基础类型检查
        //(给出 `null` 和 `undefined` 值则会跳过任何类型检查)
        propA: Number,
        // 多种可能的类型
        propB: [String, Number],
        // 必传,且为 String 类型
        propC: {
          type: String,
          required: true
        },
        // Number 类型的默认值
        propD: {
          type: Number,
          default: 100
        },
        // 对象类型的默认值
        propE: {
          type: Object,
          // 对象或者数组应当用工厂函数返回。
          // 工厂函数会收到组件所接收的原始 props
          // 作为参数
          default(rawProps) {
            return { message: 'hello' }
          }
        },
        // 自定义类型校验函数
        propF: {
          validator(value) {
            // The value must match one of these strings
            return ['success', 'warning', 'danger'].includes(value)
          }
        },
        // 函数类型的默认值
        propG: {
          type: Function,
          // 不像对象或数组的默认,这不是一个工厂函数。这会是一个用来作为默认值的函数
          default() {
            return 'Default function'
          }
        }
      }
    }
    ​
二、 子组件传递给父组件数据使用$emit

什么情况下子组件需要传递内容到父组件呢?

  • 当子组件有一些事件发生的时候,比如在组件中发生了点击,父组件需要切换内容

  • 子组件有一些内容想要传递给父组件的时候

我们如何完成上面的操作呢?

  1. 首先,我们需要在子组件中定义好在某些情况下触发的事件名称; 自定义事件

  2. 其次,在父组件中以v-on的方式传入要监听的事件名称,并且绑定到对应的方法中

  3. 最后,在子组件中发生某个事件的时候,根据事件名称触发对应的事件

该用法请参考上面代码里面的$emit用法

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值