簡體   English   中英

如何使用vue.js從應用程序中的任何其他組件觸發組件事件?

[英]How to trigger component events from any other component in the app using vue.js?

我有一個要在網站所有頁面上運行的組件(倒數計時器)。 在頂級App.vue文件中引用了它。 我需要能夠從應用程序內的任何其他組件調用該組件內部的事件(以重新啟動時間),而不管它的層次結構鏈有多深(意味着,我不想在每個事件中都運行事件和$ emits)網站上針對這件事的單個組件)。

每當我對服務器進行ajax調用時,我都想重置計時器。 因此,每次在下面的代碼中單擊按鈕時,我都想觸發倒數計時器組件上的startCountdown(true)事件。

這是我正在做的一個codeandbox示例。

Main.js

import Vue from "vue";
import App from "./App.vue";
import Vuex from "vuex";
import router from "./router/router";
import VueAwesomeCountdown from "vue-awesome-countdown";

Vue.config.productionTip = false;

Vue.use(Vuex);
Vue.use(VueAwesomeCountdown);

const store = new Vuex.Store({
  state: {
    count: 0
  },
  getters: {
    count: state => {
      return state.count;
    }
  },
  mutations: {
    increment: state => state.count++,
    decrement: state => state.count--
  },
  actions: {
    increment: context => {
      context.commit("increment");
    },
    decrement: context => {
      context.commit("decrement");
    }
  }
});

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

App.vue

<template>
  <div id="app">
    <router-link to="/" class="btn bt-link">Page 1</router-link>&nbsp;|
    <router-link to="/Page2" class="btn bt-link">Page 2</router-link>&nbsp;|
    <router-link to="/Page3" class="btn bt-link">Page 3</router-link>
    <hr>
    <br>
    <br>
    <router-view></router-view>
    <br>
    <br>

    <hr>
    <!-- Timer countdown -->
    <countdown ref="sessionTimer" :left-time="99000">
      <span slot="process" slot-scope="{ timeObj }">Session Timer Countdown: {{ timeObj.ceil.s }}</span>
      <span slot="finish">TIMED OUT!</span>
    </countdown>
    <button class="ml-3 btn btn-warning" @click="restart">Manual Restart</button>
    <hr>
    <!-- The below is just show vuex is wired up correctly -->
    <p>This is just to show that Vuex is working properly.</p>
    <p>{{ count }}</p>
    <p>
      <button @click="increment">+</button>
      <button @click="decrement">-</button>
    </p>
  </div>
</template>

<script>
export default {
  name: "App",
  computed: {
    count() {
      return this.$store.getters.count;
    }
  },
  methods: {
    restart() {
      this.$refs.sessionTimer.startCountdown(true);
    },
    increment() {
      this.$store.dispatch("increment");
    },
    decrement() {
      this.$store.dispatch("decrement");
    }
  },
  components: {}
};
</script>

<style>
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 20px;
}
</style>

Page2.vue

<template>
  <div>
    <h1>Page 2</h1>
    <br>
    <br>
    <button class="btn btn-success" @click="interactWithServer">Interact with Server 2</button>
    <br>
    <br>
    <SubComponent></SubComponent>
  </div>
</template>

<script>
import SubComponent from "./Page2-SubComponent.vue";

export default {
  methods: {
    interactWithServer() {
      //This function will interact with server but I need to start countdown timer over again first
      //axios call goes here after timer is reset
    }
  },
  components: {
    SubComponent
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
</style>

頁面SubComponent.vue

<template>
  <div>
    <h3>SUB COMPONENT</h3>
    <br>
    <br>
    <button class="btn btn-primary" @click="interactWithServer">Interact with Server 2.1</button>
  </div>
</template>

<script>
export default {
  methods: {
    interactWithServer() {
      //This function will interact with server but I need to start countdown timer over again first
      //axios call goes here after timer is reset
    }
  }
};
</script>

如果有一個較短的方式,但你可以在商店觸發變量,然后聽從不確定App.vue文件,然后執行restart打開..這里是一個codesandbox樣本

// store

state: {
  changed: false
}

getters: {
  changed: (state) => state.changed
}

mutation: {
  changed: (state) => state.changed = !state.changed
}
// App.vue

 computed: {
    trigger() {
      return this.$store.getters.changed
    }
  },
  methods: {
    restart() {
      this.$refs.sessionTimer.startCountdown(true);
    }
  },
  watch: {
    trigger() {
      this.restart()
    }
  }

在其他組件上:

interactWithServer() {
  this.$store.commit("changed");
}

將計時器的編號保存在商店的:left-time =“ 99000”中,當您在interactWithServer()中觸發事件時將其重置會更好嗎?

Main.js (其他代碼)

state:{
  timer: 99000
},
getters: {
  getTimer: state => {
    return state.timer;
  }
},
mutations: {
  resetTimer: state => state.timer = 99000
},
actions: {
  restartTimer: context => {
    context.commit("resetTimer");
  }
}

App.vue (修改后的代碼)

</template>
    <countdown ref="sessionTimer" :left-time="timer">
      <span slot="process" slot-scope="{ timeObj }">Session Timer Countdown: {{ timeObj.ceil.s }}</span>
      <span slot="finish">TIMED OUT!</span>
    </countdown>
</template>
<script>
  computed: {
    timer() {
      return this.$store.getters.timer;
    }
  },
</script>

然后在interactWithServer()中調用this。$ store.dispatch(“ restartTimer”);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM