WuShaolin

悟已往之不谏,知来者之可追!

0%

Vue的组件间通信

组件是插槽式的,例如某个页面有两个组件,其中搜索作为其中一个组件,当它作为组件的时候,它作为子组件的时候需要把参数通过属性的方式传递进来,通知父组件的时候通过触发事件来进行通信。

以上是组件化的简单描述,与模块化的组要区别在于组件化课深度定制不同的属性,借助父组件的参数值。

那么问题来了,组件间如何进行通信呢?

父子组件通信

最经典的通信方式就是:父组件与子组件之间进行通信。

组件的基本写法

Vue.component('shareLink', {
  data() {},
  props: ['shareLink'],
  methods: {},
  template: ``,
})

上述的代码就创建了一个名为shareLink的组件,并且可传递一个名为shareLink的参数值。

但是注意:

  • HTML的规范规定,标签名与属性名都必须是小写字母,所以上述的组件在HTML代码里面默认写成share-link
  • 组件里面的data必须是函数,而不是app.js中的对象写法。

具体一点的写法是:

Vue.component('share', {
  props: ['shareLink'],
  template: `
    <div class="share" v-cloak>
      <h2>
        请将下面链接分享给面试官
      </h2>
      <div>
        <textarea readonly>{{shareLink}}</textarea>
      </div>
    </div>
  `,
})

其中props中是参数的名字,接受别的组件传递的信息。

<share v-bind:share-link="shareLink" v-show="shareVisible"></share>
//在html的页面中这样写

v-bind将参数的名字绑定上,值是通过app.js获得的shareLink

简单的对应规则

v-bind :share-link = “shareLink”
对应的 props: [‘shareLink’] app.js中{shareLink: ‘ ‘}

需求分析

  1. 子组件想改父组件的data。例如登录后的关闭按钮无用的例子。
<login v-show="loginVisible"></login> 
//这是父组件的写法,loginVisible是父组件的变量,很明显儿子无法修改爸爸的数据啊
  1. 但是儿子特别像修改爸爸的数据
  2. 那么唯一的解决方案就是叫爸爸去修改

解决方案:

  1. 子组件通过事件告诉爸爸,我需要你做一些改变。

@click="$emit('close')"

  • 注意:在methods中需要使用this.$emit(''),但是在@click中不需要用this
  1. 那么爸爸根据儿子的需要做出如下改变

<login v-show="loginVisible" @close="loginVisible = false">

@close等同于v-on:close

父子组件通信的demo链接

父子组件通信图示

爷孙组件间的通信

需求分析

  1. 爷爷看不到孙子在哪里
  2. 但是呢,爷爷就是想控制孙子
  3. 所以呢,借助爸爸来间接的去控制孙子就好啦

本质上Vue只有父子间通信,爷孙间通信需要使用两次父子间通信

爷爷只控制孙子

该版本中爷爷只能控制孙子的显示,但是目前孙子无法反向操作爷爷。

demo的链接

孙子逐级冒泡通知爷爷

孙子先冒泡到爸爸那里,使用

Vue.component('child', {
  props: ['visible'],
  template: `
    <div>
      我是儿子
      <grand-child v-show="visible" @close="$emit('close')"></grand-child>
    </div>
  `
})
Vue.component('grandChild', {
  template: `
    <div>
      我是孙子
      <button @click="$emit('close')">关闭</button>
    </div>
  `
})

爷爷那里就可以监听到孙子的动作了

<body>
  <div id="app">
    <p>{{ message }}</p>
    <button @click="xxx = true">打开</button>
    <hr>
    <child :visible="xxx" @close="log"></child>
  </div> 

</body>

demo的链接

爷孙间的通信图示