2016-06-27 23 views
14

Tôi đang cố gắng tạo một bus sự kiện toàn cầu để hai thành phần anh chị em có thể giao tiếp với nhau. Tôi đã tìm kiếm xung quanh; tuy nhiên, tôi không thể tìm thấy bất kỳ ví dụ nào về cách triển khai. Đây là những gì tôi có cho đến nay:Xe buýt sự kiện toàn cầu Vue.js

var bus = new Vue(); 

Vue.component('Increment', { 
    template: "#inc", 
    data: function() { 
    return ({count: 0}) 
    }, 
    methods: { 
    increment: function(){ 
     var increment = this.count++ 
     bus.$emit('inc', increment) 
    } 
} 
}) 

Vue.component('Display', { 
    template: "#display", 
    data: function(){ 
    return({count: 0}) 
    }, 
created: function(){ 
    bus.$on('inc', function(num){ 
    alert(num) 
    this.count = num; 
    }); 
} 
}) 


vm = new Vue({ 
el: "#example", 
}) 

Tôi tạo ra các mẫu của tôi như vậy: http://codepen.io/p-adams/pen/PzpZBg

Tôi muốn các thành phần Increment để giao tiếp số lượng với thành phần Display. Tôi không chắc chắn những gì tôi đang làm sai trong bus.$on().

Trả lời

26

Vấn đề là trong chức năng bus.$on, this là xe buýt. Bạn chỉ cần để ràng buộc dụ Vue hiện chức năng rằng việc sử dụng .bind():

bus.$on('inc', function(num){ 
alert(num) 
this.count = num; 
}.bind(this)); 

Bạn cũng nên kiểm tra https://github.com/vuejs/vuex nếu bạn muốn quản lý trạng thái ứng dụng toàn cầu.

EDIT: Kể từ trang này dường như nhận được rất nhiều nhấp chuột Tôi muốn chỉnh sửa và thêm một phương pháp khác, mỗi ChristopheMarois trong các ý kiến:

bus.$on('inc', (num) => { 
alert(num); 
this.count = num; 
}); 

Hoặc loại bỏ các cảnh báo:

bus.$on('inc', (num) => this.count = num); 
+0

Hmm. Nó vẫn không hoạt động. Không quá chắc chắn những gì đang xảy ra như tôi đã không bao giờ cố gắng để tạo ra một chiếc xe buýt sự kiện trước. Tôi đã thực hiện cùng một chương trình này trong vuex. Chỉ cần trong hướng dẫn vuejs 2 gần đây, Evan đề cập đến khả năng sử dụng một xe buýt sự kiện cho các vấn đề dễ dàng –

+1

nó hoạt động ở đây: http://codepen.io/anon/pen/KMWzLQ – Jeff

+1

Một lỗi có thể là bạn đang post- số gia tăng với 'var increment = this.count ++;'. Thay đổi nó thành 'var increment = ++ this.count;'. Bằng cách đó 'count' được tăng lên trước khi được gán cho' increment' – asemahle

3

Khi bạn viết ES5 JavaScript, bạn phải nhận thức được thực tế rằng những gì bạn đề cập đến bằng cách sử dụng từ khóa this có thể thay đổi, theo phạm vi, nó được gọi là từ.

Một ẩn dụ hữu ích để có được đầu của bạn xung quanh khái niệm this là suy nghĩ về các dấu ngoặc nhọn trong ES5 làm hàng rào, chứa/liên kết this riêng của nó.

Khi bạn sử dụng this trong hàm callback của xe buýt sự kiện của bạn, this không đề cập đến thành phần Vue của bạn, nhưng đối tượng xe buýt, trong đó có không đếm dữ liệu, do các dữ liệu mà bạn mong đợi để cập nhật doesn' t.

Nếu bạn có/muốn viết ES5 cú pháp một phương pháp phổ biến (ngoài ràng buộc this theo đề nghị của các câu trả lời được chấp nhận) là gán từ khóa this cho một biến như sau:

created: function(){ 
    var self = this; 
    bus.$on('inc', function(num){ 
    alert(num) 
    self.count = num; 
    }); 
} 

Nếu bạn có thể viết ES6, làm như vậy bất cứ khi nào có thể. Bạn luôn có thể biên dịch/chuyển đổi xuống ES5 với Babel. Câu trả lời được chấp nhận cho bạn biết cách sử dụng các chức năng mũi tên.

Chức năng mũi tên hoạt động trong trường hợp đó vì chúng không ràng buộc riêng this của chúng.

Để gắn bó với hàng rào ẩn dụ: tưởng tượng ES6 mũi tên chọc một lỗ ở hàng rào chức năng của bạn, vì vậy ngoài this có thể đi qua và bạn có thể gọi this như dự định.

Để tìm hiểu thêm về chức năng mũi tên ES6 thăm: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

+0

đây là câu trả lời duy nhất làm việc, suy nghĩ do ES6 chế độ nghiêm ngặt var tự = này; là điều cần thiết nếu không một lỗi được ném – Pixelomo

3

này được trả lời dài trở lại, đây là giải pháp của tôi sử dụng trong vue.js-2

main.js

import Vue from 'vue' 
import App from './App' 

export const eventBus = new Vue({ 
    methods:{ 
    counter(num) { 
     this.$emit('addNum', num); 
    } 
    } 
}); 

new Vue({ 
    el: '#app', 
    template: '<App/>', 
    components: { App } 
}); 

comp1.vue

//Calling my named export 
import { eventBus } from '../../main' 
<template> 
    <div> 
    <h1>{{ count }}</h1> 
    <button @click="counterFn">Counter</button> 
    </div> 
</template> 

<script> 
    import { eventBus } from '../../main' 

    export default { 
    name: 'comp-one', 
    data() { 
     return { 
     count: 0 
     } 
    }, 
    methods: { 
     counterFn() { 
     eventBus.counter(this.count); 
     } 
    }, 
    created() { 
     eventBus.$on('addNum',() => { 
     this.count++; 
     }) 
    } 
    } 
</script> 
+1

thì tốt hơn là không có các phương thức trong 'EventBus' bởi vì nó toàn cầu và sẽ phá vỡ đóng gói trong trường hợp này. Chỉ cần sử dụng 'emit' và' on' với trường hợp vue 'EventBus' trống. Đó là tất cả. –

+1

@OlegAbrazhaev Tôi đồng ý với bạn, và những ngày này tôi đang làm giống như những gì bạn nói. – Syed

0

Làm thế nào về điều này? Giả Vue.js 2.

Tạo một thành phần tổ chức sự kiện-Bus tái sử dụng và gắn nó vào Vue qua Plugin mẫu:

// ./components/EventBus.vue 
import Vue from 'vue' 
export const EventBus = new Vue() 

// ./plugins/EventBus.js 
export default { 
    install(Vue) { 
    const { EventBus } = require('../components/EventBus') 
    Vue.prototype.$bus = EventBus 
    } 
} 

// ./main.js 
import EventBus from './plugins/EventBus' 
Vue.use(EventBus) 

Sau đó, bạn có thể làm bất cứ nơi nào trong mã của bạn: this.$bus.$emit('some-event', payload)

Như một lưu ý phụ, cố gắng sử dụng mẫu Event-Bus như phương sách cuối cùng.

Các vấn đề liên quan