【问题标题】:Call Global Component's Method from Another View/Component in Vue.js 3从 Vue.js 3 中的另一个视图/组件调用全局组件的方法
【发布时间】:2022-01-25 03:17:56
【问题描述】:

我有一个 Vue 3 应用程序,我想从另一个组件调用全局组件的方法。

代码如下:

 //main.js   
import { createApp, h } from 'vue';
import Loading from '@/components/Loading'; // Global Loading Component

const App = {
    computed: {
      ViewComponent () {
        return require(`./views/Index.vue`).default
      }
    },
  
    render () {
      return h(this.ViewComponent)
    },
  }

const app = createApp(App);
app.component('Loading', Loading); // Adding it to Global
app.mount('#app');

//@/components/Loading.vue
<template>
  <div id="darken"></div>
  <div id="loading">
    <img src="@/assets/images/loading.gif" />
  </div>
</template>

<script>
  export default {
    name: 'Loading',

    methods: {
      showLoading(){
        document.getElementById("darken").style.display = "inline";
        document.getElementById("loading").style.display = "inline";
      },
      hideLoading(){
        document.getElementById("darken").style.display = "none";
        document.getElementById("loading").style.display = "none";
      }
    }
  }
</script>

<style>
  #darken {
    position: absolute;
    display: none;

    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: black;
    opacity: 0.5;
  }

  #loading {
    position: absolute;
    display: none;

    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    -ms-transform: translate(-50%, -50%); /* for IE 9 */
    -webkit-transform: translate(-50%, -50%); /* for Safari */
  }

  #loading img {
    width: 400px;
  }
</style>

//@/views/Index.vue
<template>
    <!-- Design Stuff ... -->
    <button v-on:click="login()">Login</button>
    <loading />
</template>

<script>
export default {
    methods: {
      login(){
        //this.$refs.Loading.showLoading(); // this works when i add ref="Loading" to the <loading /> tag

              // but i need something better, something like "this.$components.Loading.showLoading();"

              // adding ref="Loading" with the loading tag is not convenient for me // is there alternative?
      }
    }
}
</script>

我找了很多,找不到我要找的东西。

任何想法?,我真的很感激。谢谢。

PS:我是 Vue.js 的新手,但我学得很快。

【问题讨论】:

    标签: javascript vue.js


    【解决方案1】:

    您有 2 个选项 - 共享函数和事件总线。

    使用共享函数,您有一个文件,该文件导出准系统 JavaScript 函数并在您需要它们的每个组件中导入所需的函数 - 例如。在LoadingIndex 中。或者,如果您愿意 - 您可能有多个具有不同类的文件,然后在需要它们的地方导入和实例化这些类。当您需要不依赖于使用位置的功能时,此方法适用 - 也就是说,它不依赖于应用程序中的特定组件。例如,如果您需要从应用中的不同位置将数据导出到 CSV - 您可以编写一个类(或单个函数)来处理该问题,然后在您需要该功能的任何地方使用。

    如果您需要从另一个组件向应用程序中的特定组件发出信号(即触发某些行为),那么您需要一个事件总线。您可以使用mitt。然后在Loading 组件中,您将订阅像 SHOW_LOADING 这样的事件,在Index 组件中,您将在事件总线上发出 SHOW_LOADING 事件。

    【讨论】:

      【解决方案2】:

      我解决了这个问题。

      加载组件包含需要全局渲染的 HTML 和 CSS,同时它包含需要全局调用的方法。

      所以我找到了一个适合我的解决方案:

       //main.js   
      import { createApp, h } from 'vue';
      import Loading from '@/components/Loading'; // Global Loading Component
      
      const App = {
          computed: {
            ViewComponent () {
              return require(`./views/Index.vue`).default
            }
          },
        
          render () {
            return h(this.ViewComponent)
          },
        }
      
      const app = createApp(App);
      app.component('Loading', Loading); // Adding it to Global
      app.config.globalProperties.Loading = Loading.methods; // ADDED NEW !!
      app.mount('#app');

      //@/views/Index.vue
      <template>
          <!-- // Design Stuff ... -->
          <button v-on:click="login()">Login</button>
          <loading /> <!-- // Leave it here or Put it in Main.vue Layout so it will be global in all renders --> 
      </template>
      
      <script>
      export default {
          methods: {
            login(){
              // Newly Added
              this.Loading.showLoading(); // This function can be accessed anywhere in Vue files
              
              // do stuff
              // finish stuff
              
              this.Loading.hideLoading(); // This function can be accessed anywhere in Vue files
            }
          }
      }
      </script>

      【讨论】:

        猜你喜欢
        • 2020-04-05
        • 2018-06-14
        • 2016-05-22
        • 2016-07-14
        • 2017-08-16
        • 1970-01-01
        • 2019-06-16
        • 2017-07-08
        • 1970-01-01
        相关资源
        最近更新 更多