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

文章目录

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

Ⅰ. props完整语法

一、语法

javascript 复制代码
defineProps({
  属性名: {
    type: 类型,       // Number、String、Boolean ...
    required: true,  // 是否必填
    default: 默认值,  // 默认值
    
    // value: 父传子的值
    validator (value) {
      // 自定义校验逻辑,比如判断value的范围
      return 布尔值
    }
  }
})
  1. default 和 required 最好不要同时写(因为当 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/reactive 与 props 的区别

特性 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>
相关推荐
凌云若寒8 分钟前
BarTender官网下载打印机驱动
运维·服务器·前端·网络·产品经理
zd84510150020 分钟前
基于 HTML 与 Modbus TCP 构建设备仪器上位机:可行性分析与代码结构设计
前端·tcp/ip·html
顽疲32 分钟前
Java vue 养老系统源码详解:入住核算单 live-check 缴费入账与预交金收据实践
java·vue.js·python·java 养老·springboot 养老·vue养老
Amumu121381 小时前
NodeJs介绍
前端·node.js
咧咧小侠1 小时前
Windows Codex 连接 Chrome 失败:一次 nodeRepl.fetch 报错排查记录
前端·chrome
Eider19981 小时前
大模型输出格式幻觉解决思路
开发语言·前端·javascript
广州智造1 小时前
Radioss时间步长(Time Step)
前端·设计·cad·建模·cae·radioss
志尊宝1 小时前
Vue3 零基础每日笔记(085):项目上线前 Checklist——环境变量、报错监控、安全自查
前端·javascript·笔记·安全·信息可视化·echarts
朱涛的自习室1 小时前
我让 Gemini 4 当高管、DeepSeek 当员工,开了一家软件公司(Day 1)
android·前端·人工智能
志尊宝1 小时前
Vue3 零基础每日笔记(088·完结):从零到一——一个完整 Vue3 项目的成长复盘
前端·javascript·vue.js·笔记·ecmascript·#vue.js