vue元件之間的通訊

孫小渃發表於2019-02-16

前言

作為一個vue初學者不得不瞭解的就是元件間的資料通訊(暫且不談vuex)。通訊方式根據元件之間的關係有不同之處。元件關係有下面三種:父–>子子–>父非父子

父–>子

父向子傳遞資料通過props

**父元件程式碼**
<template>
    <header-box :title-txt="showTitleTxt"></header-box>
</template>
<script>
    import Header from `./header`
    export default {
        name: `index`,
        components: {
            `header-box`: Header
        },
        data () {
            return {
                showTitleTxt: `首頁`
            }
        }
    }
</script>
**子元件程式碼**
<template>
    <header>
        {{thisTitleTxt}}
    </header>
</template>
<script>
    export default {
        name: `header-box`,
        props: {
            titleTxt: String
        },
        data () {
            return {
                thisTitleTxt: this.titleTxt
            }
        }
    }
</script>

子–>父

子元件向父元件傳遞分為兩種型別。
1、子元件改變父元件傳遞的props(你會發現通過props中的Object型別引數傳輸資料,可以通過子元件改變資料內容。這種方式是可行的,但是不推薦使用,因為官方定義prop是單向繫結)
2、通過$on和$emit

*通過props實現傳遞*
**父元件程式碼**
<template>
    <header-box :title-txt="showTitleTxt"></header-box>
</template>
<script>
    import Header from `./header`
    export default {
        name: `index`,
        components: {
            `header-box`: Header
        },
        data () {
            return {
                showTitleTxt: {
                    name: `首頁`
                }
            }
        }
    }
</script>
**子元件程式碼**
<template>
    <header @click="changeTitleTxt">
        {{thisTitleTxt.name}}
    </header>
</template>
<script>
    export default {
        name: `header-box`,
        props: {
            titleTxt: Object
        },
        data () {
            return {
                thisTitleTxt: this.titleTxt.name
            }
        },
        metheds: {
            changeTitleTxt () {
                this.titleTxt.name = `切換`
            }
        }
    }
</script>
*通過$on,$emit*
**父元件程式碼**
<template>
    <div id="counter-event-example">
      <p>{{ total }}</p>
      <button-counter v-on:increment="incrementTotal"></button-counter>
</div>
</template>
<script>
    import ButtonCounter from `./buttonCounter`
    export default {
        name: `index`,
        components: {
            `button-conuter`: ButtonCounter
        },
        data () {
            return {
                total: 0
            }
        },
        methods: {
            incrementTotal () {
                this.total++
            }
        }
    }
</script>
**子元件程式碼**
<template>
    <button @click="incrementCounter">{{counter}}</button>
</template>
<script>
    export default {
        name: `button-counter`,
        data () {
            return {
                counter: 0
            }
        },
        metheds: {
            incrementCounter () {
                this.$emit(`increment`)
                this.counter++
            }
        }
    }
</script>

非父子

簡單情況下我們可以通過使用一個空的Vue例項作為中央事件匯流排,(這裡也可以使用app例項,而不需要新建一個空Vue例項)

**main.js**
let bus = new Vue()
Vue.prototype.bus = bus

或者

**main.js**
new Vue({
  el: `#app`,
  router,
  template: `<App/>`,
  components: { App },
  beforeCreate () {
    Vue.prototype.bus = this
  }
})
**header元件**
<template>
    <header @click="changeTitle">{{title}}</header>
</template>
<script>
export default {
    name: `header`,
    data () {
        return {
            title: `頭部`
        }
    },
    methods: {
        changeTitle () {
            this.bus.$emit(`toChangeTitle`,`首頁`)
        }
    }
}
</script>
**footer元件**
<template>
    <footer>{{txt}}</footer>
</template>
<script>
export default {
    name: `footer`,
    mounted () {
        this.bus.$on(`toChangeTitle`, function (title) {
            console.log(title)
        })
    },
    data () {
        return {
            txt: `尾部`
        }
    }
}

相關文章