Vue 组件通信方式

270 阅读1分钟

父子组件通信--props/$emit

(1)父组件向子组件传值

方法:父组件通过绑定属性向子组件传递数据,子组件通过 props 属性得到相应的数据

    <div id="app">
        <!-- v-bind绑定的值就是props要接受的值 -->
        <com :parentmsg="msg"></com>  
    </div>

    <template id="tpl">
        <div>
            <h1>子组件通过props接收的数据--{{parentmsg}}</h1>
        </div>
    </template>

    <script>
    var vm = new Vue({
        el: "#app",
        data: {
            msg: "来自父组件的消息"
        },
        components: {
           // 这里注册一个子组件com
            com: {
               //props存放父组件传过来的数据,props只读,而data可读可写
                props: ['parentmsg'],
                template: '#tpl'
            }
        }

    })
    </script>

(2)子组件向父组件传值

方法:子组件通过 $emit 事件向父组件发送消息,将自己的数据作为参数传递给父组件

  <div id="app">
    <com @function="show"></com>
  </div>

  <template id="tpl">
     <div>
	<input type="button" @click="sonclick">
     </div>
  </template>

  <script>
  var vm = new Vue({
	el:"#app",
	methods:{
		show (data){
                console.log(data)  //data就是子组件的数据
		}
	},
	components:{
		com:{
		   template:'#tpl',
		   data (){
                      return {
                        sonmsg:"来自子组件的数据"
                      }
		   },
		   methods:{
		    sonclick (){
		    //子组件通过调用事件将自己的数据作为参数传递给父组件
			this.$emit('function',this.sonmsg)
		    }
		   }
        	 }
        }
  })

   </script>

隔代组件通信--provide / inject

方法:父组件使用 provide 向下提供数据,其下所有子组件都可以通过inject注入

  • provide 是一个对象或是返回一个对象的函数
  • inject 是一个字符串数组或一个对象

实例:比如vue刷新页面

App.vue(根组件,或者这里理解为父组件)

<template>
    <div id="app">
    	<router-view v-if="isRouterAlive"></router-view>
	</div>
</template>
<script>
    export default {
        name: 'App',
        provide () {    //父组件中通过provide来提供变量,在子组件中通过inject来注入变量。                                             
            return {
                reload: this.reload                                              
            }
        },
        data() {
            return{
                isRouterAlive: true                    //控制视图是否显示的变量
            }
        },
        methods: {
            reload () {
                this.isRouterAlive = false             //先关闭
                this.$nextTick(() => {
                    this.isRouterAlive = true         //再打开
                }) 
            }
        },
    }
</script>

需要刷新页面的子组件

export default {
    inject:['reload'],                                 //注入父组件(App.vue)里的reload方法
    data () {
        return {}
    }
}

父子组件通信-- ref 与 $parent / $children

简单来说:父组件使用 $children 访问子组件,子组件使用$parent访问父组件

父组件

<template>
  <div id="app">
    <h1>父组件</h1>
    <com></com>
  </div>
</template>
<script>
//导入子组件
import com from './childrencom.vue'

export default {
  name: 'parentcom',
  data() {
    return {
      'parentMsg': '来自父组件的数据'
    }
  },
  components: {
      com       //注册子组件
  },
  mounted() {
    // $children获取父组件下的所有子组件实例,返回的是一个数组
    // 当只有一个子组件时,使用[0]获取
    // 有多个子组件时 $children 并不保证顺序,也不是响应式的
    console.log(this.$children[0].childMsg) // 来自子组件的数据
  }
};
</script>

子组件(childrencom.vue)

<template>
  <div id="children">
    <h1>我是子组件</h1>
  </div>
</template>
<script>
export default {
  name: 'childrencom',
  data() {
    return {
      childrenMsg: '来自子组件的数据'
    }
  },
  created() {
    console.log(this.$parent.parentMsg) //parentMsg为 '来自父组件的数据'
  }
}
</script>

ref

  • 给子组件标签上添加ref属性
  • 在父组件中可以使用 this.$refs 来获取,返回的是一个对象,属性值是子组件

父组件

<template>
  <div id="app">
    <com ref="children"/>  <!--给子组件标签上添加ref属性-->
    <button @click="getChildrenMsg">获取子组件中的childrenMsg</button>
  </div>
</template>

<script>
import com from "./childrencom.vue"

export default {
  methods: {
    getChildrenMsg() {
      console.log(this.$refs.children.childrenMsg)  //来自子组件的数据
    }
  },
  components: {
     com
  }
}
</script>

子组件(childrencom.vue)

<template>
  <div id="children">
    <h1>我是子组件</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      childrenMsg: "来自子组件的数据"
    }
  }
}
</script>

父子、隔代、兄弟组件通信-- Vuex

下面两个通信方式没用过,研究下先

父子、隔代、兄弟组件通信-- $emit / $on

隔代组件通信-- $attrs/$listeners