当前位置: 首页 > news >正文

兰州网站设计厂家免费的行情软件网站下载入口

兰州网站设计厂家,免费的行情软件网站下载入口,js 网站开发,南平网站设计Vue3 组件通信方式全解(10种方案) 一、组件通信方式概览 通信方式适用场景数据流向复杂度Props/自定义事件父子组件简单通信父 ↔ 子⭐v-model 双向绑定父子表单组件父 ↔ 子⭐⭐Provide/Inject跨层级组件通信祖先 → 后代⭐⭐事件总线任意组件间通信任…

Vue3 组件通信方式全解(10种方案)


一、组件通信方式概览

通信方式适用场景数据流向复杂度
Props/自定义事件父子组件简单通信父 ↔ 子
v-model 双向绑定父子表单组件父 ↔ 子⭐⭐
Provide/Inject跨层级组件通信祖先 → 后代⭐⭐
事件总线任意组件间通信任意方向⭐⭐⭐
模板引用(ref)父操作子组件父 → 子
Pinia 状态管理复杂应用状态共享全局共享⭐⭐⭐
浏览器存储持久化数据共享全局共享⭐⭐⭐
attrs/attrs/listeners透传属性/事件父 → 深层子组件⭐⭐
作用域插槽子向父传递渲染内容子 → 父⭐⭐
路由参数页面间数据传递页面间

二、核心通信方案详解

1. Props / 自定义事件(父子通信)

<!-- 父组件 Parent.vue -->
<template><Child :message="parentMsg" @update="handleUpdate"/>
</template><script setup>
import { ref } from 'vue'
const parentMsg = ref('Hello from parent')const handleUpdate = (newMsg) => {parentMsg.value = newMsg
}
</script><!-- 子组件 Child.vue -->
<script setup>
defineProps(['message'])
const emit = defineEmits(['update'])const sendToParent = () => {emit('update', 'New message from child')
}
</script>

2. v-model 双向绑定(表单场景)

<!-- 父组件 -->
<CustomInput v-model="username" /><!-- 子组件 CustomInput.vue -->
<template><input :value="modelValue"@input="$emit('update:modelValue', $event.target.value)">
</template><script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>

3. Provide/Inject(跨层级)

// 祖先组件
import { provide, ref } from 'vue'
const theme = ref('dark')provide('theme', {theme,toggleTheme: () => {theme.value = theme.value === 'dark' ? 'light' : 'dark'}
})// 后代组件
import { inject } from 'vue'
const { theme, toggleTheme } = inject('theme')

4. 事件总线 mitt(任意组件)

// eventBus.js
import mitt from 'mitt'
export const emitter = mitt()// 组件A(发送)
emitter.emit('global-event', { data: 123 })// 组件B(接收)
emitter.on('global-event', (data) => {console.log(data)
})

5. Pinia 状态管理(复杂应用)

// stores/user.js
export const useUserStore = defineStore('user', {state: () => ({ name: 'Alice' }),actions: {updateName(newName) {this.name = newName}}
})// 组件使用
const userStore = useUserStore()
userStore.updateName('Bob')

6. 作用域插槽(子传父)

<!-- 子组件 -->
<template><slot :data="childData" />
</template><script setup>
const childData = { message: 'From child' }
</script><!-- 父组件 -->
<Child><template #default="{ data }">{{ data.message }}</template>
</Child>

三、进阶通信技巧

1. 多层属性透传

// 父组件
<GrandParent><Parent><Child /></Parent>
</GrandParent>// GrandParent.vue
<template><Parent v-bind="$attrs"><slot /></Parent>
</template>// 使用 inheritAttrs: false 关闭自动继承

2. 动态组件通信

<component :is="currentComponent" @custom-event="handleEvent"
/>

3. 自定义 Hook 封装

// hooks/useCounter.js
export function useCounter(initial = 0) {const count = ref(initial)const increment = () => count.value++return { count, increment }
}// 组件A
const { count: countA } = useCounter()// 组件B
const { count: countB } = useCounter(10)

4. 全局事件总线加强版

// eventBus.ts
type EventMap = {'user-login': { userId: string }'cart-update': CartItem[]
}export const emitter = mitt<EventMap>()// 安全使用
emitter.emit('user-login', { userId: '123' })

四、最佳实践指南

  1. 简单场景优先方案

    • 父子通信:Props + 自定义事件

    • 表单组件:v-model

    • 简单共享数据:Provide/Inject

  2. 复杂应用推荐方案

    • 全局状态管理:Pinia

    • 跨组件通信:事件总线

    • 持久化数据:localStorage + Pinia 插件

  3. 性能优化技巧

    • 避免在 Props 中传递大型对象

    • 使用 computed 属性优化渲染

    • 对频繁触发的事件进行防抖处理

    • 及时清理事件监听器

  4. TypeScript 增强

// Props 类型定义
defineProps<{title: stringdata: number[]
}>()// 事件类型定义
defineEmits<{(e: 'update', value: string): void(e: 'delete', id: number): void
}>()

五、常见问题解决方案

Q1: 如何避免 Props 层层传递?
✅ 使用 Provide/Inject 或 Pinia

Q2: 子组件如何修改父组件数据?
✅ 通过自定义事件通知父组件修改

Q3: 如何实现兄弟组件通信?
✅ 方案1:通过共同的父组件中转
✅ 方案2:使用事件总线或 Pinia

Q4: 如何保证响应式数据安全?
✅ 使用 readonly 限制修改权限:

provide('config', readonly(config))

Q5: 如何实现跨路由组件通信?
✅ 使用 Pinia 状态管理
✅ 通过路由参数传递
✅ 使用 localStorage 持久化存储


   

插槽详解


一、插槽核心概念

1. 插槽作用

允许父组件向子组件插入自定义内容,实现组件的高度可定制化

2. 组件通信对比
通信方式数据流向内容类型
Props父 → 子纯数据
插槽父 → 子模板/组件/HTML片段

二、基础插槽类型

1. 默认插槽

子组件

<!-- ChildComponent.vue -->
<template><div class="card"><slot>默认内容(父组件未提供时显示)</slot></div>
</template>

父组件

<ChildComponent><p>自定义卡片内容</p>
</ChildComponent>
2. 具名插槽

子组件

<template><div class="layout"><header><slot name="header"></slot></header><main><slot></slot> <!-- 默认插槽 --></main><footer><slot name="footer"></slot></footer></div>
</template>

父组件

<ChildComponent><template #header><h1>页面标题</h1></template><p>主内容区域</p><template v-slot:footer><p>版权信息 © 2023</p></template>
</ChildComponent>

三、作用域插槽(核心进阶)

1. 数据传递原理

子组件向插槽传递数据 → 父组件接收使用

子组件

<template><ul><li v-for="item in items" :key="item.id"><slot :item="item" :index="index"></slot></li></ul>
</template><script setup>
const items = ref([{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }])
</script>

父组件

<ChildComponent><template #default="{ item, index }"><span>{{ index + 1 }}. {{ item.name }}</span><button @click="deleteItem(item.id)">删除</button></template>
</ChildComponent>
2. 应用场景示例

场景:表格组件支持自定义列渲染
子组件

<template><table><thead><tr><th v-for="col in columns" :key="col.key">{{ col.title }}</th></tr></thead><tbody><tr v-for="row in data" :key="row.id"><td v-for="col in columns" :key="col.key"><slot :name="col.key" :row="row">{{ row[col.key] }} <!-- 默认显示 --></slot></td></tr></tbody></table>
</template>

父组件

<DataTable :data="users" :columns="columns"><template #action="{ row }"><button @click="editUser(row.id)">编辑</button><button @click="deleteUser(row.id)">删除</button></template><template #status="{ row }"><span :class="row.status">{{ row.status | statusText }}</span></template>
</DataTable>

四、动态插槽名

子组件

<template><div class="dynamic-slot"><slot :name="slotName"></slot></div>
</template><script setup>
defineProps({slotName: {type: String,default: 'default'}
})
</script>

父组件

<ChildComponent :slotName="currentSlot"><template #[currentSlot]><p>动态插槽内容(当前使用 {{ currentSlot }} 插槽)</p></template>
</ChildComponent>

五、高级技巧

1. 插槽继承($slots)

访问子组件插槽内容:

// 子组件内部
const slots = useSlots()
console.log(slots.header()) // 获取具名插槽内容
2. 渲染函数中使用插槽
// 使用 h() 函数创建元素
export default {render() {return h('div', [this.$slots.default?.() || '默认内容',h('div', { class: 'footer' }, this.$slots.footer?.())])}
}

六、最佳实践指南

  1. 命名规范

    • 使用小写字母 + 连字符命名具名插槽(如 #user-avatar

    • 避免使用保留字作为插槽名(如 defaultitem

  2. 性能优化

    <!-- 通过 v-if 控制插槽内容渲染 -->
    <template #header v-if="showHeader"><HeavyComponent />
    </template>
  3. 类型安全(TypeScript)

    // 定义作用域插槽类型
    defineSlots<{default?: (props: { item: T; index: number }) => anyheader?: () => anyfooter?: () => any
    }>()

七、常见问题解答

Q1:如何强制要求必须提供某个插槽

// 子组件中验证
export default {mounted() {if (!this.$slots.header) {console.error('必须提供 header 插槽内容')}}
}

Q2:插槽内容如何访问子组件方法?

<!-- 子组件暴露方法 -->
<slot :doSomething="handleAction"></slot><!-- 父组件使用 -->
<template #default="{ doSomething }"><button @click="doSomething">触发子组件方法</button>
</template>

Q3:如何实现插槽内容过渡动画?

<transition name="fade" mode="out-in"><slot></slot>
</transition>

八、综合应用案例

可配置的模态框组件

<!-- Modal.vue -->
<template><div class="modal" v-show="visible"><div class="modal-header"><slot name="header"><h2>{{ title }}</h2><button @click="close">×</button></slot></div><div class="modal-body"><slot :close="close"></slot></div><div class="modal-footer"><slot name="footer"><button @click="close">关闭</button></slot></div></div>
</template>

父组件使用

<Modal v-model:visible="showModal" title="自定义标题"><template #header><h1 style="color: red;">紧急通知</h1></template><template #default="{ close }"><p>确认删除此项?</p><button @click="confirmDelete; close()">确认</button></template><template #footer><button @click="showModal = false">取消</button></template>
</Modal>

http://www.dtcms.com/a/617278.html

相关文章:

  • 企业网站建设合同方案土巴兔装修口碑怎样
  • 做商品网站的教学视频教程张家口网站设计
  • 东莞专业网站推广工具建设监理继续教育网站
  • 做外贸自己开公司网站口碑营销有哪些方式
  • led灯具网站模板国外做汽配的网站
  • 网站打开慢怎么回事啊制作公司网页平台
  • 学校网站建设方案设计做装修公司网站
  • 网站制作工资163企业邮箱服务器
  • 江苏省住房和城乡建设厅假网站网站建设 蜀美网络
  • 怎么添加网站图标住房和城乡建设厅官网证书查询
  • 网站 备案 固话腾讯企业邮箱网页登录入口
  • 北京网站建设课程培训网页制作题用什么软件
  • 网站开发视频教程百度网盘做h的小说网站
  • 产品包装设计网站找谁做网站推广基本方法是
  • 购物网站html做写字楼租赁用什么网站好
  • 免费的行情软件网站不用下载鞍山自适应网站制作
  • 营销网站参考如何做网站建设方案
  • 阿里巴巴网站建设销售成都旅游网站建设规划
  • 沈阳网站建设21anshan网站建设经验心得
  • 沈阳做公司网站的公司在阿里巴巴做网站多少钱2019
  • 怎么看一个网站是不是外包做的做一个网站大概需要多少钱
  • 注册网站邮箱发送的验证网页无法打开青岛官网seo技术厂家
  • 自己做个网站wordpress5.0代码执行
  • 品牌网站建设还来大蝌蚪网站有pc站和手机站
  • 女性时尚网站源码wordpress 假用户插件
  • 银川市住房城乡建设局网站沈阳网站设计培训班
  • 搜搜提交网站入口洛阳网站公司哪家好
  • 郑州品牌营销网站建设网站 自适应文字大小怎么做
  • 网站建设企业排名小男孩做爰网站
  • 合肥网站seo优化排名宁夏免费做网站