【Vue】props完整语法 && 非父子组件通信 && provide && inject && eventBus

文章目录

  • [Ⅰ. props完整语法](#Ⅰ. props完整语法)
  • [Ⅱ. 非父子组件通信](#Ⅱ. 非父子组件通信)

Ⅰ. props完整语法

一、语法

javascript 复制代码
defineProps({
  属性名: {
    type: 类型,       // Number、String、Boolean ...
    required: true,  // 是否必填
    default: 默认值,  // 默认值
    
    // value: 父传子的值
    validator (value) {
      // 自定义校验逻辑,比如判断value的范围
      return 布尔值
    }
  }
})
  1. defaultrequired 最好不要同时写(因为当 required=true 时,默认值也就无效了)
  2. default 后面如果是简单类型的值,可以直接写默认。如果是复杂类型的值,则需要以函数的形式 return 一个默认值

二、代码示例

App.vue文件:

javascript 复制代码
<template>
    <MyProgress :width="20"/>
    <MyProgress :width="50"/>
    <MyProgress />
    <MyProgress :width="-10"/>
    <MyProgress :width="210"/>
</template>

<script setup>
    import MyProgress from './components3/MyProgress.vue';
</script>

<style scoped></style>

MyProgress.vue文件:

javascript 复制代码
<script setup>
    defineProps({
        width: {
            type: Number,
            required: false,
            default: 50,

            validator(value) {
                // 控制范围
                if(value < 0 || value > 100) {
                    return false;
                }
                return true;
            }
        }
    })
</script>

<template>
  <div class="my-progress">
    <div
      class="inner"
      :style="{width : width + '%'}">
      <span>{{ width }}%</span>
    </div>
  </div>
</template>

<style scoped>
.my-progress {
  height: 26px;
  width: 400px;
  border-radius: 15px;
  background-color: #272425;
  border: 3px solid #272425;
  box-sizing: border-box;
  margin-bottom: 30px;
}
.inner {
  position: relative;
  background: #379bff;
  border-radius: 15px;
  height: 25px;
  box-sizing: border-box;
  left: -3px;
  top: -2px;
}
.inner span {
  position: absolute;
  right: -30px;
  top: 26px;
}
</style>

三、ref/reactiveprops 的区别

特性 ref reactive props
定义位置 组件内部 组件内部 由父组件传入
数据类型 基本类型/单值 对象/数组 任意类型
是否响应式 ✅(来自父)
能否修改 ✅(.value) ❌(建议复制副本修改)
模板使用 自动解包({{ count }}) 直接访问({{ state.age }}) 直接访问({{ title }})

Ⅱ. 非父子组件通信

一、祖先传后代:provide && inject

祖先组件通过 provide 给后代提供数据:

javascript 复制代码
import { provide } from 'vue'
provide('数据名称', 值)

后代组件通过 inject 获取到祖先提供的数据:

javascript 复制代码
import { inject } from 'vue'
const value = inject('数据名称')

下面举个例子,模拟三代中祖先传给孙子的情况:

App.vue文件:

javascript 复制代码
<template>
<div class="app">
    <h3>我是祖先组件</h3>
    <my-parent />
</div>
</template>

<script setup>
    import { provide, ref } from 'vue';
    import MyParent from './components5/MyParent.vue';
    
    const money = ref(520)
    provide('rmb', money)
</script>

<style scoped>
    .app {
        background-color: aqua;
        padding: 20px;
    }
</style>

components5/MyParent.vue文件:

javascript 复制代码
<template>
    <div class="my-parent">
        <h3>我是父组件</h3>
        <my-child />
    </div>
</template>

<script setup>
    import MyChild from './MyChild.vue';
</script>

<style scoped>
    .my-parent {
        padding: 20px;
        background-color: chartreuse;
    }
</style>

components5/MyChild.vue文件:

javascript 复制代码
<template>
    <div class="my-child">
        <h3>我是子组件</h3>
        <p>收到爷爷的压岁钱:{{ money }}</p>
    </div>
</template>

<script setup>
    import {inject} from 'vue'

    const money = inject('rmb')
</script>

<style scoped>
    .my-child {
        background-color: blanchedalmond;
        padding: 20px;
    }
</style>

二、任意两个组件通信:eventBus

首先下载 mitt 模块包:

javascript 复制代码
npm install --save mitt

然后创建公共中间人模块(类似媒婆和中介),即创建一个 eventBus.js 文件:

javascript 复制代码
// 导入中介模块
import mitt from 'mitt'

// 通过 mitt() 拿到中介
const meipo = mitt()

// 默认导出:目的是给别的组件拿到 meipo 中间人
export default meipo

接着按照以下步骤走:

  1. 消息发送方: 使用 meipo.emit('消息名称', 数据) 发送消息
  2. 消息接收方: 使用 meipo.on('消息名称', (数据) => { 处理消息代码块 }) 接收消息并进行处理

举个例子:

App.vue文件:

javascript 复制代码
<template>
<div class="app">
    <my-left />
    <my-right />
</div>
</template>

<script setup>
    import MyLeft from './components6/MyLeft.vue';
    import MyRight from './components6/MyRight.vue';
</script>

<style scoped>
 .app {
    display: flex;
    align-items: center;
    justify-content: center;
 }
</style>

eventBus.js文件:

javascript 复制代码
import mitt from 'mitt'

// 拿到中介
const meipo = mitt()

// 默认导出:目的是给别的组件拿到 meipo 中间人
export default meipo

components6/MyLeft.vue文件:

javascript 复制代码
<template>
<div class="my-left">
    <p>我是左组件</p>
    <button @click="sendMsg">点击我发送消息给右组件</button>
</div>
</template>

<script setup>
    import { ref } from 'vue';
    import meipo from './eventBug';

    const text = ref('i like you~')

    const sendMsg = () => {
        // 发送方调用emit()发送消息
        meipo.emit('msg', text.value)
    }
</script>

<style scoped>
    .my-left {
        flex: 1;
        background-color: antiquewhite;
        text-align: center;
        height: 100px;
    }
</style>

components6/MyRight.vue文件:

javascript 复制代码
<template>
<div class="my-right">
    <p>我是右组件</p>
</div>
</template>

<script setup>
    import meipo from './eventBug';

    // 接收方调用 on() 接收消息并且进行处理
    meipo.on('msg', (text) => {
        console.log(text);
    })
</script>

<style scoped>
    .my-right {
        flex: 1;
        background-color: palegreen;
        text-align: center;
        height: 100px;
    }
</style>
相关推荐
DYuW5gBmH2 分钟前
Chrome DevTools MCP 让 AI 无缝接管浏览器调试会话
前端·chrome·chrome devtools
echome8887 分钟前
JavaScript Promise 与 async/await 实战:5 个高频异步编程场景的优雅解决方案
开发语言·javascript·ecmascript
qq12_81151751529 分钟前
Java Web 影城会员管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】
java·前端·mybatis
摸鱼仙人~1 小时前
Math.js 使用教程
开发语言·javascript·ecmascript
weixin199701080161 小时前
《中控网商品详情页前端性能优化实战》
前端·性能优化
wuhen_n2 小时前
LangChain Agents 实战:构建智能文件管理助手
前端·javascript·人工智能·langchain·ai编程
Vfw3VsDKo2 小时前
Flink源码阅读:Netty通信
java·前端·flink
别抢我的锅包肉2 小时前
【FastAPI】 + SQLAlchemy 异步 ORM 实现完整 CRUD 操作
前端·fastapi
. . . . .2 小时前
抽象语法树 AST
javascript
zero15973 小时前
TypeScript 快速实战系列:基础入门|TypeScript 核心语法 1 小时吃透(必备基础)
javascript·typescript·大模型编程语言