How to communicate between Vue components?

Table of contents

1. Component introduction

1. Define components

2. Register components

2.1 Global Registration

 2.2 Partial registration

3. Use components

2. Component communication method

1. The parent component passes the value to the child component

2. The child component passes the value to the parent component

3. Value transfer between sibling components

4. Passing values ​​between ancestor components and descendant components

5. About one-way data flow 


1. Component introduction

Components are one of the most powerful features of Vue.js. Components can extend HTML elements, encapsulating reusable code. At a high level, components are custom elements to which Vue's compiler adds special functionality. In some cases, components can also appear as native HTML elements extended with the is attribute. When a component is registered, various parameters need to be specified for the component.

Because components are reusable Vue instances, they receive the same options as new Vue, such as data, computed, watch, methods, and lifecycle hooks. The only exceptions are options specific to the root instance like el.

Component Features:

  • Components can be reused any number of times
  • The data of the component must be a function to ensure that each instance can maintain an independent copy of the returned object, that is, any change in one component will not affect other components

1. Define components

Components have the same options as new Vue, such as data, computed, watch, methods and life cycle hooks, etc., but components do not have el options, but use template

let myA={
    template:`
		<div>
			{
   
   {msgA}}
		</div>
	`,
	data(){
		return {
			msgA:'我是子组件'
		}
	}
};

2. Register components

Before using the component, you need to register the component first. The ways to register the component are: global registration and local registration

2.1 Global Registration

Use Vue.component('component name', component); for global registration, the components after global registration can be used in any component.

Vue.component('my-a',myA);

 2.2 Partial registration

Partially registered components can only be used in the current component, so we want to use the component in which component, and locally register the component in that component. We use the components configuration item for local registration.
For example, if we want to use the myA component in the myB component, then we need to partially register the myA component in the myB component:

let myA={
	template:`
		<div>
			{
   
   {msgA}}
		</div>
	`,
	data(){
		return {
			msgA:'我是子组件'
		}
	}
};
let myB={
	// 局部注册
	components:{
    //组件名: 组件
		'my-a':myA
    },
	template:`
		<div>B组件
			<my-a></my-a>
		</div>
	`
}

3. Use components

To use components, you only need to use html tags in the template, and the tag name is the component name:

<div id="app">
	<my-a></my-a>
	<my-b></my-b>
</div>

2. Component communication method

Component A uses component B in its template. They must communicate with each other: the parent component may send data to the child component, and the child component may inform the parent component of what happened inside it. In Vue, the relationship between parent and child components can be summarized as props are passed down and events are passed up. The parent component sends data to the child component through props, and the child component sends messages to the parent component through events.

1. The parent component passes the value to the child component

The way the parent component passes the value to the child component:
Step 1: Write the value to be passed in the label of the child component

Step 2: Use the props configuration item in the child component to receive the value passed by the parent component

<body>
	<div id="app">
		<!-- 父组件传值给子组件 -->
		<!-- 1.在子组件标签上 写入传入的值 -->
		<!-- 静态传参 不使用v-bind进行数据绑定,那么传递的就是'msg'字符串本身-->
		<!-- <my-a msg1="msg"></my-a> -->
		<!-- 动态传参 使用v-bind进行数据绑定,就可以传递任意类型的值-->
		<my-a :msg2="msg" :age="18" :obj="{name:'zhangsan'}" :stu='[1,2,3]'></my-a>
	</div>
	<script>
		let myA={
			// 子组件内使用props接收父组件传递的值
			props:['msg2','stu','age','obj'],
			template:`
				<div>
					我是子组件<br>
					{
   
   {msg2}}---{
   
   {typeof msg2}}<br>
                    {
   
   {stu}}---{
   
   {typeof stu}}<br>
                    {
   
   {age}}---{
   
   {typeof age}}<br>
                    {
   
   {obj}}---{
   
   {typeof obj}}
				</div>
			`
		};
		new Vue({
          // 局部注册组件
			components:{
				'my-a':myA
			},
			el:"#app",
			data:{
				msg:'我是父组件'
			}
		})
	</script>
</body>

In props, the child component can perform type verification on the passed value of the parent component. When the value passed in is not the type we want, an error will be reported. At this time, props need to be written in the form of an object:

Note: null and undefined can pass any type of validation

<body>
  <div id="app">
    <!-- 父组件传值给子组件 -->
    <!-- 1.在子组件标签上 写入传入的值 -->
    <!-- 静态传参 不使用v-bind进行数据绑定,那么传递的就是'msg'字符串本身-->
    <!-- <my-a msg1="msg"></my-a> -->
    <!-- 动态传参 使用v-bind进行数据绑定,就可以传递任意类型的值-->
    <my-a :msg2="msg" :age="18" :obj="{name:'zhangsan'}" :stu='[1,2,3]' :stu2="19"></my-a>
  </div>
  <script>
    let myA = {
      // 子组件内使用props接收父组件传递的值
      props: {
        age: {
          // 可以进行多个类型值的校验
          // 可以是Number,String,Boolean类型中的任意一个
          type: [Number, String, Boolean],
          // 自定义校验器规则  参数val表示传过来的值
          validator(val) {
            return val > 50
          }
        },
        msg2: String,
        obj: Object,
        stu2: String,
        stu: {
          type: Array,
          // 可以设置默认值,注意:需要写成函数的形式
          default () {
            return [4, 5, 6]
          },
          //要求必须传递
          required: true
        }
      },
      template: `
				<div>
					我是子组件<br>
					{
   
   {msg2}}---{
   
   {typeof msg2}}<br>
                    {
   
   {stu}}---{
   
   {typeof stu}}<br>
                    {
   
   {stu2}}---{
   
   {typeof stu2}}<br>
                    {
   
   {age}}---{
   
   {typeof age}}<br>
                    {
   
   {obj}}---{
   
   {typeof obj}}
				</div>
			`
    };
    new Vue({
      // 局部注册组件
      components: {
        'my-a': myA
      },
      el: "#app",
      data: {
        msg: '我是父组件'
      }
    })
  </script>
</body>


2. The child component passes the value to the parent component

The way the child component passes values ​​to the parent component:
Step 1: Use $emit('emit event name', passed parameters) in the child component to emit custom events and pass values ​​to the parent component

Step 2: Declare a custom event in the parent component to receive parameters

<body>
  <div id="app">
    <!-- 自定义事件 -->
    <my-a @my-event="handler"></my-a>
  </div>
  <script>
    let myA = {
      template: `
        <div>我是子组件
          <button @click='toSend'>子传值给父</button>
        </div>
      `,
      data() {
        return {
          subMsg: "我是子组件A,我要给父组件传值"
        }
      },
      methods: {
        toSend() {
          // 发射事件 $emit('发射事件的名称',传递的参数)
          this.$emit('my-event', this.subMsg)
        }
      }
    }
    new Vue({
      components: {
        'my-a': myA
      },
      el: '#app',
      data: {
        msg: "我是父组件",
      },
      methods: {
        handler(a) {
          console.log(a, '这是子组件的值');
        }
      }
    })
  </script>
</body>


 

3. Value transfer between sibling components

The way to pass values ​​between sibling components:

Using the event bus:
Step 1: Declare an event bus xxx.js, that is, create a new js file and export a Vue instance in the js file

Step 2: Introduce the event bus xxx.js, that is, import the xxx.js file in one of the sibling components, and use $emit() to emit data

Step 3: Import the xxx.js file in another sibling component, and use $on() to receive the data passed by the sibling component

We demonstrate in vue scaffolding:
 

After creating the scaffolding, we create two .vue files under the components folder under src, namely Header.vue and Footer.vue, and then introduce and use these two components in App.vue. At this time, Header.vue And Footer.vue are sibling components, and then create a new eventBus.js file under src, which is the event bus.

app.vue

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <Header/>
    <hr>
    <Footer/>
  </div>
</template>

<script>
import Header from './components/Header.vue'
import Footer from './components/Footer.vue'
export default {
  name: 'App',
  components: {
    Header,
    Footer,
  },
  data() {
    return {
      msg:'我是祖先组件'
    }
  },
  provide(){
    return {'msg':this.msg}
  }
}

</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

eventBus.js 

import Vue from 'vue';
export default new Vue();

Header.vue

<template>
  <div>
    {
   
   {msgH}}
    <button @click="handler">点击我传值给Footer</button>
  </div>
</template>

<script>
// 引入事件总线
import Bus from '../eventBus.js'
export default {
  data(){
    return {
      msgH:"头部组件",
      Footer:"这是兄弟组件Footer"
    }
  },
  methods:{
    handler(){
      // 兄弟组件传值 
	  // 1.兄弟组件使用$emit('发射事件',携带参数) 
      Bus.$emit('toFoot',this.Footer)
    }
  }
}
</script>

footer.view

<template>
  <div>
    {
   
   {msgF}}
  </div>
</template>

<script>
// 引入事件总线
import Bus from '../eventBus.js'
export default {
  data(){
    return {
      msgF:"底部组件",
    }
  },
  // 另一个兄弟组件使用 $on(自定义事件名称,(形参 用于接收兄弟组件传递过来的值)=>{}) 接收参数
  created(){
    Bus.$on('toFoot',(a)=>{
      console.log(a,"这是Footer传给我的值");
    })
  }
}
</script>

 

4. Passing values ​​between ancestor components and descendant components

The method of passing values ​​between ancestor components and descendant components:
the first step: ancestor components use the provide method to pass data

Step 2: Descendants use inject to inject data

We also demonstrate in the vue scaffolding:
create a new FooterChild.vue file under the components folder, then use the FooterChild.vue component in the Footer.vue component, and use the Footer.vue component in App.vue, then App.vue will be used as The ancestor component, FooterChild.vue is used as the descendant component.

app.vue

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <Header/>
    <hr>
    <Footer/>
    
  </div>
</template>

<script>
import Header from './components/Header.vue'
import Footer from './components/Footer.vue'
export default {
  name: 'App',
  components: {
    Header,
    Footer,
  },
  data(){
    return {
      msg: '我是祖先组件',
      a: 18
    }
  },
  // 祖先组件使用provide方法提供传递的数据
  provide(){
    return {
      "msg":this.msg,
      "a":this.a
    }
  }
}

</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

footer.view

<template>
  <div>
    {
   
   {msgF}}
    <FooterChild/>
  </div>
</template>

<script>
import FooterChild from './FooterChild.vue'
export default {
  components:{
    FooterChild
  },
  data(){
    return {
      msgF:"底部组件",
    }
  }
}
</script>

FooterChild.vue

<template>
  <div>
    {
   
   {msgC}}--{
   
   {msg}}--{
   
   {a}}
  </div>
</template>

<script>
export default {
  data(){
    return {
      msgC:"底部组件的子组件"
    }
  },
  // 注入数据
  inject:['msg','a']
}
</script>

5. About one-way data flow 

 One-way data flow means that data flows from the upper layer to the lower layer, that is to say, when the data of the parent component changes, the data of the child component will also change; while the data of the child component changes, the data of the parent component will not be affected Influence.

Guess you like

Origin blog.csdn.net/lq313131/article/details/127054416