切图妞

vuePress-theme-reco 切图妞    2020 - 2021
切图妞 切图妞
前端知识梳理
  • Vue
  • 浏览器 & 网络
  • HTML & CSS
  • Web安全
  • 算法
文章分类
  • 前端小麻烦
  • 配置乐园
  • 实战不完全手册
  • 手撕源码
宝藏女孩
  • 模板仓
  • 项目简介
  • GitHub
  • Segmentfault
  • CSDN
时间轴
author-avatar

切图妞

19

Article

18

Tag

前端知识梳理
  • Vue
  • 浏览器 & 网络
  • HTML & CSS
  • Web安全
  • 算法
文章分类
  • 前端小麻烦
  • 配置乐园
  • 实战不完全手册
  • 手撕源码
宝藏女孩
  • 模板仓
  • 项目简介
  • GitHub
  • Segmentfault
  • CSDN
时间轴
  • 浏览器 & 网络

  • HTML & CSS

  • JS基础

  • 算法(整理中)

  • Vue基础

    • Vue基础
    • v-model
    • Vue传值
  • Web安全

Vue传值

vuePress-theme-reco 切图妞    2020 - 2021

Vue传值

切图妞 2020-02-03 VueVue基础

# 常用传值

父子传值,兄弟传值,祖孙传值

# 父子传值

# 父组件 => 子组件

  • 属性props

    将父组件的数据通过props传给子组件。

  // parent

  <common-c :num="appleNum" />

  // child

  props: {
    num: {
      type: Number,
      default: 0
    }
  },
1
2
3
4
5
6
7
8
9
10
11
12
  • ref

    通过引用ref拿到子组件内部的数据或者方法

  // parent

  <common-c ref="commonC"  :num="appleNum" @addNumber="addNumber"/>

  this.$refs.commonC.handleToggle()

1
2
3
4
5
6

# 子组件 => 父组件

使用$emit触发自定义事件

// parent

  <common-c @addNumber="addNumber"/>

// child

<el-button @click="addNumber">加苹果</el-button>

addNumber() {
  this.$emit('addNumber')
}

1
2
3
4
5
6
7
8
9
10
11
12

# 兄弟传值

常用方法是以父组件作为中转站,子组件1$emit给父组件,父组件$on给子组件2

// child1

reduceApple() {
  this.$emit('reduceApple')
}

// parent

<common-c1 @reduceApple="reduceApple"/> // child1
<common-c  :num="appleNum"/> // child2

reduceApple() {
  this.appleNum--
}

// child2

props: {
  num: {
    type: Number,
    default: 0
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 祖孙传值

https://cn.vuejs.org/v2/api/#vm-attrs

$attrs 可以获取父作用域传入的值(不包括 props 中的), $listeners 相当于父作用域的事件监听器,从而实现祖孙之间的数据通信。

// 第一代

<common-c2 :info="info" @getName="getName"/>

// 第二代

<Grandson  v-bind="$attrs" v-on="$listeners"/>

// 第三代

<h3>第一代传过来的信息是:{{this.$attrs.info}}</h3>
<el-button @click="getName">名字传给第一代</el-button>

getName() {
  this.$emit('getName','切图妞')
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  1. 将组件的所有props传递给子组件

<child v-bind="$props" />

利用v-if可在http请求返回后再显示。这样子组件可以返回的http请求数据。

# EventBus通讯

EventBus 又称为事件总线。在 Vue 中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件。工作原理是发布/订阅方法,通常称为 Pub/Sub

# 常用

定义一个vue对象作为eventBus,让其代为订阅发布事件,AB页面通过EventBus文件,分别调用Bus事件触发和监听来实现通信和参数传递。

  • EventBus
import Vue from 'vue'
export const EventBus = new Vue()
1
2
  • 发送消息

EventBus.$emit(channel: string, callback(payload1,…))

  // A页面

  <
  el - button @click = "sendMsg" > 发送消息给B < /el-button>

  import {
      EventBus
  } from "./event-bus.js"

  sendMsg() {
      EventBus.$emit('sendMsg', '我是来自A的消息')
  }
1
2
3
4
5
6
7
8
9
10
11
12
  • 监听接收消息

EventBus.$on(channel: string, callback(payload1,…))

  // B页面

  mounted() {
      EventBus.$on('sendMsg', msg => {
          this.msg = msg
      })
  },
1
2
3
4
5
6
7

# 全局

  • 创建全部EventBus
    // main.js

    Vue.prototype.$bus = new Vue()
1
2
3

发布订阅模式相当于

  var EventBus = new Vue();

  Object.defineProperties(Vue.prototype, {
      $bus: {
          get: function() {
              return EventBus
          }
      }
  })
1
2
3
4
5
6
7
8
9
  • 使用
  this.$bus.$emit('name', {});

  this.$bus.$on('name', ($event) => {})

  this.$bus.$off('name')
1
2
3
4
5

# 问题

  • 多次触发

    B页面接收事件的组件没挂载之前仍会接受 $emit,在排队等待dom挂载后集中接收之前发出的全部事件,导致多次触发。 处理方法:在生命周期的beforeDestroy中,将事件销毁。

  beforeDestroy() {
      EventBus.$off('sendMsg')
  }
1
2
3

https://github.com/vuejs/vue/issues/3399

  • 路由跳转情况下未生效

    vue-router切换的时候,会先加载新的组件,当新的组件渲染好但是还没mount的时候,销毁旧组件,然后再挂载新组件,也就是说当B页面的生命周期进行到beforeMount的时候,下一步走到的就是A页面的beforeDestory或者destroyed方法里面。

    Dom渲染完毕后再处理回调

  this.$nextTick(() => {

  })
1
2
3
  • 复杂情况难维护

eventbus 在复杂情况下使用不太方便,若使用不慎易造成难以维护的灾难,需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。

https://blog.csdn.net/i168wintop/article/details/95107935