面试之Vue2组件通信

173 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情

vue2.0组件通信方式有哪些?

父子组件通信

props+自定义事件

this.$emit('需要触发的自定义事件', 需要传递的参数)

props: 父组件以属性形式向子组件传值,子组件用props接收来自父组件的值

<Child :nameFather="name"></Child>

$emit子组件向父组件传值,父组件绑定子组件传递的事件方法,注意$emit('自定义方法')要和父组件绑定的事件名一样。

<Child :nameFather="name" @newData="newName"></Child>
// 注意:newData才是父组件绑定子组件传递的事件 newName是父组件中用来接收子组件参数并赋值的方法
需要在子组件中写明 this.$emit('newData',传递的参数)

send.gif

父组件 Father.vue

<template>
    <div>
        <input type="text" v-model="name">
        <!--子组件传递过来的值由自定义事件方法接收-->
        <Child :nameFather="name" @newData="newName"></Child>
    </div>
</template>

<script>
import Child from '@/views/Child.vue'
export default {
  data () {
    return {
      name: '我是父'
    }
  },
  methods: {
    // value是自定义方法接收子组件传递的参数
    newName (value) {
      this.name = value
    }
  },
  components: {
    Child
  }
}
</script>

子组件 Child.vue

<template>
    <div>
        <p @click="change">Child组件:{{nameFather}}</p>
    </div>
</template>

<script>
export default {
  // 接收属性nameFather
  props: {
    nameFather: String
  },
  methods: {
    change () {
      // 触发父组件中的自定义事件newData ,
      this.$emit('newData', '这是子')
    }
  }
}
</script>

props+sync修饰符

this.$emit('update:父组件需要更新的自定义属性','更新后的属性值')

props+自定义事件props+sync修饰符的结果是一样的,但是个人觉得自定义事件要多写很多代码,推荐后者

send2.gif 父组件 Father.vue

<template>
    <div>
        <input type="text" v-model="name">
        <Child :nameFather.sync="name"></Child>
    </div>
</template>

<script>
import Child from '@/views/Child.vue'
export default {
  data () {
    return {
      name: '我是父组件'
    }
  },
  components: {
    Child
  }
}
</script>

子组件 Child.vue

<template>
    <div>
        <p @click="change">Child组件:{{nameFather}}</p>
    </div>
</template>

<script>
export default {
  // 接收属性nameFather
  props: {
    nameFather: String
  },
  methods: {
    change () {
      this.$emit('update:nameFather', '这是子组件')
    }
  }
}
</script>

props+v-model

现在子组件里面写明modelmodel里面要写明propevent,prop是自定义属性,event是自定义事件,修改用this.$emit('自定义事件名','要传递的参数')

send3.gif 父组件 Father.vue

<template>
    <div>
        <input type="text" v-model="name">
        <Child v-model="name"></Child>
    </div>
</template>

<script>
import Child from '@/views/Child.vue'
export default {
  data () {
    return {
      name: '我是父组件'
    }
  }
  components: {
    Child
  }
}
</script>

子组件 Child.vue

<template>
    <div>
        <p @click="change">Child组件:{{nameFather}}</p>
    </div>
</template>

<script>
export default {
  // 声明model
  model: {
    prop: 'nameFather', // props的属性名
    event: 'nameChange' // model绑定的事件名
  },

  props: {
    nameFather: String
  },
  methods: {
    change () {
      this.$emit('nameChange', '这是子组件v-model')
    }
  }
}
</script>

$parent

$parent提供给子组件访问父组件的实例的功能

this.$parent.父组件中的方法(需要传入的参数)

这个方法适用于子组件调用父组件方法

send4.gif 父组件 Father.vue

<template>
    <div>
        <input type="text" v-model="name">
        <Child :nameFather="name"></Child>
    </div>
</template>

<script>
import Child from '@/views/Child.vue'
export default {
  data () {
    return {
      name: '我是父组件'
    }
  },
  methods: {
    fatherMethod () {
      this.name = '还在父组件哦'
    }
  },
  components: {
    Child
  }
}
</script>

子组件 Child.vue

<template>
    <div>
        <p @click="childMethod">Child组件:{{nameFather}}</p>
    </div>
</template>

<script>
export default {
  props: {
    nameFather: String
  },
  methods: {
    childMethod () {
      this.$parent.fatherMethod()
    }
  }
}
</script>

$ref

ref是为元素或子组件赋予一个ID引用,通过this.$ref.refName来访问元素或子组件的实例。

this.$ref.子组件的refName.子组件方法

如何使用ref:

  1. 在子组件标签上添加 ref 属性
  2. 然后在方法中通过 this.$refs 找到绑定 ref 的属性
  3. 调用该子组件内的方法即可。
<Child ref="child" :nameFather.sync="name"></Child>

父组件 Father.vue

<template>
    <div>
        <input type="text" v-model="name">
        <Child ref="child" :nameFather.sync="name"></Child>
        <button @click="changeByRef">点一下,使用ref</button>
    </div>
</template>

<script>
import Child from '@/views/Child.vue'
export default {
  data () {
    return {
      name: '我是父组件'
    }
  },
  methods: {
    changeByRef () {
      this.$refs.child.useRef()
    }
  },
  components: {
    Child
  }
}
</script>

子组件 Child.vue

<template>
    <div>
        <p @click="useRef">Child组件:{{nameFather}}</p>
    </div>
</template>

<script>
export default {
  props: {
    nameFather: String
  },
  methods: {
    useRef () {
      console.log('ref')
      this.$emit('update:nameFather', '这是子ref')
    }
  }
}
</script>

send5.gif

$children

关于$children,Vue2官网是这么说的

当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。 如果你发现自己正在尝试使用 $children 来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源。

我自己在学习和开发过程中没有用过也不是很了解,欢迎大家的评论区交流讨论,我来学习一下~

非父子组件通信

eventBus

创建一个空的vue实例

// Bus.vue
import Vue from 'vue'
const bus = new Vue()
export default bus

注册为全局实例

// main.js
import bus from '@/Bus.vue'
Vue.prototype.$bus = bus

使用:

  1. 提交 this.$bus.emit('自定义事件名',参数)
  2. 接收 this.$bus.on('自定义事件名',参数)
  3. 销毁 this.$bus.off('自定义事件名')

注意:只要保证事件名一致,就可以在非父子组件间进行通信