vue3组件通信之slot

插槽:默认插槽、具名插槽、作用域插槽可以实现父子组件通信.

默认插槽

在子组件内部的模板中书写slot全局组件标签

<template>
  <div>
    <slot></slot>
  </div>
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>

在父组件内部提供结构:Todo即为子组件,在父组件内部使用的时候,在双标签内部书写结构传递给子组件

<Todo>
  <h1>我是默认插槽填充的结构</h1>
</Todo>

注意开发项目的时候默认插槽一般只有一个
缺点就是不能规定父组件填充内容所指向的插槽, 父组件内填充的所有内容, 会填充到每个子组件内的插槽中

具名插槽

顾名思义,此插槽带有名字在组件内部留多个指定名字的插槽。

下面是一个子组件内部,模板中留两个插槽

<template>
  <div>
    <h1>todo</h1>
    <slot name="a"></slot>
    <slot name="b"></slot>
  </div>
</template>
<script setup lang="ts">
</script>

<style scoped>
</style>

父组件内部向指定的具名插槽传递结构。需要注意v-slot:可以替换为#

<template>
  <div>
    <h1>slot</h1>
    <Todo>
      <template v-slot:a>  //可以用#a替换
        <div>填入组件A部分的结构</div>
      </template>
      <template v-slot:b>//可以用#b替换
        <div>填入组件B部分的结构</div>
      </template>
    </Todo>
  </div>
</template>

<script setup lang="ts">
import Todo from "./Todo.vue";
</script>
<style scoped>
</style>

Vue官方文档: 没有被包裹在带有 v-slot: 的 < template> 中的内容都会被视为默认插槽内容.

具名插槽扩展-动态插槽名

//随便定义一个方法randomName, 使用这个方法的返回值;
<a v-bind:[randomName]="user"> ... </a>

作用域插槽

作用域插槽:可以理解为,子组件数据由父组件提供,但是子组件内部决定不了自身结构与外观(样式)

子组件Todo代码如下:

<template>
  <div>
    <h1>todo</h1>
    <ul>
     <!--组件内部遍历数组-->
      <li v-for="(item,index) in todos" :key="item.id">
         <!--作用域插槽将数据回传给父组件-->
         <slot :$row="item" :$index="index"></slot>
      </li>
    </ul>
  </div>
</template>
<script setup lang="ts">
defineProps(['todos']);//接受父组件传递过来的数据
</script>
<style scoped>
</style>

父组件内部代码如下:

<template>
  <div>
    <h1>slot</h1>
    <Todo :todos="todos">
      <template v-slot="{$row,$index}">
         <!--父组件决定子组件的结构与外观-->
         <span :style="{color:$row.done?'green':'red'}">{{$row.title}}</span>
      </template>
    </Todo>
  </div>
</template>

<script setup lang="ts">
import Todo from "./Todo.vue";
import { ref } from "vue";
//父组件内部数据
let todos = ref([
  { id: 1, title: "吃饭", done: true },
  { id: 2, title: "睡觉", done: false },
  { id: 3, title: "打豆豆", done: true },
]);
</script>
<style scoped>
</style>
### Vue3 Setup 语法下的组件通信方式 #### props 和 emit `props` 是一种单向的数据流,用于父组件子组件传递数据。而在 `setup` 函数中可以通过参数来接收 `props` 对象。 ```javascript // 子组件 Child.vue 中使用 setup 接收 props <script> import { defineComponent } from &#39;vue&#39;; export default defineComponent({ props: { message: String, }, setup(props) { console.log(props.message); // 输出来自父级的消息 return {}; } }); </script> ``` 对于自定义事件,在 `setup` 下可以利用第二个参数中的 `emit` 来触发事件通知父组件[^1]。 ```javascript // 子组件内部调用 emit 发送消息到父组件 <button @click="() => emit(&#39;childEvent&#39;, &#39;some data&#39;)">Click me!</button> ``` #### provide / inject 通过 `provide` 和 `inject` 可以让祖先组件向下层多个后代组件提供依赖关系,这在大型应用里特别有用当存在多层级嵌套时[^3]。 ```javascript // 父组件 Parent.vue 提供属性 <template> <Child /> </template> <script> import { provide, ref } from &#39;vue&#39;; export default { name: "Parent", setup() { const parentMessage = ref("Hello from parent"); provide(&#39;message&#39;, parentMessage); return {}; } }; </script> ``` ```javascript // 后代组件 GrandChild.vue 注入并使用该属性 <script> import { inject } from &#39;vue&#39;; export default { name: "GrandChild", setup() { const injectedMessage = inject(&#39;message&#39;); console.log(injectedMessage.value); // Hello from parent return {}; } } </script> ``` #### 使用 Pinia 进行状态管理 Pinia 是官方推荐的状态管理模式之一,它简化了 Vuex 的 API 设计使得更易于理解和上手。开发者可以在 store 文件夹下创建仓库文件,并导出相应的 getter/setter 方法以便于其他模块引入操作全局变量。 ```bash npm install pinia ``` ```javascript // 创建 Store 实例 import { createPinia, defineStore } from &#39;pinia&#39; const pinia = createPinia() // 定义 counter 店铺逻辑 export const useCounterStore = defineStore(&#39;counter&#39;, { state: () => ({ count: 0 }), actions: { increment() { this.count++ } } }) ``` ```javascript // 在 main.js 或者 app.ts 中挂载至根实例 app.use(pinia) // 组件内使用 import { useCounterStore } from &#39;./stores/counter&#39; function setup() { const counter = useCounterStore() function handleClickIncrementButton(){ counter.increment(); } return { handleIncrementButtonClick }; } ``` #### 插槽 (Slot) Vue3 支持三种类型的插槽:默认插槽、命名插槽以及作用域插槽。它们允许父组件子组件模板插入内容或者访问子组件内的局部变量。 ```html <!-- 父组件 --> <MyComponent> <!-- 默认插槽 --> <p>这里是默认的内容。</p> <!-- 命名插槽 --> <template v-slot:title> <h2>这是标题</h2> </template> <!-- 作用域插槽 --> <template v-slot:item="{ item }"> {{ item }} </template> </MyComponent> ``` ```html <!-- 子组件 MyComponent.vue --> <div class="my-component"> <header><slot name="title"/></header> <main><slot/></main> <footer><ul><li v-for="(item,index) in items"><slot :name="&#39;item&#39;" :item="item"></slot></li></ul></footer> </div> ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值