vue3 + typescript 实现组件间通信

vue 组件间通信分为 :

父组件向子组件通信
子组件向父组件通信
兄弟间组件通信

父组件向子组件通信

父组件向子组件通信的关键是defineProps函数
父组件向子组件传递一个字符串,子组件接收这个字符串并展示出来
father.vue

<script setup lang="ts">
import Son from './Son.vue'
</script>

<template>
  <Son msg="这信息来自父组件" /></Son>
</template>

son.vue

<script setup lang="ts">
    defineProps<{msg:string}>()
</script>

<template>
    <div class="son">
        子组件内容:
        <p></p>
        <div>{{msg}}</div>
    </div>
</template>

这里要特别注意的是 defineProps 在 typescript 的专用写法:defineProps<>() ,而且 defineProps 是在 setup 语法糖才能使用, defineProps无须引入。

<template>
  <h1>{{ msg }}</h1>
  <div @click="clickThis">1111</div>
</template>

<script setup lang="ts">
  defineProps<{ // 采用ts专有声明,无默认值
    msg: string,
    num?: number
  }>()
     // 采用ts专有声明,有默认值
    interface Props {
        msg?: string
        labels?: string[]
    }
    const props = withDefaults(defineProps<Props>(), {
        msg: 'hello',
        labels: () => ['one', 'two']
    })
    
  defineProps({ // 非ts专有声明
    msg: String,
    num: {
      type:Number,
      default: ''
    }
  })
</script>

<style scoped lang="less">
</style>

defineEmits

子组件向父组件事件传递

<template>
  <div @click="clickThis">点我</div>
</template>

<script setup lang="ts">
    /*ts专有*/
  const emit= defineEmits<{
    (e: 'click', num: number): void
  }>()
    /*非ts专有*/
  const emit= defineEmits(['click'])
  
  const clickThis = () => {
    emit('click',2)
  }
</script>

<style scoped lang="less">
</style>


子组件向父组件通信

子组件向父组件通信的关键是defineEmits函数
Son.vue 通过 defineEmits 定义事件传递方法 toFather

<script setup lang="ts">
    const emit = defineEmits<{(e:'toFather',msg:string):void}>()
    const click = () =>{
        emit('toFather','来自子组件信息')
    }
</script>

<template>
    <div class="son">
        子组件内容:
        <p></p>
        <button @click="click">
        点击传信息给父组件
        </button>
    </div>
</template>

defineExpose的用法

在vue2.x中我们可以通过this. r e f s . x x x 或 者 t h i s . refs.xxx或者 this. refs.xxxthis.parent 链获取到的组件的公开实例,

但是使用

为了在

假如我们要在子组件里暴露一个handleClick2方法,我们要先定义这个方法

const handleClick2 = () => {
  a.value = 3
  obj.name = '我叫改变'
};

然后整个

// defineExpose 统一暴露
defineExpose({
    a,
    obj,
    handleClick2
})

因为如果defineExpose代码行在上,handleClick2申明在下,会报错

//定义对象属性
 interface defineObj {
      readonly name: string; //只读属性
      age: number; //必填
      sex?: string; //选填
      call(): string; //有返回值,类型为string
      action(): void; //必填、无返回值
      [propName: string]: any; //任意属性
      //需要注意的是,一旦定义了任意属性,那么确定属性和可选属性都必须是它的子属性
 }
 const obj = reactive<defineObj>({
      name: "abc", //只读,不可修改
      age: 18, //sex:'男',
      a: "a",
      b: 9,
      c: true,
      call: () => "call",
      action: function () {
        console.log("void接口");
      },
      o: { id: 1 },
 });

点击跳转

defineExpose

暴露自己的属性供父组件使用

const count = ref(0);
defineExpose({
  count,
});<HelloWorld  ref="child" />
const child = ref(null);
onMounted(() => {
  console.log("child", child.value.count);
});

组件实战

父组件

<template>
  <HelloWorld :msg="msg"  @change="change"/>
  <p v-if="state.msg1!==''">   {{state.msg1}}</p>
</template>

<script  lang="ts">
import { defineComponent,ref,reactive } from 'vue';
import HelloWorld from './components/HelloWorld.vue';

export default defineComponent({
  name: 'App',
  components: {
    HelloWorld
  },
  setup(){
     let msg=ref("天下无敌")
     let state=reactive({
       msg1:""
     });
     let change=(val:string)=>{
       console.log("子组件传参过来了",val)
       state.msg1=val
       console.log(state.msg1)
     }
    return{
       msg,
       change,
       state
    }
  }
});
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

子组件

<template>
  <div class="hello" @click="change">
    {{msg}}
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  name: 'HelloWorld',
  props: {
    msg: String,
  },
  setup(props,context){
     let change=()=>{
       console.log("数据正在改变")
       context.emit('change','hellowoolad')
     }
     return{
       change
     }
  }
});
</script>

<style scoped>
</style>

ref<InstanceType<typeof 组件>>()
组件之间的通信$refs

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值