Parent components pass values to child components

  • Accept values passed by the parent via the child component’s props options
  • The data in props can be used directly in the template
  • Note: props do not have properties with the same name as data, which could cause overlay issues

How child components are set up

My - com ponent Vue.com (' ', {props: [' title '], / / to the binding properties of the parent class template: '< h > {{title}} < / h >'})

How the parent component is set

  • Set properties for the custom component

    < div id = "app" > < my - com title = "instance content 1" > < / my - com > / / static attribute set, can't modify operation < my - com: title = "' 2 'power content" > < / my - com > / / dynamic properties Settings: <my-com :title="item.title"></my-com> // Dynamic property setting: data (parent component data update will make the child component update synchronize) </div>
    new Vue({ ... Data: {item: {title: "three power content"}}, components: {" my - com ": {props: [" title"]. template:` <div> <h3>{{ title }}</h3> </div> ` } } })

    Props naming rules

  • It is recommended to use camelCase for prop naming and kebab-case for parent binding. Why is that?
  • (props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props, props
  • In the parent component, the properties are written in HTML, and HTML properties are case insensitive, so the camelCase is recognized as a camelCase, which may not be the Camel-Case result we want

Child components

Vue.component("my-com",{ props:["myTitle"], // {myTitle:String} template: '<div> <h3>{{myTitle}}</h3> <a :href="myTitle"></a> // `})

The parent component

< div id = "app" > < my com - my - title = "instance content 1" > < / my - com > < my - com: my - the title = "' 2 'power content" > < / my - com > < my - com :my-title="item.title"></my-com> </div>

A one-way data stream from parent to child

All props between the parent-child components are bound one-way down. It means that it can only be transmitted from the father to the son, not the other way around (the son influences the father)

Explanation:

  • The data changes of the parent component are automatically bound to the child component and updated, and the actions of the child component cannot affect the parent component in reverse
  • If the child component is to process prop data, it should be stored in data or computed and operated on

    Vue.component("my-com",{ props:['initialTitle'], template:'<h3> {{ myTitle }} </h3>', Data () {return {myTitle: enclosing initialTitle / / save properties, after processing in the interpolation}}})
    <div id="app" <my-com :initial =" value"></my-com> </div> var vm = new Vue({data:{value:' '),}, }).$mount("#app")
  • The component is also a VUE instance, so no matter how the property inside the instance is changed, or how the MyTitle data is changed, the parent data will not be affected
  • Props data processing methodThis. myTitle = "Other Content"
  • Modifying the props data directly generates a warningThis. initialTitle = "Other Content", suggests using data or computed instead of a direct revision (I didn’t show up)

  • Note that if prop is an array or object, the child component operations will affect the state of the parent component. (reference)
  • The solution

    • Save it, copy it to an object operation,

      obj_:Object.assign({},this.obj)
    • Objects are not passed in as a whole

      < div id = "app" > < p > {{obj. Name}} < / p > / / be affected < my - com: initial - obj = "obj" > < / my - com > < / div > var = new vm Vue ({data: { Obj: {name: 'McGee, / / be affected 1 age: 18}},}). $mount (" # app ")
      Vue.component("my-com",{ props:['initialObj'], The template: ` < div > < h3 > {{myObj. Name}}, {{myObj. Age}}, < / h3 > < button @ click = "fn" > button < / button > < / div > `, Data (){return {myObj:this.initialObj}}, methods:{fn(){this.initialObj. Name = "Jack"}})

Child components pass values to parent components

  • Passing values from child to parent requires custom events
  • Unable to process via props, via custom events
  • There is a problem with passing from parent to child and trying to get back to the parent. When is the child component finished processing, when is the data modified, and when is the data passed to the parent component undetermined and therefore triggered by an event

case

The product is the child component, and the shopping cart is the parent component. The parent component needs to count the number of items, so it needs to pass the value to the parent component when the number of children changes.

Var = new vm Vue ({data: {products: [{id: 1, the title: "eggplant"}, {id: 2, the title: "pepper"}, {id: 3, the title: "tomatoes"}], totalCount: 0}, }).$mount("#app")
<div id="app" <h3> shopping cart </h3> <product-item v-for='item in products' :key="item.id" :title='item.title' ></product-item> <p> {{totalCount}}</p> </div>
Vue.component('product-item',{ props:['title'], The name of the template: ` < div > < span > {{title}}, the number of {{count}} < / span > < button @ click = "addCount" > + 1 < / button > < / div > `, data(){ return { count:0 } }, methods:{ countIns(){ this.count++; }}})
  • Subcomponent data changes when passed$emit()Fire a custom event. (Instance method)
  • Custom event names are recommended to use kebab-case, which is not recognized by binding the hump or PASCAL with @ in the parent component

    Vue.component('product-item',{ ... $emit(' countIns ++ ') {$emit(' countIns ++ '); }}})

    The parent component

    <div id="app"> <product-item ... @Count-Change =" TotalCount ++"; @Count-Change =" TotalCount ++"; @Count-Change =" TotalCount ++"; @Count-Change =" TotalCount ++"

    Custom event pass values

    Vue.component('product-item',{ ... $emit('count-change',1) {$emit(){$emit('count-change',1); }, countIns5(){ this.$emit('count-change',5) this.count+=5; }}})
  • The parent component needs to receive data passed by the child component when listening for events.

    <div id="app"> <product-item ... {{totalCount}}</p> </div> {{totalCount}}</p> </div>

    or

    @count-change="onCountChange" new Vue({ ... }}} :{onCountChange(ProductCount){this.totalCount += ProductCount}})

Non-parent-child components pass values

  • A non-parent component is a sibling component or two components that are completely unrelated

Description of content

  • Brother components pass values
  • EventBus
  • Other methods of passing values

Brother components pass values

  • A sibling component can relay data through a parent component
  • For example, the value passed by a child of B can be passed by a child of A to a parent, which in turn can be passed by a parent to a child of B

    New Vue({data:{value:"" // The root instance data used for data transfer}})
    <div id="app"> <com-a @value-change="value = $event" ></com-a> // <com-b :value="value"></com-b> // / </div>

    A component

    Vue.ponents ('ComA',{template: 'A content {{value}} <button @click="$emit('value-change',value)" > send </button> ', Data (){return {value: 'power content'}}})

    B component

    VueSeponents ('ComB',{props:['value'] template: 'component B content {{value}}'})

    EventBus

    The problem

  • When the component nesting relationship is complex, passing values according to the component relationship can be tedious.
  • In order for a component to relay data, there will be a lot of data in the data that is not related to the function of the current component.

To solve

  • EventBus(EventBus) is a separate event center that manages pass-by-value operations between components. (Postman, transfer processing)
  • EventBus manages component pass-value operations with a new Vue instance, and components register events with the instance and invoke events to pass data.

    // EventBus.js var bus = new Vue() // EventBus.js var bus = new Vue() // EventBus.js var bus = new Vue(
  • The sending component fires a BUS event, and the receiving component registers the event with the BUS.

    <script SRC ="EventBus.js"></script> // Add js vue.component ('product-item',{... $emit(' Count-Change ',1) {$emit(' Count-Change ',1) {$emit(' Count-Change ', 2){$emit(' Count-Change ', 2); }}})
  • The bus is registered with the corresponding event by the $on() operation.

    Vue.component('product-total',{ template:` <p>{{ totalCount }}</p> `, data(){ return { totalCount:0 } }, $on(' CountChange ',(productCount)=>{this.totalCount+=productCount // })})})