Vue.js 元件之間的傳值

tankboo發表於2017-12-27

概述

vue中元件之間的傳值傳值情況主要有以下三種

  • 父元件向子元件傳值
  • 子元件向父元件傳值
  • 兄弟元件之間相互傳值或者是兩個沒有關係的元件之間的傳值

在開始介紹之前我們先建立3個vue檔案,檔名分別為:Parent.vue , Child1.vue , Child2.vue

父元件向子元件傳值

這種情況是三種傳值方案中最簡單的, 通過在子元件中使用 props就可以實現

父元件Parent.vue中的程式碼

<template>
  <div>
    <child-1  :btnName="btnName"/>
  </div>
</template>
<script>
import Child1 from './Child1'

export default {
  name: 'Parent',
  components: {
    'child-1': Child1
  },
  data () {
    return {
      btnName: ' 我是一個button'
    }
  }
}
</script>
複製程式碼

子元件Child1.vue

<template>
    <button > {{btnName}}</button>
</template>
<script>
export default {
  name: 'Child1',
  props: ['btnName']
}
</script>
<style>
    button{
        padding:5px 10px;
        margin:2px;
        background-color:#fff;
        border-radius: 5px; 
    }
</style>
複製程式碼

關鍵點就是需要在子元件中 使用 props 關鍵字 來接收父元件傳過來的值

顯示效果如下

Vue.js 元件之間的傳值

子元件向父元件傳值

在子元件向父元件傳值時需要使用 vue 中的 $on 和 $emit ,使用$emit 可以觸發 $on 中監聽的事件,現在我們來實現一個可以統計按鈕點選次數的功能

在父元件中有個 count 欄位用於統計,button點選的次數

首先我們需要在Parent.vue的data中定義count變數,預設值為0,程式碼如下:

data () {
    return {
      btnName: ' 我是一個button',
      count: 0
    }
  }
複製程式碼

然後將count加入到template中便於顯示, 此時parent.vue的template的程式碼如下

<template>
  <div>
    <p>點選次數: {{count}}</p>
    <child-1  :btnName="btnName"/>
  </div>
</template>
複製程式碼

count加上後頁面的顯示效果如下:

Vue.js 元件之間的傳值
接下來我們需要在父元件中增加一個可以改變count值的事件,同時在 中加上監聽事件

<template>
  <div>
    <p>點選次數: {{count}}</p>
    <child-1  :btnName="btnName" @update:count="changeCount"/>
  </div>
</template>
<script>
import Child1 from './Child1'

export default {
  name: 'Parent',
  components: {
    'child-1': Child1
  },
  data () {
    return {
      btnName: ' 我是一個button',
      count: 0
    }
  },
  methods: {
    changeCount () {
      ++this.count
    }
  }
}
</script>
複製程式碼

子元件Child1.vue

<template>
    <button @click="clickHandle"> {{btnName}}</button>
</template>
<script>
export default {
  name: 'Child1',
  props: ['btnName'],
  methods: {
    clickHandle () {
      this.$emit('update:count')
    }
  }
}
</script>
複製程式碼

現在通過點選button即可實現改變count的值

兄弟元件之間的傳值

兄弟元件之間傳值有兩種方式:

  1. 將需要改變的值放到父元件中,子元件通過props來獲取父元件的值
  2. 通過eventbus 來實現兄弟元件之間的傳值,其原理還是通過$on和$emit來時實現的,區別是現在全域性建立一個空的vue物件,然後將事件繫結到該空物件上,最後通過該空物件來觸發$on監聽的事件

現在還是通過上面的例子來實現說明這兩種情況

在開始之前需要新建一個元件Child2,然後將count移動到child2中,然後在parent中引入child2

Child2.vue

<template>
    <p>點選次數: {{count}}</p>
</template>
<script>
export default{
  name: 'Child2',
  props: ['count']
}
</script>
複製程式碼

Parent.vue

<template>
  <div>
      <child-2 />
      <child-1  :btnName="btnName"/>
  </div>
</template>

<script>
import Child1 from './Child1'
import Child2 from './Child2'

export default {
  name: 'Parent',
  components: {
    'child-1': Child1,
    'child-2': Child2
  },
  data () {
    return {
      btnName: ' 我是一個button'
    }
  }
}
</script>

複製程式碼

此時點選button 即可實現統計功能,但是這種方式不太好的地方是它會通過父元件來進行過度,那樣就會涉及到對父元件的修改,如果要改變的變數很多,則需要在父元件中宣告很多變數,然後在傳到子元件中進行修改,既然是兄弟元件之間的傳值,那麼有沒有辦法直接跳過父元件,讓兄弟元件之間直接進行交流,這個時候就需要用到eventbus 首先建立一個bus.js的檔案 ,在檔案中我們需要建立一個空vue物件,程式碼如下:

import Vue from 'vue'

export default new Vue()

複製程式碼

然後在 Child1和Child2中引入該檔案

此時parent.vue , child1.vue , child2.vue 他們的程式碼分別如下

Parent.vue

<template>
  <div>
      <child-2 />
      <child-1  :btnName="btnName"/>
  </div>
</template>

<script>
import Child1 from './Child1'
import Child2 from './Child2'

export default {
  name: 'Parent',
  components: {
    'child-1': Child1,
    'child-2': Child2
  },
  data () {
    return {
      btnName: ' 我是一個button'
    }
  }
}
</script>
複製程式碼

Child1.vue

<template>
    <button @click="clickHandle"> {{btnName}}</button>
</template>
<script>
import Event from '../bus'

export default {
  name: 'Child1',
  props: ['btnName'],
  methods: {
    clickHandle () {
      Event.$emit('update:count')
    }
  }
}
</script>
<style>
    button{
        padding:5px 10px;
        margin:2px;
        background-color:#fff;
        border-radius: 5px; 
    }
</style>
複製程式碼

Child2.vue

<template>
    <p>點選次數: {{count}}</p>
</template>
<script>
import Event from '../bus'

export default{
  name: 'Child2',
  data () {
    return {
      count: 0
    }
  },
  created () {
    Event.$on('update:count', () => {
      ++this.count
    })
  }
}
</script>
複製程式碼

eventbus這種方式不僅可以用到兄弟元件之間,它還可以用到任意兩個不想關聯的元件之間,但是如果大量使用的話不太利於管理,比如可能會照成命名的衝突。在比較複雜的系統中可以考慮是用vuex

在上面的例子中$on ,$emit 並沒有直接傳值過去,如果需要傳值,可用如下格式:

this.$on('test', function (msg) {
  console.log(msg)
})
this.$emit('test', 'hi')
// => "hi"
複製程式碼

附錄

vue中的事件型別(轉載自官網):

vm.$on( event, callback )

引數:

  • {string | Array} event (陣列只在 2.2.0+ 中支援)
  • {Function} callback

用法: 監聽當前例項上的自定義事件。事件可以由vm.$emit觸發。回撥函式會接收所有傳入事件觸發函式的額外引數。

示例:

vm.$on('test', function (msg) {
  console.log(msg)
})
vm.$emit('test', 'hi')
// => "hi"
複製程式碼

vm.$once( event, callback )

引數:

  • {string} event
  • {Function} callback

用法: 監聽一個自定義事件,但是隻觸發一次,在第一次觸發之後移除監聽器

vm.$off( [event, callback] )

引數:

  • {string | Array} event (只在 2.2.2+ 支援陣列)
  • {Function} [callback]

用法:

  • 移除自定義事件監聽器。
  • 如果沒有提供引數,則移除所有的事件監聽器;
  • 如果只提供了事件,則移除該事件所有的監聽器;
  • 如果同時提供了事件與回撥,則只移除這個回撥的監聽器。

vm.$emit( event, […args] )

引數:

  • {string} event
  • [...args]

觸發當前例項上的事件。附加引數都會傳給監聽器回撥。

相關文章