genkio / blog

Stay hungry stay foolish
https://slashbit.github.io/blog/
0 stars 1 forks source link

Communication between parent and child components in Vue.js #160

Open genkio opened 7 years ago

genkio commented 7 years ago

So, we modularized our components, great, but how about communication between parent and child component? There are a couple of ways to do this, take Agular 1 for example, you can just create a two-way binded scope object between parent and child (directive). Things are bit different with Vue, customizing component v-model (feature introduced in 2.2.0) and custom events are two of the solutions, and here are the minimal examples for each approach:

customizing component v-model

Parent component

<template>
  <div>
    <pre>{{ parentData }}</pre>
    <child-component v-model="parentData"></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent'

export default {
  components: {
    'child-component': ChildComponent
  },
  data () {
    return {
      parentData: {
        someProp: 'Hello world!'
      }
    }
  }
}
</script>

Child component

<template>
  <div>
    <!--parentData in the parent component will also be updated when changes occur here-->
    <input type="text" v-model="parentData.someProp" />
  </div>
</template>

<script>
export default {
  model: {
    prop: 'parentData'
  },
  props: {
    parentData: {
      type: Object,
      default: {}
    }
  }
}
</script>

Custom event

Parent component

<template>
  <div>
    <pre>{{ parentData }}</pre>
    <child-component :someProp="parentData" v-on:customEventForValChange="handleCustomEvent"></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent'

export default {
  components: {
    'child-component': ChildComponent
  },
  data () {
    return {
      parentData: {
        someValue: 'Hello world!'
      }
    }
  },
  methods: {
    handleCustomEvent (newVal) {
      this.$set(this.parentData, 'someValue', newVal)
    }
  }
}
</script>

Child component

<template>
  <div>
    <input type="text" v-model="someProp.someValue" />
  </div>
</template>

<script>
export default {
  props: {
    someProp: {
      type: Object,
      default: {}
    }
  },
  watch: {
    someProp: {
      handler: function (newVal) {
        this.$emit('customEventForValChange', newVal)
      },
      deep: true
    }
  }
}
</script>