跟禹神VUE——组件间的通信方式(props配置项、组件间自定义事件、全局事件总线、消息订阅与发布、VUEX)

一、通过props配置项传递数据(适用于父组件给子组件传递数据)

父组件向子组件传递数据:

父组件代码:在子组件的标签中传递数据

<template>
    <div>
        <h2>学校名称:{{schoolName}}</h2>
        <!-- 方式一:props(父传子) 教师收到学校的名称 -->
        <h1>教师组件:</h1>
        <Teacher :schoolName="schoolName"></Teacher>

    </div>
</template>

<script>
import Teacher from './Teacher.vue';
export default {
    name:'School',
    components:{
        Teacher
    },
    data() {
        return {
            schoolName:'尚硅谷',
        }
    }
}
</script>

<style>
</style>

        子组件代码:定义props配置项去获取父组件在组件标签中传递的数据,props中的数据会存入组件实例对象中,使用数据时直接调用即可。

<template>
    <div >
        <h2>所属学校名称:{{schoolName}}</h2>
    </div>
</template>

<script>
export default {
    name:'Teacher',
    props:['schoolName']
}
</script>

<style>
</style>

子组件传递数据到父组件:

父组件:定义一个函数接收子组件传递的数据,并把函数放到子组件的标签中传递给子组件

<template>
    <div>
      <h2>教师名称:{{teacherName}}</h2>
      <Teacher :getTeacher="getTeacher"></Teacher>
    </div>
</template>

<script>
import Teacher from './Teacher.vue';
export default {
    name:'School',
    components:{
        Teacher
    },
    data() {
        return {
            teacherName:''
        }
    },
    methods: {
        getTeacher(teacherName){
            this.teacherName=teacherName
        }
    }
}
</script>

<style>
</style>

子组件:使用props配置项接受父组件传递的函数,定义点击事件,在事件中调用父组件的函数并把数据传递

<template>
    <div >
      <button @click="sendName">点我传递教师名</button>
    </div>
</template>

<script>
import StuOne from './StuOne.vue';
import StuTwo from './StuTwo.vue';
export default {
    name:'Teacher',
    props:['getTeacher'],
    data () {
        return {
            tName:'桥老师'
        }
    },
    methods:{
        sendName(){
            this.getTeacher(this.tName)
        }
    }
}
</script>

<style>
</style>

二、组件的自定义事件(适用于子组件向父组件传递数据)

自定义事件写法一:

父组件中:使用@或v-on指令为子组件绑定一个事件,并在父组件中定义一个事件被触发后的回调函数

<template>
    <div>
        <h2>教师年龄:{{teacherAge}}</h2>
        <!-- 方式二 自定义事件(子传父) -->
        <Teacher @getAge="gotAge"></Teacher>
    </div>
</template>

<script>
import Teacher from './Teacher.vue';
export default {
    name:'School',
    components:{
        Teacher
    },
    data() {
        return {
            teacherAge:''
        }
    },
    methods: {
        gotAge(age){
            this.teacherAge=age
        }
    }
}
</script>

<style>
</style>

子组件中:使用$emit()去触发父组件为自己绑定的事件,并把数据携带给父组件的回调函数。($emit()在子组件的实例对象上,使用this获取) 在此案例中使用钩子函数触发事件。

<template>
    <div >
    </div>
</template>

<script>
export default {
    name:'Teacher',
    data () {
        return {
            tAge:22
        }
    },
    mounted () {
        this.$emit('getAge',this.tAge)
    }
}
</script>

<style>
</style>

自定义事件写法二:

父组件中:为子组件设置ref属性,在钩子函数中使用this.$refs.属性名获取子组件实例对象,再使用$on()为子组件实例对象绑定事件并设置回调函数

<template>
    <div>
      <Teacher ref="tea"></Teacher>
    </div>
</template>

<script>
import Teacher from './Teacher.vue';
export default {
    name:'School',
    components:{
        Teacher
    },
    data() {
        return {
            teacherAge:''
        }
    },
    methods: {
        gotAge(age){
            this.teacherAge=age
        }
    },
    mounted(){
        //回调函数可以使用箭头函数,也可以定义到methods中再使用this调用
        this.$refs.tea.$on('getAge',(age)=>{
            this.teacherAge=age
        })
    }
}
</script>

<style>
</style>

子组件中:此案例中定义了一个点击事件触发自定义事件。不可使用钩子函数触发自定义事件,因为Vue脚手架默认的编译顺序是先编译被父组件引入的子组件,这样会导致触发函数无法匹配到父组件定义的自定义事件。

<template>
    <div >
       <button @click="sendAge">点我传递教师年龄</button>
    </div>
</template>

<script>
export default {
    name:'Teacher',
    data () {
        return {
            tAge:22
        }
    },
    methods:{
        sendAge(){
            this.$emit('getAge',this.tAge)
        }
    },
}
</script>

<style>
</style>

当子组件废弃时,使用this.$off(事件名)即可解绑事件

三、全局事件总线(适用于任意组件间通信,最适合祖孙组件、兄弟组件之间)

原理:

全局事件总线,全局两个字,意思是在全局都能够访问到。并且能够绑定方法呢?

我们之前给子组件绑定自定义事件的时候,其本质就是为子组件的实例对象new VueComponent绑定上一个自定义事件。

在这个全局事件总线中,我们就不能再给每个组件的实例对象来绑定自定义事件了,而是要将自定义事件绑定到一个全部组件都能够访问的对象上。看到这张图你就有了答案:

 我们将它放在vue原型上,那么全局事件总线就能够做到任意间组件通信。

在main.js中设置事件总线:

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

const vm=new Vue({
  render: h => h(App),
  //在Vue实例对象创建前在Vue原型创建全局事件总线
  beforeCreate(){
    //把$bus变成Vue实例对象vm,组件就可以通过this调用它
    Vue.prototype.$bus=this
  }
}).$mount('#app')

console.log(Vue.prototype.$bus)

在获取数据的组件中:为传递数据的组件绑定事件,并定义回调函数。

<template>
    <div class="stu">
        <h3>我是李四</h3>
        <h3>张三的年龄是:{{Zage}}</h3>
    </div>
</template>

<script>
export default {
    name:'StuTwo',
    data () {
        return {
            Zage:''
        }
    },
    mounted(){
        this.$bus.$on('getAge',(age)=>{
            this.Zage=age
        })
    }
}
</script>

<style>
</style>

在传递数据的组件中:触发事件并传递数据

<template>
  <div class="stu">
    <h3>我是张三</h3>
    <button @click="sendAge">把我的年龄告诉李四</button>
  </div>
</template>

<script>
export default {
    name:'StuOne',
    data() {
        return {
            age:24
        }
    },
    methods: {
        sendAge(){
            this.$bus.$emit('getAge',this.age)
        }
    }

}
</script>

<style>

</style>

四、消息的订阅以及发布

一种组件间通信的方式,适用于任意组件间通信。

使用步骤:

1.安装pubsub:npm i pubsub-js

2.引入: import pubsub from 'pubsub-js'

                1.接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。

                methods(){ demo(message,data){......} } ...... mounted() { this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息 }

                2.提供数据:pubsub.publish('xxx',数据)

                3.最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)去取消订阅。

注意: subscribe的回调函数中有两个参数,第一个参数是消息的名称,第二个参数才是发布消息所携带的数据

例:School组件获取Student组件的数据

School组件:在钩子函数中订阅消息

<template>
    <div>
        <h2>学生的姓名:{{studentName}}</h2>
    </div>

</template>

<script>
import Teacher from './Teacher.vue';
import pubsub from 'pubsub-js'
export default {
    name:'School',
    data() {
        return {
            studentName:''
        }
    },
    mounted(){
        //订阅消息
        pubsub.subscribe('getName',(msg,name)=>{
            this.studentName=name
        })
    }
}
</script>

<style>
</style>

Student组件:发布消息

<template>
  <div>
    <button @click="sendName">把我的姓名告诉学校</button>
  </div>
</template>

<script>
import pubshb from 'pubsub-js'
export default {
    name:'StuOne',
    data() {
        return {
            name:'张三'
        }
    },
    methods: {
        sendName(){
         //发布消息
            pubshb.publish('getName',this.name)
        }
    }

}
</script>

<style>

</style>

五、使用VueX集中管理数据

概念:

        专门在Vue中实现集中式状态(数据)管理的Vue插件,对Vue应用中多组件的共享数据进行管理(读/写),也是组件间通信方式之一,适用于任意组件间通信。

何时使用?

        当多个组件共同使用同一状态(数据)时

        当多个组件修改同一状态(数据)时

工作原理:

 首先,VueX中有四个角色,分别是Actions对象、Mutations对象、State对象、Store对象,它们是用来干什么的呢?

        State:存放共享数据

        Mutations:对数据进行操作,开发者工具中可以看到Mutations的工作记录

        Actions:负责编写代码逻辑,并调用Mutations去处理State中数据,可以连接接口、AJAX等

        Store:管理者State、Mutations、Actions,在组件中使用this.$Store去操作他们

工作流程:

        组件调用dispatch('Actions中函数名',参数)去找Actions,Actions帮组件执行指定函数,函数中通过commit('Mutations函数名',value)去找Mutations,Mutations去操作State中的数据,然后把操作后的数据渲染到页面上。当对数据操作的逻辑较为简单时,组件可以直接通过commit找Mutations去操作数据。

        了解三层架构的小伙伴应该可以更快速的理解他们之间的关系,Actions类似于Service层,Mutations类似于Dao层。

生动理解:

        再举一个形象的例子:把Vuex看做一个餐厅,Store就是餐厅的经理,Actions是餐厅服务员,Mutations是厨师,而State就是菜品,组件扮演顾客。

        顾客来到餐厅吃饭,喊服务员过来点菜,服务员把点的菜通知厨师,厨师去做菜,菜被端到顾客的桌子上。那么也有一种情况,就是当这个顾客和这家餐厅很熟,那么顾客可以直接联系厨师去做菜。

代码实现:

 注意!在下载vuex时最好指定vuex的版本(npm i vuex@3)。vue2使用vuex3版本,vue3使用vuex4以及以上版本。

根据vue官方推荐形式,首先在src中创建store文件夹,在文件夹下定义index.js,在index.js中创建Actions对象、Mutations对象、State对象并把他们封装到使用vuex.Store创建的store中并暴露。

import Vue from 'vue'
import vuex from 'vuex'

Vue.use(vuex)

const actions ={
    //actions中函数有两个参数,第一个参数是上下文参数,其中有state中属性,mutations中函数等
    //第二个参数才是传过来的数据
    changeName(context,value){
        context.commit('CHANGE_NAME',value)
    }
}

const mutations={
    //mutations中函数也有两个参数,第一个是state的属性,第二个参数才是传过来的值
    CHANGE_NAME(state,value){
        state.firstStu=value
    }
}
const state={
    //定义一个变量存放姓名
    firstStu:'张三'
}

export default new vuex.Store({
    actions,
    mutations,
    state
})

在main.js中引入store并使用

import Vue from 'vue'
import App from './App.vue'
import store from './store/index'

Vue.config.productionTip = false

const vm=new Vue({
  render: h => h(App),
  store,
}).$mount('#app')

创建Teacher组件读取store.state中的姓名,StudentOne组件负责修改姓名

<template>
    <div >
        <h2>学生:{{ $store.state.firstStu}}!</h2>
        <StuOne></StuOne>
    </div>
</template>

<script>
import StuOne from './StuOne.vue';

export default {
    name:'Teacher',
    components:{
        StuOne
    }
}
</script>

<style>
</style>
<template>
  <div class="stu">
    <h3>我是{{$store.state.firstStu}}</h3>
    <!-- 使用vuex技术修改姓名 -->
    <input type="text" v-model="name">
    <button @click="changeName">改名按钮</button>
  </div>
</template>

<script>
export default {
    name:'StuOne',
    data() {
        return {
            name:''
        }
    },
    methods: {
        changeName(){
            this.$store.dispatch('changeName',this.name)
        }
    }
}
</script>

<style>
</style>

由于使用store的state中的值时,代码过长($store.state....),vuex为我们提供了mapState以便我们简便的操作state中数据:

1.引入mapState:import {mapState} from 'vuex'

2.使用:

<template>
    <div >
        <h2>学生:{{firstStu}}!</h2>
        <StuOne></StuOne>
    </div>
</template>

<script>
import StuOne from './StuOne.vue';
import {mapState} from 'vuex'

export default {
    name:'Teacher',
    components:{
        StuOne,
    },
    computed: {
        ...mapState({firstStu:'firstStu'})
        //简写形式:
        //...mapState(['firstStu])
    }

}
</script>

<style>
</style>

vuex还为我们提供了mapActions、mapMutations、mapGetters等方便我们操作函数

<template>
  <div class="stu">
    <h3>我是{{firstStu}}</h3>
    <!-- 使用vuex技术修改姓名 -->
    <input type="text" v-model="name">
    <!--调用函数时就传值-->
    <button @click="changeName(name)">改名按钮</button>
  </div>
</template>

<script>
import {mapState,mapActions} from 'vuex'
export default {
    name:'StuOne',
    data() {
        return {
            name:'张三'
        }
    },
    methods: {
        ...mapActions(['changeName'])
    },
    computed:{
        ...mapState(['firstStu'])
    }

}
</script>

<style>
</style>

 注意!由于使用了mapActions去为我们调用store中actions的函数,所以需要我们在模板中使用函数时传值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/68024.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kafka是有序的吗?如何保证有序?

首先&#xff0c;Kafka无法保证消息的全局有序性&#xff0c;这是因为Kafka的设计中允许多个生产者并行地向同一个主题写入消息。而且&#xff0c;一个主题可能会被划分为多个分区&#xff0c;每个分区都可以在独立的生产者和消费者之间进行并行处理。因此&#xff0c;生产者将…

ABC300

ABC300E 题面 思路 对于投骰子&#xff0c;最后一步可能得到1、2、3、4、5、6&#xff0c;那么对应的最后一步之前的数是n/1、n/2、n/3、n/4、n/5&#xff0c;n/6。并且每个数字&#xff08;1、2、3、4、5、6&#xff09;得到的概率是一样的&#xff0c;即为1/6。 也就是F(n…

CC++内存管理

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析2 目录 &#x1f449;&#x1f3fb;c内存管理方式new/delete 操作内置类型new和delete操…

redis的持久化

第一章、redis的持久化 1.1&#xff09;持久化概述 ①持久化可以理解为将数据存储到一个不会丢失的地方&#xff0c;Redis 的数据存储在内存中&#xff0c;电脑关闭数据就会丢失&#xff0c;所以放在内存中的数据不是持久化的&#xff0c;而放在磁盘就算是一种持久化。 ②为…

misc学习(1)Bugku-社工-进阶收集

新手一枚&#xff0c;参考文献如下&#xff1a; Bugku&#xff1a;社工-进阶收集_bugku 社工 进阶收集_FW_ENJOEY的博客-CSDN博客 照片如图所示&#xff1a; 线索线&#xff1a; 1.百度识图 发现是大雁塔 2.主角家距离大雁塔一共有七站地铁&#xff0c;其中要进行中转。 同时…

剑指Offer68-I.二叉搜索树的最近公共祖先 C++

1、题目描述 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也…

uni——月份选择(横向滑动tab,横向滚动选择日期)

案例展示 案例代码 已封装成组件使用 <template><view><view class"tabBox"><scroll-view scroll-x"true" :scroll-left"scrollLeft" :scroll-with-animation"true"><view class"box"><…

STM32--EXTI外部中断

前文回顾---STM32--GPIO 相关回顾--有关中断系统简介 目录 STM32中断 NVIC EXTI外部中断 AFIO EXTI框图 旋转编码器简介 对射式红外传感器工程 代码&#xff1a; 旋转编码器工程 代码&#xff1a; STM32中断 先说一下基本原理&#xff1a; 1.中断请求发生&#xff1a…

Zabbix自动注册服务器及部署代理服务器

文章目录 一.zabbix自动注册1.什么是自动注册2.环境准备3.zabbix客户端配置4.在 Web 页面配置自动注册5.验证自动注册 二.部署 zabbix 代理服务器1.分布式监控的作用&#xff1a;2.环境部署3.代理服务器配置4.客户端配置5.web页面配置5.1 删除原来配置5.2 添加代理5.3 创建主机…

周末在家值班,解决几个月前遗忘的Bug

问题&#xff1a; 周末被迫在家值班&#xff0c;无聊之际打开尘封已久的Bug清单&#xff0c;发现有Bug拖了几个月还没解决… 场景是这样子的&#xff0c;有个功能是拿Redis缓存热点数据进行展示&#xff0c;暂且称它为功能A&#xff0c;有个另外的功能B&#xff0c;它会去更新缓…

day3 STM32 GPIO口介绍

GPIO接口简介 通用输入输出接口GPIO是嵌入式系统、单片机开发过程最常用的接口&#xff0c;用户可以通过编程灵活的对接口进行控制&#xff0c;实现对电路板上LED、数码管、按键等常用设备控制驱动&#xff0c;也可以作为串口的数据收发管脚&#xff0c;或AD的接口等复用功能使…

家政服务平台|家政上门服务系统打开时代新渠道

在快节奏的现代社会&#xff0c;工作和家庭的双重压力常常使人们备受折磨。为了缓解这种压力&#xff0c;我们公司推出了一款创新的家政上门服务系统&#xff0c;旨在为您提供便捷、高效的生活服务。通过结合先进技术和人性化服务&#xff0c;我们致力于改善您的生活品质&#…

JPA实现存储实体类型信息

本文已收录于专栏 《Java》 目录 背景介绍概念说明DiscriminatorValue 注解&#xff1a;DiscriminatorColumn 注解&#xff1a;Inheritance(strategy InheritanceType.SINGLE_TABLE) 注解&#xff1a; 实现方式父类子类执行效果 总结提升 背景介绍 在我们项目开发的过程中经常…

CMake:检测python模块和包

CMake:检测python模块和包 导言项目结构CMakeLists.txt相关源码 导言 上一篇&#xff0c;我们基本了解了如何去检测python的解释器和python库。通常&#xff0c;代码是依赖于特定的python模块&#xff0c;无论是python工具、嵌入python的程序&#xff0c;还是扩展python的库。…

法律监督大数据平台有什么作用?

大数据赋能时代法律监督&#xff0c;构建法律行业领域大数据监督模型。法律监督大数据研判系统助力检察机关以社会公正为核心价值追求&#xff0c;对执法不严、司法不公“零容忍”&#xff0c;强化对诉讼活动的法律监督&#xff0c;坚决维护法律尊严&#xff0c;坚决捍卫公平正…

创建Springboot+vue3项目

项目概述创建springboot项目加入mybatis-plus支持1.加入依赖代码2.创建数据库实例3.yml文件的配置4.编写测试代码5.测试结果 创建vue项目报错错误一错误二错误三 项目概述 后端&#xff1a;Springboot、mybatis-plus、java 前端&#xff1a;nodejs、vue脚手架、element-ui 数据…

研发工程师玩转Kubernetes——PVC使用Label和storage选择PV

在《研发工程师玩转Kubernetes——local型PV和PVC绑定过程中的状态变化》和《研发工程师玩转Kubernetes——使用local型PV在不同Pod上共享数据》中&#xff0c;我们介绍了指定VPC的spec.volumeName为PV名称来绑定它们的方法。本文将介绍PVC在创建时&#xff0c;系统自动选择绑定…

GEE学习04-

0 回顾 之前学习的内容可以概括为&#xff1a; conda activate gee cd /d e:/geelearn jupyter lab可以在prompt中chrlc停止当前打开的jupyter lab. import ee #ee.Authenticate() import geemap geemap.set_proxy(port 1080) map geemap.Map() map1、视频课学习 之后跟着…

SonarQube安装与Java、PHP代码质量分析扫描

文章目录 1、下载安装1.1、SonarQube下载1.2、SonarQube安装1.3、SonarQube中文汉化1.4、SonarScanner扫描器 2、扫描项目2.1、java代码扫描2.2、php代码扫描 1、下载安装 SonarQube负责存储代码数据、收集数据、分析代码和生成报告等。 1.1、SonarQube下载 下载地址&#x…

【TypeScript】类型断言-类型的声明和转换(五)

【TypeScript】类型断言-类型的声明和转换&#xff08;五&#xff09; 【TypeScript】类型断言-类型的声明和转换&#xff08;五&#xff09;一、简介二、断言形式2.1 尖括号语法2.2 as形式 三、断言类型3.1 非空断言3.2 肯定断言-肯定化保证赋值3.3 将任何类型断言为any3.4 调…