vue3+typescript【5】

父子组件通信

父传子

父组件传递给子组件:通过props属性;

  • Props是你可以在组件上注册一些自定义的attribute;
  • 父组件给这些attribute赋值,子组件通过attribute的名称获取到对应的值

props两种常见用法:

  • 方式一:字符串数组,数组中的字符串就是attribute的名称;
props:{
    title:String
}

多个可能类型的写法:

props:{
    title:[String,Number]
}
  • 方式二:对象类型,对象类型我们可以在指定attribute名称的同时,指定它需要传递的类型、是否是必须的、默认值等等
props:{
    content:{
        type:String,
        required:true,
        default:"lalalla"
    }
}

对象类型的其他写法:

//带有默认值的对象(重要)
//对象或数组的默认值必须从一个工厂函数获取
propA:{
    type:Object,
    default(){
        return {message:'hello'}
    }
}
//自定义验证函数
propB:{
    validator(value){
        return ['success','warning','danger'].includes(value)
    }
}
//具有默认值的函数
//与对象或数组默认值不同,这是一个用作默认值的函数而不是一个工厂函数
propC:{
    type:Function,
    default(){
        return 'default Function'
    }
}

type类型

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

prop大小写命名 大小写不敏感,使用DOM模板时,驼峰命名法的prop名需要使用等价的短横线分隔命名

非prop的attribute
传递给一个组件某个属性,但是该属性并没有定义对应的props或者emits时,就称之为 非Prop的Attribute
常见包括classstyleid属性
Attribute继承

  • 当组件有单个根节点时,非Prop的Attribute将自动添加到根节点的Attribute中
  • 如果我们不希望组件的根元素继承attribute,可以在组件中设置 inheritAttrs: false:
    • 禁用attribute继承的常见情况是需要将attribute应用于根元素之外的其他元素;
    • 我们可以通过 $attrs来访问所有的 非props的attribute
    • 多个根节点的attribute如果没有显示的绑定,那么会报警告,我们必须手动的指定要绑定到哪一个属性上,如:class="$attrs.class"

子传父

子组件传递给父组件:通过$emit触发事件

子传父步骤

  • 首先,需要在子组件中定义好在某些情况下触发的事件名称;
emits:["add","sub"],
methods:{
    increment(){
        console.log("+1")
        this.$emit("add")
    },
    decrement(){
        console.log("-1")
        this.$emit("sub")
    }
}
  • 其次,在父组件中以v-on的方式传入要监听的事件名称,并且绑定到对应的方法中;
    <counter-operation @add="addOne" @sub="subOne"></counter-operation>
methods:{
    addOne(){
        this.counter++
    },
    subOne(){
        this.counter--
    }
}
  • 最后,在子组件中发生某个事件的时候,根据事件名称触发对应的事件

emits也可以写成数组或对象
对象写法的目的是为了进行参数的验证

  1. 传单个参数时:
emits:{
    addN:payload=>{
        console.log(payload)
    }
}
  1. 传多个参数时
emits:{
    addN(num,name,age)=>{
        console.log(num,name,age);
        if(num>10){
            return ture
        }
        return false
    }
}

此时的验证只会警告,但仍可以正常传递参数

父子组件案例

简单的页面切换

//父组件
<template>
  <div>
    <tab-control :titles="titles" @titleClick="titleClick"></tab-control>
    <h2>{{content[currentIndex]}}</h2>
  </div>
</template>

<script>
import tabControl from "./tabControl.vue";
export default {
  components: {
    tabControl,
  },
  data() {
    return {
      titles: ["衣服", "鞋子", "裤子"],
      content:["衣服页面","鞋子页面","裤子页面"],
      currentIndex:0
    }
  },
  methods:{
    titleClick(index){
        this.currentIndex=index
    }
  }
};
</script>

<style scoped>
</style>
//子组件
<template>
    <div class="tab-control">
<div v-for="(title,index) in titles" 
    :key="title"
    :class="{active:currentIndex===index}"
    @click="itemClick(index)"
    class="tab-control-item"><span>{{title}}</span></div>
    </div>
</template>

<script>
    export default {
        emits:["titleClick"],
        data(){
            return{
                currentIndex:0
            }
        },
        props:{
            titles:{
                type:Array,
                default(){
                    return []
                }
            }
        },
        methods:{
            itemClick(index){
                this.currentIndex=index;
                this.$emit("titleClick",index)
            }
        }
    }
</script>

<style scoped>
.tab-control{
    display: flex;
}
.tab-control-item{
    flex: 1;
    text-align: center;
    font-weight: 700;
}
.tab-control-item.active{
    color:red
}

.tab-control-item.active span{
    border-bottom: 3px red solid;
}
</style>

非父子组件通信

Provide/Inject

兄弟之间不能用,是子孙之间使用的

  • 无论层级结构有多深,父组件都可以作为其所有子组件的依赖提供者;
  • 父组件有一个 provide 选项来提供数据;
  • 子组件有一个 inject 选项来开始使用这些数据
    可以将依赖注入看作是long range props
  • 父组件不需要知道哪些子组件使用它 provide 的 property
  • 子组件不需要知道 inject 的 property 来自哪里

provide

provide:{
    name:"why",
    age:18
}

inject

inject:["name","age"]

处理响应式数据

provide(){
    return{
        length:computed(()=>this.names.length)
    }
}

computed返回的是一个ref对象,需要取出其中的value来使用{{length.value}}

全局事件总线mitt库

Vue3从实例中移除了 o n 、 on、 onoff 和 $once 方法
npm install mitt

封装一个工具eventbus.js

import mitt from 'mitt'

const emitter = mitt();

export default emitter;

监听事件

created(){
    emitter.on("why",(info)={
        console.log("why event:",info);
    })

    <!-- 没传递kobe,不会触发 -->
    emitter.on("kobe",(info)={
        console.log("kobe event:",info);
    })

    <!-- 监听所有数据 -->
    emitter.on("*",(type,e)={
        console.log("* event:",type,e);
    })
}

触发事件

methods:{
    methodsFunction(){
        emitter.emit("why",{name:"why",age:18})
    }
}

取消数据监听

  1. 取消所有监听
    emitter.all.clear()

  2. 取消指定监听

function onFoo(){}       //定义一个函数
emitter.on('foo',onFoo)  //监听
emitter.off('foo',onFoo) //取消监听
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值