Heim  >  Artikel  >  Web-Frontend  >  So lösen Sie das Problem, dass der Eventbus in Vue mehrmals ausgelöst wird

So lösen Sie das Problem, dass der Eventbus in Vue mehrmals ausgelöst wird

小云云
小云云Original
2018-05-12 09:39:362437Durchsuche

Angenommen, ich habe Seite A, um die Datenübertragung zwischen zwei Seitenkomponenten zu realisieren. Nachdem ich auf eine Schaltfläche auf Seite A geklickt habe, springt die Seite automatisch zu Seite B, und ich möchte um einige Parameter von Seite A auf Seite B zu übertragen. (Für kleine Parameter können Sie Parameter über Routing-Parameter oder Abfragen übergeben, oder große Daten können mit Vuex verarbeitet werden.) In diesem Artikel werden hauptsächlich der mehrfach ausgelöste Eventbus in Vue und die aufgetretenen Fallstricke vorgestellt Es ist ziemlich gut. Teilen Sie es jetzt mit allen und hoffen Sie, dass es allen helfen kann.

Um das Ziel zu erreichen:

Nach dem Klicken geben Sie ein Ereignis aus und springen dann zur Seite /moneyRecord.

Der nächste Schritt besteht darin, dieses Ereignis auf der MoneyRecord-Seite zu empfangen und dann die Parameter zu akzeptieren.

// 这是页面A的内部触发bus事件的代码
 editList (index, date, item) {
// 点击进入编辑的页面,需要传递的参数比较多。
  console.log(index, date, item)
  bus.$emit('get', {
  item: item.type,
  date: date
  })
  this.$router.replace({path: '/moneyRecord'})
 }

// moneyRecord页面
created () {
 //这里我将icon的list给保存下来了
 bus.$on('get', this.myhandle)
 },
methods: {
 myhandle (val) {
  console.log(val, '这是从上个页面传递过来的参数')
 }
}

Gerade als ich begeistert war, hatte ich das Gefühl, dass Seite B die Daten wie selbstverständlich akzeptieren würde, solange ich das Get-Ereignis auf Seite A auslöste. Allerdings war das Ergebnis nicht zufriedenstellend, schauen Sie sich die Animation unten an.

Beurteilen Sie die Anzahl der Ereignisauslöser hauptsächlich anhand der Häufigkeit, mit der die Datenzeile „Dies sind die von der vorherigen Seite übertragenen Daten“ ausgegeben wird. ""


Ich weiß nicht, ob Sie es bemerkt haben, aber als ich die Listenseite zum ersten Mal betrat, klickte ich auf ein beliebiges Element unter der Liste, um es dort zu steuern erfolgt keine Ausgabe von der Station. Aber wenn ich zum zweiten Mal klicke, um das Ereignis auszulösen, werden Testdaten ausgegeben. Klicken Sie erneut hinein und es werden zwei Daten ausgegeben. . . Der Reihe nach erhöht. (Das „Dies sind die von der vorherigen Seite übertragenen Daten“ auf der Konsole sind die Testdaten)

Es gibt also zwei Fragen.

Frage:

  1. Frage 1: Warum wird das Ein-Ereignis auf Seite B nicht ausgelöst, wenn es zum ersten Mal ausgelöst wird

  2. Frage 2: Warum erscheint es, wenn ich es nacheinander erneut auslöse? Jedes Mal stelle ich fest, dass die vorherige Ereignisverteilung nicht widerrufen wurde, was dazu führt, dass immer mehr Ereignisauslöser ausgeführt werden jedesmal.

Lösung

Für Problem 1

Das muss mit dem Lebenszyklus von vue beginnen, I I Ich habe zuerst einen Test durchgeführt, das heißt, wie sind die Lebenszyklen der beiden Komponenten, wenn ich von Seitenkomponente A zu Seitenkomponente B springe? Hier ist ein Bild des Vue-Lebenszyklus.


Ich habe meine eigenen Experimente durchgeführt, um die Ausführung des Lebenszyklus dieser beiden Komponenten während des Seitensprungprozesses zu überprüfen.

// 我分别在页面A和页面B中去添加以下代码:
beforeCreate () {
 console.group('%c%s', 'color:red', 'beforeCreate 创建前状态===============组件2》')
 },
 created () {
 console.group('%c%s', 'color:red', 'created 创建完毕状态===============组件2》')
 },
 beforeMount () {
 console.group('%c%s', 'color:red', 'beforeMount 挂载前状态===============组件2》')
 },
 mounted () {
 console.group('%c%s', 'color:red', 'mounted 挂载状态===============组件2》')
 },
 beforeUpdate () {
 console.group('%c%s', 'color:red', 'beforeUpdate 更新前状态===============组件2》')
 },
 updated () {
 console.group('%c%s', 'color:red', 'updated 更新状态===============组件2》')
 },
 beforeDestroy () {
 console.group('%c%s', 'color:red', 'beforeDestroy 破前状态===============组件2》')
 },
 destroyed () {
 console.group('%c%s', 'color:red', 'destroyed 破坏状态===============组件2》')
 }
// 另外一个组件的我就不放出来了

Testergebnisbild:



Tatsächlich kann man es sehen deutlich durch die Ergebnisse Wenn wir uns also noch auf Seite A befinden, wurde Seite B noch nicht generiert, d. h. das Ereignis von A, das von der Erstellung auf Seite B überwacht wird, wurde noch nicht ausgelöst. Zu diesem Zeitpunkt, als Sie das Ereignis in A ausgeben, hat B es tatsächlich nicht überwacht.

Schauen Sie noch einmal, die rote Seite ist die B-Seitenkomponente. Was passiert, wenn Sie von Seite A zu Seite B springen? Zuerst wird zuerst die B-Komponente erstellt, dann beforeMount, dann wird die A-Komponente zerstört und dann wird die A-Komponente beforeDestory ausgeführt und destoryed.

So können wir das Emit-Ereignis in die A-Seitenkomponente in beforeDestory schreiben . Da zu diesem Zeitpunkt die B-Seitenkomponente erstellt wurde, wurde das von uns geschriebene $on-Ereignis

ausgelöst. Daher ist es in Ordnung, das $emit-Ereignis während beforeDestory zu verwenden.

// 修改一下A页面中的代码:
// 这是原先的代码
 editList (index, date, item) {
// 点击进入编辑的页面,需要传递的参数比较多。
  console.log(index, date, item)
  this.item = item.type
  this.date = date
  this.$router.replace({path: '/moneyRecord'})
 }
// 重新在data属性内部定义新的变量,来存储要传过去的数据;
然后:
 beforeDestroy () {
 console.log(this.highlight, '这是今年的数据', this, '看看组件销毁之前会发生什么')
 bus.$emit('get', {
  item: this.item,
  date: this.date
  })
 },

Weiter. Schauen Sie sich den Effekt nach der Änderung an


Sie können dies sehen, wenn Sie zum ersten Mal auf die Liste klicken, dh wenn das Emit-Ereignis ausgelöst wird Zum ersten Mal ist das Steuerelement auch Es wird ausgegeben, daher ist es wirksam, $emit in beforeDestoryed auszugeben, und die B-Seitenkomponente überwacht auch das Eintreffen von $on.

Es scheint jedoch, dass selbst das Auslösen von Ereignissen der Reihe nach immer noch zunimmt, das heißt, die Ausgabe der Konsole wird jedes Mal zunehmen. . .

Lösung:

Schauen Sie sich an, was auf Github vorgeschlagen wurde. https://github.com/vuejs/vue/issues/3399


You Dada hat die folgende Lösung vorgeschlagen:


* Das heißt, dieses $on-Ereignis wird nicht automatisch und eindeutig zerstört, und wir müssen es manuell zerstören. (Allerdings bin ich mir nicht sicher, was der externe Bus hier bedeutet. Kann es jemand erklären? Sie haben auch erwähnt, dass er gelöscht werden muss, wenn der externe Bus registriert ist) ****

所以。我在B组件页面中添加Bus.$off来关闭。代码如下:

// 在B组件页面中添加以下语句,在组件beforeDestory的时候销毁。
 beforeDestroy () {
 bus.$off('get', this.myhandle)
 },

来看一下输出的结果


t可以看到,控制台第一次进去的时候就有输出,而且输出的不会逐次增加

*当然,尤大大还说可以写一个mixin?我还不知道是什么?以后在研究一下。

总结: 所以,如果想要用bus 来进行页面组件之间的数据传递,需要注意亮点,组件A$emit事件应在beforeDestory生命周期内。其次,组件B内的$on记得要销毁。

相关推荐:

guava eventbus实例代码详解

Java-类库-Guava-EventBus

vue微信公众号开发踩坑记录

Das obige ist der detaillierte Inhalt vonSo lösen Sie das Problem, dass der Eventbus in Vue mehrmals ausgelöst wird. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn