vue2组件通信和vue3组件通信的方式

Vue2组件通信方式

一 、props

  • 使用场景:[父子通信]

  • 传递数据类型:
    1:可能是函数 -----------实质子组件想给父亲传递数据
    2:可能不是函数-----------实质就是父亲给子组件传递数据

    <TodoList :todos="123"  @updateChecked="hander">
    // 子传父,在子组件中调用hander 但 hander 函数是写在父组件中的
    

二、 自定义事件

  • 使用场景:[子给父传递数据]
    儿子$emit----> 父亲$on[简写@]
    父亲中的两种写法:
    [简单写法|复杂写法]
    <Todos @erha="handler">
    <Todos ref='erha'>
    mounted(){
      this.$refs.erha.$on('xx',callBack)
    }
    
  • 自定义事件
    • 子向父传递数据
    • 事件类型 回调函数 谁调用 默认传递的是什么?
      • 1、事件类型 无数个
      • 2、回调函数 自己去定义的
      • 3、谁调用 自己去调用自己使用$emit触发调用的
      • 4、默认传递的是什么? 默认传递的是自己给的参数有就有,没有就没有 (undefined)
        this.$emit( 'haha' ,10)

三、全局事件总线

  • 使用场景: [所有场合]
  • 全局事件总线的角色标准
    1、所有的组件对象都可以看到它
    2、可以使用$on$emit方法
    vm对象
    vm对象必须挂在Vue的原型上
  • 怎么添加事件总线?
    1、安装总线
    2、在接收数据的组件对象当中获取总线给总线绑定自定义事件this.$bus.$on
    3、在发送数据的组件对象当中︰获取总线触发总线身上绑定的自定义事件this. $bus.$emit

四、 pubsub-js【发布订阅消息】*****在vue中根本不用【React用】 ----万能

  • 类似于全局事件总线 但是在vue当中因为有了全局事件总线 所有一般不用
  • 是一个第三方包来实现地消息的订阅和发布 但是这个包使用起来会增加体积

五、 Vuex

  • 使用场景 : Vuex[仓库] ----万能的
  • 注意点: 数据非持久化(刷新会丢失,自动登录的时候需要考虑(可以放在本地存储里))
  • 什么时候用? 看项目大小,项目大就用这个
    看项目的大小来决定要不要使用vuex
    一般我们都要用的,一般情况我们的项目都比较大,项目比较复杂,使用vuex比较方便
    项目如果很小,使用vuex反而会降低效率,因为vuex是需要占用打包体积的
  • 核心概念:5
    js { state mutations actions getters modules }

六、 插槽

  • 使用场景: -----父子通信【结构】
    slot
    默认插槽
    具名插槽
    作用域插槽:子组件的数据来源于父组件,但是子组件的自己的结构由父亲决定。

七、 v-model实现组件通信,(父子同步)

  • v-model:指令,可以收集表单数据【text、radio、checkbox、range】等等

  • 切记:v-model收集checkbox需要用数组收v-model在不同身上的作用

    • :value="msg"在html标签身上是单向数据绑定
    • :value="msg"在组件标签身上是props组件通信
    • @input html标签身上是原生dom事件
    • @input 组件标签身上是自定义事件
      使用我们的v-model 达到父子同步的效果!!!
v-model本质其实是单向数据绑定v-bind和input事件的组合
在html标签中, :value是负责读取的 @input是负责赋值的 ,这样就形成了双向数据绑定
    
    // <input type="text" :value="msg" @input=" msg = $event.target.value" >
    // <span>塞北的大雪{{msg}}</span>
    

父组件(Communication)中的代码
      :value给子组件传递数据,然后通过自定义事件在从子组件中拿数据,就形成了父子同步
     <CustomInput :value="msg"  @input="msg = $event" ></CustomInput>
    //  <CustomInput v-model="msg"></CustomInput>   这两个的效果是一样的,写哪个都行!
     value是我们的props传参方式 @ipnut是我们的自定义事件  $event是触发自定义事件接受的参数


子组件(CustomInput)中的代码
    <div>
      <h2>input包装组件</h2>
第一个value是单向数据绑定值是父组件传过来的 这个@input是原生dom事件 $emit是触发事件 input是自定义事件名称 后面的是input框的值作为参数传递过去了
      <input type="text" :value="value" @input="$emit('input',$event.target.value)" >
    </div>

    <script type="text/ecmascript-6">
      export default {
        name: 'CustomInput',
        props:['value']
      }
    </script>

八、 属性修饰符.sync,可以实现父子数据同步。

.sync和v-model用在组件标签上,都可以达到父子组件数据同步
区别:
.sync达到数据同步: 子组件内部不是表单类元素
v-model达到数据同步:子组件内部一定是表单类元素
  • 以后在elementUI组件中出现,实现父子数据同步。
// 父组件
<div>
      小明的爸爸现在有{{money}}<h2>不使用sync修改符</h2>
    <Child :money="money" @update:money="money = $event" ></Child> 
    //必须用@update:xxx ,这么写相当与.sync
-------------------------------------------------------------------------------------
    <h2>使用sync修改符</h2>
    <Child :money.sync="money"></Child >
------------------------------------------------------------------------------------
    <h2>使用v-model修改符</h2>
    <Child2 :value="money" @input="money = $event" ></Child2 >
    <Child2 v-model="money" ></Child2>
----------------------------------------------------------------------------

</div>


.sync子组件----------------------------------------------------------------------
          <template>
          <div style="background: #ccc; height: 50px;">
            <span>小明每次花100</span>
            <button @click="$emit('update:money',money - 100)" >花钱</button>
            爸爸还剩 {{money}}</div>
        </template>

        <script type="text/ecmascript-6">
          export default {
            name: 'Child',
            props:['money'],
          }
        </script>


v-model子组件----------------------------------------------------------------------

        <template>
          <div style="background: #ccc; height: 50px;">
            <span>小明每次花100</span>
            <button @click="$emit('input',value-100)" >花钱</button>
            爸爸还剩 {{value}}</div>
        </template>

        <script type="text/ecmascript-6">
          export default {
            name: 'Child2',
            props:['value']
          }
        </script>

九、 $attrs 与 $listeners

  • 使用场景: -----父子通信
    $attrs:组件实例的属性,可以获取到父亲传递的props数据(前提子组件没有通过props接收)
    $listeners:组件实例的属性,可以获取到父亲传递自定义事件(对象形式呈现)
  <div>
    <h2>自定义带Hover提示的按钮</h2>
    <!-- 二次封装的HintButton按钮的时候,把人家el-button需要的数据传递过去 -->
     <HintButton type="success" icon="el-icon-plus" title="我是中国人" @click="handler"/>
  </div>
下面是对el-button的二次封装
 <a :title="title">
   <el-button v-bind="$attrs" v-on="$listeners">添加</el-button>
 </a>
export default {
  name: "",
  props:['title'],
  mounted(){
    //this.$attrs:可以获取到父亲传递的数据【props】
    //this.$attrs是可以获取父亲传递的props数据,如果子组件通过
    //props:[],接受,this.$attrs属性是获取不到的
    console.log(this.$attrs);
    console.log(this.$listeners);
  }
};
十、 $children$parent
  • 使用场景: -----父子通信
ref:可以在父组件内部获取子组件—实现父子通信,可以给所有的子组件打标识,从而拿到某个子组件中的数据
$children:可以在父组件内部获取全部的子组件【返回数组】 配合ref使用,可以一次性拿到所有子组件中的数据
$parent:可以在子组件内部获取唯一的父组件【返回组件实例】
下面是$ref$children的使用
 <h2>爸爸有存款: {{ money }}</h2>
  <button @click="JieQianFromXM(100)">找小明借钱100</button>

   <Son ref="xm" /> //儿组件
   <Daughter ref="xh"/> //子组件
   
    //爸爸找儿子借钱
    JieQianFromXM(money) {
      this.money += money;//爸爸组件的钱累加100
      this.$refs.xm.money -= money; //小明的钱累减100
    },
    //找所有的孩子们借钱
    JieQianAll(money){
      this.money += 2*money;
      this.$children.forEach(item=>item.money-=money);
      //不建议用枚举获取子组件:因为没办法确定到底是那个子组件
      // this.$children[0].money -=money;

    },

-----此处省略某些代码
  data() {
    return {
      money: 1000,
    };
  },

Vue3组件通信方式

一、props

  • 使用场景:[父子通信]

父组件 Father.vue

<template>
 	<!--通过v-bind给子组件传值 -->
	<Son :money="info.money" :car="info.car">
    </Son>
</template>
<script setup>
	import { reactive } from 'vue';
	import Son from '@/components/Son.vue';
	const info=reactive({
		money: 10,
	    car: '兰博基尼'
	  });
</script>

子组件 Son.vue

<template>
	<section>
  		<div>我是儿子,爸爸给了我{{money}}元钱,给我买了一辆{{car}}的车</div>
	</section>
</template>
<script setup>
	const props = defineProps({
		money: Number,
		car: String,
	});
    // 对象形式声明 props
	// 等价于以字符串数组声明 props
	//const props = defineProps(['title', 'info', 'author']);
    ...
	// 在setup中使用时则直接 props.money
    const myMoney= props.money;
</script>
<style></style>

二、pina

  • 使用场景:[任意组件间通信]
  • 安装: npm install pinpa
  • 引入
import {createPinia} from 'pinia'          //main.js导入
createApp(App).use(createPinia()).mount('#app')  //createPinia()得加上括号

三:、$ref + defineExpose

  • 使用场景:[父子组件]
  • defineExpose : 组件向外暴露自身的属性和方法, 实现子向父传递
  • $refs: 在 vue3 中,由于在 setup 中无法访问到 this, 不能通过this.$refs.xxx 获取, 那么为了能够使用 $refs,我们需要借助一个方法:getCurrentInstance()。该对象返回当前的实例对象,实现父向子传递

父组件 Father.vue

<template>
    <div>
        <Child ref="child"></Child>
        <button @click="findMyChild">寻找我的孩子</button>
    </div>
</template>
<script setup>
import Child from './components/Child.vue';
import {  getCurrentInstance} from 'vue'
const currentInstance = getCurrentInstance()

console.log(currentInstance);
function findMyChild() {
  // 拿到子组件的方法
  currentInstance.ctx.$refs.child.tellFatherMyPositon()//两种写法都可以
  // currentInstance.refs.child.tellFatherMyPositon()

  // 拿到子组件的数据
  console.log( currentInstance.ctx.$refs.child.position());

}
</script>

子组件 Son.vue

<template>
    <div>
        孩子的位置: {{position}}
    </div>
</template>

<script setup>
import { ref , defineExpose } from 'vue'
let position= ref('我在北边的小卖铺里').value
let tellFatherMyPositon = function () {
    alert(position)
}

//向外暴露指定属性
defineExpose({
    position,
    tellFatherMyPositon
})
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值