vue-组件通信(动态组件)

​🌈个人主页:前端青山

🔥系列专栏:Vue篇

🔖人终将被年少不可得之物困其一生

依旧青山,本期给大家带来vue篇专栏内容:vue-组件通信|动态组件

目录

组件通信

1.父传子

2.子传父

3.ref

4.兄弟组件

[5.跨层级 provide、inject](#5.跨层级 provide、inject)

动态组件

插槽

1.匿名插槽

2.具名插槽

3.作用域插槽

组件通信

在MVVM框架中,每个组件的数据都具有私有性,即默认情况下,组件自身的数据只允许在本组件内部供自己使用。但实际开发中,我们经常会需要将某些组件的数据对其它组件开放访问,此时就需要使用合适的通信方式来实现数据共享了,Vue框架中支持以下数据通信方式:

  • 父传子

  • 子传父

  • 兄弟通信

  • 非常深的层级的父子/子父关系等特殊关系 跨层级

1.父传子

为了便于理解父传子子传父,在理解时,可以寻求一下两种方式的切入点

即将父组件中的数据传递给子组件。Vue中父传子是借助props来进行传递的。具体实现思路是:

  • 父组件将数据以属性的方式绑定在子组件标签上

  • 子组件通过props属性进行接收,props支持两种书写形式:

    • 数组形式,书写简单,但不支持类型与默认值约束

    • 对象形式,书写复杂,但支持类型与默认值约束

在子组件收到props数据后,即可将数据当做自身的数据来使用,使用方法参照使用data数据的方式来即可。

请注意,props是单向数据流向的只读属性,不能在子组件中进行对其修改。

2.子传父

即将子组件中的数据传递给父组件。Vue中子传父是借助$emit/$on操作自定义事件实现的。具体实现思路是:

  • 在子组件中触发一个自定义事件,将需给父的数据以参数的形式传递给自定义事件

  • 父组件在子组件标签上监听刚才触发的自定义事件,并且定义事件处理程序,在事件处理程序中以形参的方式接收来子组件的数据

  • 如果需要保存来自子组件的数据,可以在回调函数中将来自子组件的数据保存到自身的data中

3.ref

子传父(父去拿子的数据)情况类似,形式与this.$children也是非常像的,可以看作ref是this.$children的完美替代方案。通过ref获取子节点实例的时候是不要获取子组件实例对应的索引。

ref属性被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用ref属性,则引用指向的就是 DOM 元素;如果ref属性用在子组件上,引用就指向子组件实例

javascript 复制代码
<template>
    <div>
        <!-- 
          ref:
          1. ref用于在父组件中去获取子组件/元素的对象
          2. 如果获取的子元素是一个组件,则获取到的对象是子组件实例
          3. 如果获取的子元素是一个普通的html标签,则获取到的对象是标签对应的dom对象
          4. 语法:
                a. 只需要给对应的元素绑定一个ref属性即可(属性值不能重名)
                b. 通过 this.$refs.属性值 来进行获取
                这里的this.$refs其实就是当前组件自身已经绑定的ref属性对象集合,对象属性名就是刚才通过ref属性绑定的属性值
                c. 通过对应的属性名来获取对应的对象
          5. 该套路与react后续的ref操作一致,区别在ref属性值,vue中我们可以直接写属性值,而react里属性值需要通过createRef()   useRef()等方法来创建
       -->
        <div ref="refDiv1">父组件</div>
        <div ref="refDiv2">今天是2月的最后1天,明天就是3月份</div>
        <Child ref="refChild"></Child>
​
        <button @click="getData">获取</button>
    </div>
</template>
​
<script>
import Child from "./Child.vue"
export default {
    components: {
        Child,
    },
    methods: {
        getData(){
            console.log(this.$refs);
            // 元素对应的dom获取
            console.log(this.$refs.refDiv1);
            console.log(this.$refs.refDiv2);
            // 元素对应的dom属性
            this.$refs.refDiv1.innerHTML = "0942"
            // 元素对应的实例获取
            console.log(this.$refs.refChild);
            // 元素对应的实例上属性
            console.log(this.$refs.refChild.date);
            // 元素对应的实例上的方法
            console.log(this.$refs.refChild.getDate());
        }
    }
}
</script>
​
<style></style>
4.兄弟组件

又称eventBus中央事件总线

核心步骤

  • 建立事件中心

    复制代码
    const eventBus = new Vue()
  • 传递数据

    复制代码
    eventBus.$emit('自定义事件名',传递的数据)
  • 接收数据

    复制代码
    eventBus.$on('自定义事件名'[,callback])
  • 销毁事件中心

    复制代码
    eventBus.$off('自定义事件名')

案例:互相伤害,具体代码实现可以查看本节对应的代码文件

通过组件模拟俩个角色,赋予组件角色名称、生命值、攻击力,给每个组件一个按钮,点击按钮实现攻击对方,发动攻击后需要扣减对方生命值,当任意一方生命值为0时,游戏结束。

  • 先将eventBus全局化(写在main.js中)

    • 思路:将需要全局化的数据挂载到Vue的原型上

    • // 将数据全局化 const eventBus = new Vue() // 只需要将需要全局化的数据放到Vue的原型上 Vue.prototype.$eventBus = eventBus

  • 后续按照上面的语法使用即可

5.跨层级 provide、inject

组件通信方式:

1、父传子 props、$parent

2、子传父 自定义事件 $emitchildren、`refs`

3、兄弟 eventbus emit on $off

4、跨层级 provider inject 依赖注入 $root

5、组件共享工具 vuex pinia

动态组件

通过使用保留的 <component>元素,动态地绑定到它的is 特性,==我们让多个组件可以使用同一个挂载点(位置),并动态切换。==

语法:

javascript 复制代码
<component :is="默认渲染的组件名"/>

场景:当我们希望实现tab选项卡切换的效果的时候就可以使用动态组件

案例:使用动态组件实现简易的步骤向导效果

插槽

插槽也是组件传值的一种方式。

组件的最大特性就是重用,而用好插槽能大大提高组件的可重用能力。

通俗的来讲,插槽无非就是在子组件中挖个坑,坑里面放什么东西由父组件决定。

插槽类型有:

  • 单个(匿名)插槽

  • 具名插槽

  • 作用域插槽

插槽标签:<slot></slot>

1.匿名插槽

简单来讲就是没有名字的插槽,在组件使用过程中,一个子组件中只能具备一个匿名插槽。

步骤

  • 父组件通过在子组件标签之间写内容

  • 子组件通过插槽获取父写的内容

父组件

javascript 复制代码
<div>
    <Child>{{thing}}</Child>
    <Child>用户名不能为空</Child>
    <Child>用户名已经被使用</Child>
    <Child>密码输入不一致</Child>
</div>

子组件

javascript 复制代码
<div class="warn">
    错误:<slot></slot>
</div>
2.具名插槽

与匿名插槽非常的像,区别在于具名插槽是具有名字的插槽,与匿名相比多了个名字而已。

步骤

  • 子组件通过预留slot标签来挖坑,但是这里插槽有名字(只需要给slot标签name属性即可)

    • name值在当前范围内要唯一

    • 可以存在多个具名插槽

    • 同时也可以存在匿名插槽,匿名插槽只能有一个

  • 父组件需要去填坑,父组件写在子组件标签之间的元素也需要存在多个,每个元素上需要有绑定到的插槽的名字(通过slot="名"形式进行指定)

  • 如果元素没有名字则绑定到对应的匿名插槽上,如果子组件没有匿名插槽则数据丢弃

3.作用域插槽

**应用场景:**父组件对子组件的内容进行加工处理

作用域插槽是一种特殊类型 的插槽,作用域插槽会绑定了一套数据,父组件可以拿这些数据来用,于是,情况就变成了这样:样式父组件说了算,但父组件中内容可以显示子组件插槽绑定的数据。

简单来讲:子也可以往坑里放数据,让父组件去拿(子→父)

示例代码

javascript 复制代码
==父组件==

<template>
    <div>
        <!-- 
          作用域插槽:
          1. 三个插槽中最难理解的一个
          2. 作用:子-父
          3. 子组件如果需要把数据往坑里放,需要将数据以属性值的形式放在slot标签上,属性值可以多个,但是名不能用name
          4. 父需要给子组件标签里加一个元素,元素现在一般是div(理论上讲任意标签都行),给div加上slot-scope属性,值一般是props
          5. 第4步中的props就是第3步中绑定的那些数据的集合(对象形式)
​
          6. slot-scope属性所在标签上面不能再有其它的标签,必须是子组件标签
       -->
        <Child :uname="name">
            <div slot-scope="props">
                <div>
                    <button @click="changeName(props.newname)">修改名字</button>
                </div>
            </div>
        </Child>
    </div>
</template>
​
<script>
import Child from "./Child.vue"
export default {
    data() {
        return {
            name: "牛牛",
        }
    },
    components: {
        Child,
    },
    methods: {
        changeName(name) {
            this.name = name
        },
    },
}
</script>
​
<style></style>

==子组件==

javascript 复制代码
<template>
    <div>
        <div>勇敢{{ uname }},不怕困难。</div>
        <!-- <button @click="changeName">修改名字</button> -->
        <slot :newname="newname"></slot>
    </div>
</template>
​
<script>
export default {
    data() {
        return {
            newname: "牛牛",
        }
    },
    props: {
        uname: {
            type: String,
        },
    },
    // methods: {
    //     changeName() {
    //         this.uname = this.newname
    //     },
    // },
}
</script>
​
<style></style>
​
相关推荐
mldong28 分钟前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排1 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60612 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角3 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!3 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰3 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi5 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen5 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马6 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu6 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss