Six methods of passing values between vue components

1. Passing values ​​between vue components

1. Pass value from parent component to child componentprops

Parent component code:

<template>
  <div>
    父组件:
    <input type="text" v-model="name">
    <br>
    <br>
    <!-- 引入子组件 -->
    <child :inputName="name"></child>
  </div>
</template>
<script>
  import child from './child'
  export default {
    components: {
      child
    },
    data () {
      return {
        name: ''
      }
    }
  }
</script>

Subcomponent code:

<template>
  <div>
    子组件:
    <span>{
   
   { inputName }}</span>
  </div>
</template>
<script>
  export default {
    // 接受父组件的值
    props: {
      inputName: String
    }
  }
</script>

The page shows:
insert image description here

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

Subcomponent code:

<template>
  <div>
    子组件:
    <span>{
   
   { childValue }}</span>
    <!-- 定义一个子组件传值的方法 -->
    <input type="button" value="点击触发" @click="childClick">
  </div>
</template>
<script>
  export default {
    data () {
      return {
        childValue: '我是子组件的数据'
      }
    },
    methods: {
      childClick () {
        // childByValue是在父组件on监听的方法
        // 第二个参数this.childValue是需要传的值
        this.$emit('childByValue', this.childValue)
      }
    }
  }
</script>

Parent component code:

<template>
  <div>
    父组件:
    <span>{
   
   {name}}</span>
    <br>
    <br>
    <!-- 引入子组件 定义一个on的方法(简写@)监听子组件的状态-->
    <child @childByValue="childByValue"></child>
  </div>
</template>
<script>
  import child from './child'
  export default {
    components: {
      child
    },
    data () {
      return {
        name: ''
      }
    },
    methods: {
      childByValue (childValue) {
        // childValue就是子组件传过来的值
        this.name = childValue
      }
    }
  }
</script>

The page shows:
insert image description here


The principle of passing values ​​between parent and child components: 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, as shown in the following figure:
insert image description here

3. $parent / $children && ref

  • ref: If used on a normal DOM element, the reference points to the DOM element; if used on a child component, the reference points to the component instance
  • $parent / $children: access to parent/child instances,
    both of which are to directly obtain component instances, and you can directly call component methods or access data after use.

refUse the code:

// component-a 子组件
export default
 {
  data () {   
    return
     {
         title: 'Vue.js'
     }
  },
  methods: {
    sayHello () {
      window.alert('Hello');
    }
  }
}
// 父组件
<template>
  <component-a ref="comA"></component-a>
</template>
 
<script>  
export default
 {
    mounted () {    
        const comA = this.$refs.comA;
        console.log(comA.title);  // Vue.js
        comA.sayHello();  // 弹窗
    }
  }
</script>

$parent/$childrenUse the code:

// child 子组件
export default
 {
  data () {   
    return
     {
         name: '我是子组件的数据'
     }
  },
  created() {
	console.log(this.$parent, ''获取父组件的实例对象")
  },
  methods: {
    sayName () {
      window.alert('我是子组件的方法');
    }
  }
}
// 父组件
<template>
  <child />
</template>
 
<script>  
export default
 {
 	data() {
		return {
			parentName: '我是父组件的数据"
		}
	},
	created() {
		console.log(this.$children, ''获取子组件的实例对象')
	},
	methods: {
		parentFun() {
			console.log("我的父组件的方法")
		}
	}
 }
</script>

4. Bus mechanismbus

This method uses an empty Vue instance as the central event bus (event center), uses it to trigger events and listen to events, and cleverly and lightweightly implements communication between any components, including parent-child, sibling, and cross-level.

public-bus.js:

//bus.js
import Vue from 'vue'
export default new Vue()

Component A code:

<template>
  <div>
    A组件:
    <span>{
   
   {elementValue}}</span>
    <input type="button" value="点击触发" @click="elementByValue">
  </div>
</template>
<script>
  // 引入公共的bus,来做为中间传达的工具
  import Bus from './bus.js'
  export default {
    data () {
      return {
        elementValue: 4
      }
    },
    methods: {
      elementByValue() {
      	// 使用$emit来传递参数
        Bus.$emit('sendVal', this.elementValue)
      }
    }
  }
</script>

Component B code:

<template>
  <div>
    B组件:
    <input type="button" value="点击触发" @click="getData">
    <span>{
   
   {num}}</span>
  </div>
</template>
<script>
  import Bus from './bus.js'
  export default {
    data () {
      return {
        num: 0
      }
    },
    mounted() {
      var vm = this
      // 用$on事件来接收参数
      Bus.$on('sendVal', (data) => {
        console.log(data)
        vm.num= data
      })
    },
    methods: {
      getData() {
        this.num++
      }
    },
    destroyed () {
	   // 取消对bus事件的监听
	   // 事件订阅是通过Bus对象完成的 与组件无关
	   Bus.$off('sendVal')
	 }
  }
</script>

4. vuex

PMT knowledge base address: vuex

5. $attrs / $listeners

  • $attrs: Contains properties (except class and style) that are not recognized (and obtained) by prop in the parent scope. When a component does not declare any props, all properties of the parent scope ( except class and style ) will be included here, and can be v-bind="$attrs"passed to internal components via . Usually interitAttrsused with option.
  • $listeners: Contains v-on event listeners in the parent scope (without the .native modifier). It can be v-on="$listeners"passed to internal components via .

$attrsNext, let's look at an example of cross-level communication ( ):

index.view:

//index.vue
<template>
  <div>
    <h2>浪里行舟</h2>
    <child-com1
      :foo="foo"
      :boo="boo"
      :coo="coo"
      :doo="doo"
      title="前端工匠"
    ></child-com1>
  </div>
</template>
<script>
import childCom1 from "./childCom1.vue";
export default {
  components: { childCom1 },
  data() {
    return {
      foo: "javascript",
      boo: "Html",
      coo: "Css",
      doo: "Vue"
    };
  },
  methods: {
    outputMsg() {
      console.log('我是父组件的方法');
    }
  }
};
</script>

childCom1.vue:

//childCom1.vue
<template>
  <div>
    <p>foo:{
   
   { foo }}</p>
    <p>childCom1的$attrs:{
   
   { $attrs }}</p>
    <child-com2 v-bind="$attrs"></child-com2>
  </div>
</template>
<script>
import childCom2 from "./childCom2.vue";
export default {
  components: { childCom2 },
  inheritAttrs: false, // 不会显示在子组件的dom元素上
  props: { foo: String }, // foo作为props属性绑定
  created() {
    console.log(this.$attrs); // { "boo": "Html", "coo": "CSS", "doo": "Vue", "title": "前端工匠" }
  }
};
</script>

childCom2.vue:

//childCom2.vue
<template>
  <div>
    <p>boo:{
   
   { boo }}</p>
    <p>childCom2的$attrs:{
   
   { $attrs }}</p>
  </div>
</template>
<script>
export default {
  inheritAttrs: false, // 不会显示在子组件的dom元素上
  props: { boo: String }, // boo作为props属性绑定
  created() {
    console.log(this.$attrs); // { "coo": "CSS", "doo": "Vue", "title": "前端工匠" }
  }
};
</script>
  • When inheritAttrs is false: it will not be displayed on the dom element of the child component
    insert image description here
  • When inheritAttrs trueis (default): it will be displayed on the dom element of the child component
    insert image description here
    $listenersExample:
// 父组件
<template>
  <my-input
      required
      placeholder
      class="theme-dark"
      @focue="onFocus"
      @input="onInput"
  >
  </my-input>
</template>
<script>
import MyInput from './child'
export default {
  components: {
    MyInput
  },
  methods: {
    onFocus (e) {
      console.log(e.target.value)
    },
    onInput (e) {
      console.log(e.target.value)
    }
  }
}
</script>
// 子组件
<template>
  <div>
    <input
        type="text"
        v-bind="$attrs"
        class="form-control"
        @focus="$emit('focus', $event)"
        @input="$emit('input', $event)"
    />
  </div>
</template>

<script>
export default {
  name: 'MyInput',
  inheritAttrs: false
}
</script>

It is very troublesome to bind native events in this way. Every native event needs to be bound, but using v-on="$listeners" will save a lot of trouble.

 <input
        type="text"
        v-bind="$attrs"
        class="form-control"
+       v-on="$listeners"
-       @focus="$emit('focus', $event)"
-       @input="$emit('input', $event)"
    />

6. provide / inject

  • Appears in pairs: provide and inject appear in pairs;
  • Role: used to pass data from parent components to descendant components;
  • How to use: provide returns the data to be passed to the subordinate in the parent component, and inject injects data into the subordinate components such as child components or grandchildren that need to use this data;
  • Usage scenario: Since vue has a $parent property, child components can access parent components. But it is more difficult for grandson components to access ancestor components. Cross-level access to parent component data can be easily achieved through provide/inject.

Parent component definition:

<script>
export default {
  // 父组件通过provide将自己的数据以对象形式传出去
  provide(){
    return {
      parentValue:"我是父组件的值啊" // 也可以从data中拿值
    }
  }
};
</script>

Acceptance method of descendant components:

<script>
export default {
  // inject:["parentValue"], // 使用一个注入的值作为数据入口:
  inject:{
    // 使用一个默认值使其变成可选项
    parentValue: { // 健名
      from: 'parentValue', // 来源
      default: '我是默认值' // 默认值
    }
  }
}
</script>

Note: provide is not responsive, and the responsive function has been lost when the subcomponent is injected. If you
want the entire data to be responsive—provide provides a function.
The function returns a responsive data inside. At this time, the responsive state of the entire piece of data will not be lost.

//父组件传值的定义个回调函数
<template>
  <div>
    <a-input v-model="parentValue"/>
  </div>
</template>
<script>
export default {
  data() {
    return {
      parentValue: "我是父组件的值啊"
    };
  },
  provide() {
    return {
      getParentVal: () => ({
        parentValue: this.parentValue
      })
    }
  }
};
</script>
//子组件用计算属性取值,watch监听
export default {
  inject: ['getParentVal'],
  computed: {
    actConfig() {
      this.parentValue= this.getParentVal().parentValue // 获取初始时父组件传过来的值
      return this.getParentVal();
    },
  },
  watch: {
    actConfig(val) {
      console.log("组件监听到的值", val);
      this.parentValue= val.parentValue
    },
  },
  data() {
    return {
      parentValue: ''
    }
  },
};
</script>

Summarize

Common usage scenarios can be broken down into three categories:

  • Parent-child communication: data is passed from parent to child props, and from child to parent through events ( $emit); communication is also possible through the parent chain/child chain ( $parent/ $children); ref can also access component instances; provide/ inject; $attrs/$listeners

  • Sibling communication: Bus;Vuex

  • Crossover communication: Bus; Vuex; provide/ inject, $attrs/$listeners

Guess you like

Origin blog.csdn.net/weixin_42566993/article/details/127045794