简体   繁体   English

从组件外部调用 Vue.js 组件方法

[英]Call a Vue.js component method from outside the component

Let's say I have a main Vue instance that has child components.假设我有一个包含子组件的主 Vue 实例。 Is there a way of calling a method belonging to one of these components from outside the Vue instance entirely?有没有办法完全从 Vue 实例外部调用属于这些组件之一的方法?

Here is an example:这是一个例子:

 var vm = new Vue({ el: '#app', components: { 'my-component': { template: '#my-template', data: function() { return { count: 1, }; }, methods: { increaseCount: function() { this.count++; } } }, } }); $('#external-button').click(function() { vm['my-component'].increaseCount(); // This doesn't work });
 <script src="http://vuejs.org/js/vue.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="app"> <my-component></my-component> <br> <button id="external-button">External Button</button> </div> <template id="my-template"> <div style="border: 1px solid; padding: 5px;"> <p>A counter: {{ count }}</p> <button @click="increaseCount">Internal Button</button> </div> </template>

So when I click the internal button, the increaseCount() method is bound to its click event so it gets called.所以当我点击内部按钮时, increaseCount()方法被绑定到它的点击事件,所以它被调用。 There is no way to bind the event to the external button, whose click event I am listening for with jQuery, so I'll need some other way to call increaseCount .无法将事件绑定到外部按钮,我正在使用 jQuery 监听其单击事件,因此我需要一些其他方法来调用increaseCount

EDIT编辑

It seems this works:似乎这有效:

vm.$children[0].increaseCount();

However, this is not a good solution because I am referencing the component by its index in the children array, and with many components this is unlikely to stay constant and the code is less readable.但是,这不是一个好的解决方案,因为我通过子数组中的索引引用组件,并且对于许多组件,这不太可能保持不变并且代码的可读性较差。

In the end I opted for using Vue's ref directive .最后我选择了使用Vue 的ref指令 This allows a component to be referenced from the parent for direct access.这允许从父级引用组件以进行直接访问。

Eg例如

Have a compenent registered on my parent instance:在我的父实例上注册了一个组件:

var vm = new Vue({
    el: '#app',
    components: { 'my-component': myComponent }
});

Render the component in template/html with a reference:使用引用在 template/html 中渲染组件:

<my-component ref="foo"></my-component>

Now, elsewhere I can access the component externally现在,我可以在其他地方从外部访问组件

<script>
vm.$refs.foo.doSomething(); //assuming my component has a doSomething() method
</script>

See this fiddle for an example: https://jsfiddle.net/xmqgnbu3/1/看这个小提琴的例子: https ://jsfiddle.net/xmqgnbu3/1/

(old example using Vue 1: https://jsfiddle.net/6v7y6msr/ ) (使用 Vue 1 的旧示例: https ://jsfiddle.net/6v7y6msr/)

Edit for Vue3 - Composition API为 Vue3 编辑 - 组合 API

The child-component has to return the function in setup you want to use in the parent-component otherwise the function is not available to the parent.子组件必须在setupreturn要在父组件中使用的函数,否则该函数对父组件不可用。

Note: <sript setup> doc is not affacted, because it provides all the functions and variables to the template by default.注意: <sript setup> doc不受影响,因为它默认为模板提供了所有的函数和变量。

You can set ref for child components then in parent can call via $refs:您可以为子组件设置 ref,然后在父组件中可以通过 $refs 调用:

Add ref to child component:将 ref 添加到子组件:

<my-component ref="childref"></my-component>

Add click event to parent:向父级添加点击事件:

<button id="external-button" @click="$refs.childref.increaseCount()">External Button</button>

 var vm = new Vue({ el: '#app', components: { 'my-component': { template: '#my-template', data: function() { return { count: 1, }; }, methods: { increaseCount: function() { this.count++; } } }, } });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <my-component ref="childref"></my-component> <button id="external-button" @click="$refs.childref.increaseCount()">External Button</button> </div> <template id="my-template"> <div style="border: 1px solid; padding: 2px;" ref="childref"> <p>A counter: {{ count }}</p> <button @click="increaseCount">Internal Button</button> </div> </template>

For Vue2 this applies:对于 Vue2 这适用:

var bus = new Vue()

// in component A's method // 在组件 A 的方法中

bus.$emit('id-selected', 1)

// in component B's created hook // 在组件 B 的 created 钩子中

bus.$on('id-selected', function (id) {

  // ...
})

See here for the Vue docs.有关 Vue 文档,请参见此处 And here is more detail on how to set up this event bus exactly.这里有更多关于如何准确设置这个事件总线的细节。

If you'd like more info on when to use properties, events and/ or centralized state management see this article .如果您想了解有关何时使用属性、事件和/或集中状态管理的更多信息,请参阅这篇文章

See below comment of Thomas regarding Vue 3.请参阅以下 Thomas 关于 Vue 3 的评论。

You can use Vue event system可以使用 Vue 事件系统

vm.$broadcast('event-name', args)

and

 vm.$on('event-name', function())

Here is the fiddle: http://jsfiddle.net/hfalucas/wc1gg5v4/59/这是小提琴:http: //jsfiddle.net/hfalucas/wc1gg5v4/59/

A slightly different (simpler) version of the accepted answer:接受答案的稍微不同(更简单)的版本:

Have a component registered on the parent instance:在父实例上注册一个组件:

export default {
    components: { 'my-component': myComponent }
}

Render the component in template/html with a reference:使用引用在 template/html 中渲染组件:

<my-component ref="foo"></my-component>

Access the component method:访问组件方法:

<script>
    this.$refs.foo.doSomething();
</script>

Say you have a child_method() in the child component:假设您在子组件中有一个child_method()

export default {
    methods: {
        child_method () {
            console.log('I got clicked')
        }
    }
}

Now you want to execute the child_method from parent component:现在你想从父组件执行child_method

<template>
    <div>
        <button @click="exec">Execute child component</button>
        <child-cmp ref="child"></child_cmp> <!-- note the ref="child" here -->
    </div>
</template>

export default {
    methods: {
        exec () { //accessing the child component instance through $refs
            this.$refs.child.child_method() //execute the method belongs to the child component
        }
    }
}

If you want to execute a parent component method from child component:如果要从子组件执行父组件方法:

this.$parent.name_of_method()

NOTE: It is not recommended to access the child and parent component like this.注意:不建议像这样访问子组件和父组件。

Instead as best practice use Props & Events for parent-child communication.相反,作为最佳实践,使用 Props & Events 进行父子通信。

If you want communication between components surely use vuex or event bus如果你想在组件之间进行通信,一定要使用vuex事件总线

Please read this very helpful article请阅读这篇非常有用的文章


This is a simple way to access a component's methods from other component这是从其他组件访问组件方法的简单方法

// This is external shared (reusable) component, so you can call its methods from other components

export default {
   name: 'SharedBase',
   methods: {
      fetchLocalData: function(module, page){
          // .....fetches some data
          return { jsonData }
      }
   }
}

// This is your component where you can call SharedBased component's method(s)
import SharedBase from '[your path to component]';
var sections = [];

export default {
   name: 'History',
   created: function(){
       this.sections = SharedBase.methods['fetchLocalData']('intro', 'history');
   }
}

这是一个简单的

this.$children[indexOfComponent].childsMethodName();

Using Vue 3:使用 Vue 3:

const app = createApp({})

// register an options object
app.component('my-component', {
  /* ... */
})

....

// retrieve a registered component
const MyComponent = app.component('my-component')

MyComponent.methods.greet();

https://v3.vuejs.org/api/application-api.html#component https://v3.vuejs.org/api/application-api.html#component

I am not sure is it the right way but this one works for me.我不确定它是否正确,但这个方法对我有用。
First import the component which contains the method you want to call in your component首先导入包含您要在组件中调用的方法的组件

import myComponent from './MyComponent'

and then call any method of MyCompenent然后调用 MyCompenent 的任何方法

myComponent.methods.doSomething()

Declare your function in a component like this:在这样的组件中声明您的函数:

export default {
  mounted () {
    this.$root.$on('component1', () => {
      // do your logic here :D
    });
  }
};

and call it from any page like this:并从这样的任何页面调用它:

this.$root.$emit("component1");

Sometimes you want to keep these things contained within your component.有时您希望将这些内容包含在您的组件中。 Depending on DOM state (the elements you're listening on must exist in DOM when your Vue component is instantiated), you can listen to events on elements outside of your component from within your Vue component.根据 DOM 状态(当您的 Vue 组件被实例化时,您正在侦听的元素必须存在于 DOM 中),您可以在 Vue 组件内侦听组件外部元素上的事件。 Let's say there is an element outside of your component, and when the user clicks it, you want your component to respond.假设您的组件外部有一个元素,当用户单击它时,您希望您的组件做出响应。

In html you have:在 html 中,您有:

<a href="#" id="outsideLink">Launch the component</a>
...
<my-component></my-component>

In your Vue component:在您的 Vue 组件中:

    methods() {
      doSomething() {
        // do something
      }
    },
    created() {
       document.getElementById('outsideLink').addEventListener('click', evt => 
       {
          this.doSomething();
       });
    }
    

If you're using Vue 3 with <script setup> sugar, note that internal bindings of a component are closed (not visible from outside the component) and you must use defineExpose (see docs ) to make them visible from outside.如果您将 Vue 3 与<script setup>糖一起使用,请注意组件的内部绑定是关闭的(从组件外部不可见),您必须使用defineExpose (请参阅docs )使它们从外部可见。 Something like this:像这样的东西:

<script setup lang="ts">
const method1 = () => { ... };
const method2 = () => { ... };

defineExpose({
  method1,
  method2,
});
</script>

I have used a very simple solution.我使用了一个非常简单的解决方案。 I have included a HTML element, that calls the method, in my Vue Component that I select, using Vanilla JS, and I trigger click!我使用 Vanilla JS 在我选择的 Vue 组件中包含了一个调用该方法的 HTML 元素,然后触发点击!

In the Vue Component, I have included something like the following:在 Vue 组件中,我包含了如下内容:

<span data-id="btnReload" @click="fetchTaskList()"><i class="fa fa-refresh"></i></span>

That I use using Vanilla JS:我使用Vanilla JS:

const btnReload = document.querySelector('[data-id="btnReload"]');
btnReload.click();                

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM