# Vue组件通信的方式

  • $root / $parent / $children
  • $refs
  • provide / inject
  • $attrs / $listeners
  • props / $emit
  • vuex
  • EventBus
  • v-model

# $root

<template>
  <div>
    <!--
      小型应用中可以在 vue 根实例里存储共享数据
      组件中可以通过 $root 访问根实例
    -->
    $root.title:{{ $root.title }}
    <br>
    <button @click="$root.title = 'Hello $root'">改变 title</button>
  </div>
</template>

# $parent/$children

指定已创建的实例之父实例,在两者之间建立父子关系。子实例可以用 this.$parent 访问父实例,子实例被推入父实例的 $children 数组中。

节制地使用 $parent$children - 它们的主要目的是作为访问组件的应急方法。更推荐用 props 和 events 实现父子组件通信

<!-- parent.vue -->
<template>
  <div class="parent">
    parent
    <child></child>
  </div>
</template>

<script>
export default {
  components: {
    child
  },
  data () {
    return {
      title: '获取父组件实例'
    }
  },
  methods: {
    handle () {
      console.log(this.title)
    }
  }
}
</script>

<!-- children.vue -->
<template>
  <div class="child">
    child<br>
    $parent.title:{{ $parent.title }}<br>
    <button @click="$parent.handle">获取 $parent.title</button>
    <button @click="$parent.title = 'Hello $parent.title'">改变 $parent.title</button>
  
    <grandson></grandson>
  </div>
</template>

# $refs

<!-- parent.vue -->
<template>
  <div>
    <myinput ref="mytxt"></myinput>
    <button @click="focus">获取焦点</button>
  </div>
</template>

<script>
export default {
  components: {
    myinput
  },
  methods: {
    focus () {
      this.$refs.mytxt.focus() // 调用的是子组件的 focus 方法
      this.$refs.mytxt.value = 'hello'
    }
  }
}
</script>

<!-- myinput.vue -->
<template>
  <div>
    <input v-model="value" type="text" ref="txt">
  </div>
</template>

<script>
export default {
  data () {
    return {
      value: 'default'
    }
  },
  methods: {
    focus () {
      this.$refs.txt.focus() // this.$refs.txt 获取 DOM 对象,focus 方法获取焦点
    }
  }
}
</script>

# provide/inject

provideinject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。

提示:provideinject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。并且在子组件中不可修改

// 父级组件提供 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}

// 子组件注入 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

# $attrs / $listeners

# props / $emit

父组件通过props向子组件传递数据,子组件通过$emit触发父组件的方法,从而实现子到父的通信

# 父组件传子组件:通过props

<!--父组件-->
<template>
    <div>我是父组件,我的值是{{ msg }}
        <child :logo="msg"></child>
    </div>
</template>

<script>
import child from './child'
export default {
  data () {
    return {
      msg: '123'
    }
  },
  components: {
    child
  }
}
</script>


<!--子组件-->
<template>
    <div>
      <div>我是子组件,这是父组件的值:{{ logo }}</div>
    </div>
</template>

<script>
export default {
  name: 'child',
  data () {
    return {
    }
  },
  props: ['logo']
}
</script>

<!--
	我是父组件,我的值是123
	我是子组件,这是父组件的值:123
-->

# 子组件传父组件:$emit

  • 输入框的onchange事件,要在 input 失去焦点的时候才会触发;
  • oninput 事件在用户输入时触发,它是在元素值发生变化时立即触发;
<!--父组件-->
<template>
    <div>
        <child @transfer="get"></child>
        <div>我是父组件:这是子组件传来的值:{{ msg }}</div>
    </div>

</template>

<script>
import child from './child'
export default {
  data () {
    return {
      msg: ''
    }
  },
  components: {
    child
  },
  methods: {
    get (msg) {
      this.msg = msg
    }
  }
}
</script>

<!--子组件-->
<template>
    <div>
        <input type="text" v-model="msg" @input="set">
    </div>
</template>

<script>
export default {
  name: 'child',
  data () {
    return {
      msg: ''
    }
  },
  methods: {
    set: function () {
      this.$emit('transfer', this.msg)
      console.log(1)
    }
  }
}
</script>

<!--
    23131 //输入框
    我是父组件:这是子组件传来的值:23131
-->

# vuex

vuex (opens new window)

# event bus

一个完整的eventBus主要分为三个部分:eventBus组件、注册事件($on)、发送事件($emit)

# v-model

父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this.$emit(‘input',val)自动修改v-model绑定的值

Vue.component('child',{
    props:{
      value:String, //v-model会自动传递一个字段为value的prop属性
    },
    data(){
      return {
        mymessage:this.value
      }
    },
    methods:{
      changeValue(){
        this.$emit('input',this.mymessage);//通过如此调用可以改变父组件上v-model绑定的值
      }
    },
    template:`
      <div>
        <input type="text" v-model="mymessage" @change="changeValue">
      </div>
  })


  Vue.component('parent',{
    template:`
      <div>
        <p>this is parent compoent!</p>
        <p>{{message}}</p>
        <child v-model="message"></child>
      </div>
    `,
    data(){
      return {
        message:'hello'
      }
    }
  })
最后更新时间: 9/3/2021, 7:07:07 PM