VUE3 TS 父子组件通信

一、父传子,传递简单字符串

父组件

传递 简单的字符串 title 给子组件

<template>
  <div class="layout">
    <Menu title="title传给子组件Menu的数据" />
    <div class="layout-right">
      <Header />
      <Content />
    </div>
  </div>
</template>

子组件

<template>
  <div class="menu">
    菜单区
    <p>{{ title }}</p>
  </div>
</template>

<script setup lang="ts">
type Props = {
  title: string;
};
// 1.子组件用 defineProps() 接收父组件传来的数据  此处为ts语法糖写法  正常写法defineProps({title:''}),去上面用 type 定义类型
// 2.定义了 Props 把 Props 塞到下方 <>
defineProps<Props>();
// 3.此时可以去 template 里面展示接收的数据
</script>

设置默认值

父组件的 title如果没有设置值 如  title=" "  则 title 的值就是这里设置的默认值

复杂的数据类型需要 一个函数 return 的形式 如下 data

type Props = {
  title?: string;
  data?:number[]
};
withDefaults(defineProps<Props>(),{
  title:'这样可以设置默认值',
  // 复杂的数据类型需要 一个函数 return 的形式 如下
  data:()=>[6,6,6,6]
})

二、父传子,传递数组或对象

父组件

1.父组件 给子组件传递 数据为 listToSon 的数组

2.用 dataToSon 事件绑定,给子组件传递 listToSon

<!-- v-bind 绑定事件 dataToSon 传递数据 listToSon 给子组件-->
      <Header :dataToSon="listToSon" />

3.父组件 定义 listToSon 的数据

<script setup lang="ts">
import Header from "./Header/index.vue";

import { reactive } from "vue";

// 父组件定义一个传递给 子组件 的数组 listToSon 去template的子组件上面命名 dataToSon 绑定 v-bind 给子组件,选择的传递的数据 就是 listToSon、
const listToSon = reactive<number[]>([1, 2, 3]);

子组件

4.定义 该 子组件的 接受 defineProps() 为 HeaderProps ,并在defineProps()里注册HeaderProps

5.子组件用父组件绑定的 dataToSon 事件接收 父组件传递过来的 listToSon 的数组。

6.此时已经收到了数据,可以去页面展示

<template>
  <div class="header">
    头部区
    <div>{{ dataToSon }}</div>
  </div>
</template>

<script setup lang="ts">
// 1.子组件接收 父组件绑定的事件 :dataToSon="listToSon"
// 3.可以去 template 里面展示,此时已经收到了父组件 传递过来的数组listToSon
type HeaderProps = { 
  dataToSon: number[];
};
// 2. type 声明的HeaderProps 用 defineProps注册
defineProps<HeaderProps>(); 
</script>

三、子传父

子组件

1.子组件通过定义事件 给 父组件 传递数据 此处事件名:dataToFather

<!--  1.子组件通过定义事件 给 父组件 传递数据 -->
    <button @click="dataToFather">子传父</button>
<button @click="dataToFather2">子传父2</button>

2.注册刚才的事件 就是子传父定义的事件 dataToFather

3.用 defineEmits 其返回值 为一个函数,这里定义函数名为 emitdefineEmits 接收一个数组(因为可以定义多个自定义事件) ,数组里为自定义事件名称,此处自定义事件名称:clickToFather 

 4.使用 返回命名为 emit 的函数,在自定义事件后面跟一个参数,即为要传递给父组件的数据 listTofather  和 listTofather2(后面不在多余说明传递的其他的数据,只强调 listTofather ,此外还加入了一个没有 const 定义的布尔值 false )

5.定义要传递的数据 listTofather

代码如下

<script setup lang="ts">
import { reactive } from "vue";
// 5.定义要传递的数据 listTofather
const listTofather = reactive<number[]>([4, 5, 6]);
const listTofather2 = reactive<number[]>([8, 8, 6]);
const list2 = reactive<object>({ name: "content", num: 1 });
// 3.用 defineEmits 其返回值 为一个函数,这里定义函数名为 emit。defineEmits 接收一个数组 ,数组里为自定义事件名称
const emit = defineEmits(["clickToFather", "clickToFather2"]);
// 2.注册 子传父 定义的事件 dataToFather
const dataToFather = () => {
  // 4.使用 defineEmits 返回命名为 emit 的函数,在自定义事件后面跟一个参数,即为传递的数据 listTofather 和 listTofather2
  emit("clickToFather", listTofather, listTofather2, false);
};
const dataToFather2 = () => {
  emit("clickToFather2", list2);
};
</script>

父组件

6. 在子组件中用 defineEmits 的接收一个数组,里面包含了自定义事件。此处子组件数组里自定义事件名称为 clickToFather,父组件这里则用 @clickToFather 接收子组件传递过来的数据,并自定义一个函数 getSonData()

<div class="layout">
    <div class="layout-right">
      <!-- 6. 用 defineEmits 其返回值 为一个函数,子组件函数名为 emit。defineEmits 接收一个数组 -->
      <!-- 6. 数组里为自定义事件名称 clickToFather,组件这里则 @clickToFather接收数据,并自定义函数名称 getSonData -->
      <Content @clickToFather="getSonData" @clickToFather2="getSonData2" />
    </div>
</div>

7. 子组件的 clickToFather 事件 父组件接收的函数为 getSonData=()=>{} 其接收的参数 就是子组件定义的数据 listTofather

<script setup lang="ts">
// 7. clickToFather 事件 父组件接收的函数 getSonData=()=>{} 其接收的参数 就是子组件定义的数据 const getSonData = (
  listTofather: number[],
  listTofather2: number[],
  flag: boolean
) => {
  console.log(
    listTofather,
    listTofather2,
    flag,
    "子组件传过来的数据listTofather 和 listTofather2 和一个布尔值 "
  );
};
const getSonData2 = (list2: object) => {
  console.log(list2, "第二个button传过来的数据");
};
</script>

四、父组件 拿到 子组件 实例

父组件

1.拿到 子组件 content 的实例 用 ref 定义一个 contents

(此处只展示获取子组件实例部分的代码,所以省略了前面的代码部分)

<!-- ***  1.1.拿到 子组件 content 的实例 用ref  -->
      <Content ref="contents" />

2.定义上面的 contents ,ref 给个空值就行,然后去下面 借用 getSonData 打印 contents.value

// *** 1.2.定义上面的 contents ,ref 给个空值就行,然后去下面 借用 getSonData 打印 contents.value
const contents = ref(null);

3.  借用 getSonData 打印 contents.value

const getSonData = (
  // *** 1.3.  借用 getSonData 打印 contents.value
  console.log(contents.value, "子组件实例");
};

4.点击按钮触发事件后,发现子组件定义的数据全都么得了。因为这里子组件默认,这些数据不对外暴漏,我们需要用到 defineExpose({}),将需要暴漏的数据,暴漏出去

 子组件

5.子组件对外暴漏 需要传出的数据 ( 此处以 list2 对象为例)

defineExpose({
  list2
})

6.然后观察控制台,发现暴漏的 list2 已经传给 父组件了

 优点:相比 Vue2 这样的好处就在于数据更加安全,父组件不能随意修改子组件的数据

  • 15
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值