头图

本文整理总结了开发中使用频率比较多的vue组件通信方式,相信无论是面试还是实际开发,总会对你有所帮助。

Props & $emit

这是使用频率最多、最基础,必须要掌握的用法,使用非常简单,用一个helloworld组件示例。

<div id="app">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}

数据从父级传递到子级,子级组件读取使用,子级不推荐直接在内部修改props(会导致渲染异常、监听紊乱),而应该通知父组件去更新msg。

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <button @click="resetMsg">i want change msg</button>
  </div>
</template>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  methods: {
    resetMsg () {
      this.$emit('update');
    }
  }
}

父组件:

<template>
  <div id="app">
    <HelloWorld :msg="msg" @update="update" />
  </div>
</template>
methods: {
    update () {
      this.msg = "Welcome to my Blog";
    }
  }

$attrs & $listenners

父组件不变,子组件用过$attrs在模板和JS中使用父组件提供的数据,使用$listenners执行父组件内方法(也可以用于跨级组件)。

<template>
  <div class="hello">
    <h1>{{$attrs.msg}}</h1>
    <button @click="resetMsg">i want change msg</button>
  </div>
</template>
export default {
  name: 'HelloWorld',
  methods: {
    resetMsg () {
      this.$listeners.update()
      // this.$emit('update');
    }
  }
}

$children & $parent

父组件内使用 $children 可以访问子组件列表,根据所在序号找到指定组件,获取数据和方法。

<template>
  <div id="app">
    <HelloWorld />
    <button @click="showMsg">show children msg</button>
    <h1>{{ msg }}</h1>
  </div>
</template>
showMsg () {
    console.log(this.$children)
    this.msg = this.$children[0].msg;
 }

使用$parent获取父组件实例,也就可以直接调用方法和获取数据了,注意:此实例获取方式并非响应式,如果父/子一侧数据变化,之前获取的数据不会刷新!

<template>
  <div class="hello">
    <h1>{{msg}}</h1>
    <button @click="resetMsg">i want change msg</button>
  </div>
</template>
resetMsg () {
    console.log(this.$parent);
    this.msg = "Welcome to my Blog";
}

provider & inject

在提供数据的组件中标明提供的数据和方法,在子孙组件中inject所需数据和方法。

<template>
  <div id="app">
    <HelloWorld />
  </div>
</template>
provide: function () {
    return {
      msg: () => this.msg,
      user: this.user,
      reset: this.updateNickName,
      resetMsg: this.updateMsg
    }
  },
  data () {
    return {
      msg: 'Welcome to Your Vue.js App',
      user: {
        nickName: 'Jack Chen'
      },
    }
  },
  methods: {
    updateNickName () {
      this.user.nickName = "Jet Li";
    },
    updateMsg () {
      this.msg = "Welcome to Your Vue.js Blog";
    }
  }

子/孙级组件:

<template>
  <div class="hello">
    <h1>{{_msg}} {{ user.nickName }}</h1>
    <button @click="resetMsg">reset msg</button>
    <button @click="reset">reset nickName</button>
  </div>
</template>
inject: ['msg','user', 'reset', 'resetMsg'],
  computed: {
    _msg () {
      return this.msg();
    }
  },

同$children和$parent一样,此方式并非百分百响应式,对于基本类型数据,想要它保持响应式,需要转换为一个函数,返回此变量,在需要使用的组件中,执行方法或者使用计算属性方式。

ref(s)

这种方式更明显地具有父级访问子级组件的特征,不能纯粹算互相通信,只能作为特定场景的使用方案之一。

<template>
  <div id="app">
    <HelloWorld ref="hellowd"/>
    <button @click="getMsg">get msg</button>
    <h2>{{ msg }}</h2>
  </div>
</template>
getMsg () {
  const hellowd = this.$refs['hellowd'];
  this.msg = hellowd.msg;
},
updateMsg () {
  const hellowd = this.$refs['hellowd'];
  hellowd.resetMsg();
}

通过操作发现,只要是通过实例获取的,均非响应式

async & update

<template>
  <div id="app">
    <HelloWorld :msg.sync="msg"/>
    <h2>{{ msg }}</h2>
  </div>
</template>
<template>
  <div class="hello">
    <h1>{{msg}}</h1>
    <button @click="updateMsg">update msg</button>
  </div>
</template>
updateMsg () {
  this.$emit('update:msg', "Welcome to Your Vue.js Blog");
}

这种更新是响应式的,父组件有引用的地方都会同步更新。

其它方式

  • Vuex 数据管理Store
  • eventBus 挂载在Vue原型上,使用on监听,emit传播事件
  • slot 插槽,主要用于模板处理中
  • 本地缓存
  • 自己实现一个Store

何弃疗
106 声望7 粉丝

前端路上摸爬滚打;野路子前端debug