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

假设我有一个主Vue实例,它有子组件。是否有一种方法可以完全从Vue实例外部调用属于这些组件之一的方法?

这里有一个例子:

.
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>

因此,当我单击内部按钮时,increaseCount()方法被绑定到它的click事件,因此它被调用。没有办法将事件绑定到外部按钮,其点击事件,我正在用jQuery监听,所以我需要一些其他的方法来调用increaseCount

编辑

这似乎是可行的:

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

然而,这不是一个好的解决方案,因为我是通过它在子数组中的索引来引用组件的,对于许多组件来说,这不太可能保持不变,代码的可读性也较差。

333392 次浏览

您可以使用Vue事件系统

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

而且

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

这里是小提琴: http://jsfiddle.net/hfalucas/wc1gg5v4/59/ < / p >

最后我选择使用Vue的ref指令。这允许从父组件中引用组件进行直接访问。

如。

在父实例上注册一个组件:

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

在template/html中使用引用渲染组件:

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

现在,在其他地方我可以从外部访问组件

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

请看这个小提琴的例子:https://jsfiddle.net/0zefx8o6/

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

编辑Vue3 -组合API

子组件必须return你想在父组件中使用的setup中的函数,否则该函数对父组件不可用。

注意:<sript setup> 医生不受影响,因为它默认为模板提供了所有的函数和变量。

对于Vue2,这适用于:

var bus = new Vue()

//组件A的方法

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

//组件B创建的钩子

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


// ...
})

Vue docs参见在这里在这里是关于如何确切地设置此事件总线的更详细信息

如果你想了解更多关于何时使用属性、事件和/或集中状态管理的信息,请参阅这篇文章

请看下面托马斯关于Vue 3的评论。

这里有一个简单的例子

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

假设你在子组件中有child_method():

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

现在你想从父组件执行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
}
}
}

如果你想从子组件执行父组件方法:

this.$parent.name_of_method()

注意:不建议像这样访问子组件和父组件。

相反,作为最佳实践使用道具&亲子交流活动。

如果你想要组件之间的通信,一定要使用vuex事件总线

请阅读这非常有用的文章


这是一种从其他组件访问一个组件的方法的简单方法

// 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');
}
}

我使用了一个非常简单的解决方案。我已经包括了一个HTML元素,调用方法,在我的Vue组件,我选择,使用香草JS,我触发点击!

在Vue组件中,我包含了如下内容:

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

我使用香草JS:

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

你可以为子组件设置引用,然后在父组件中调用$refs:

为子组件添加引用:

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

添加点击事件到父:

<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>

一个稍微不同(更简单)的公认答案:

在父实例上注册一个组件:

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

在template/html中使用引用渲染组件:

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

访问组件方法:

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

我不确定这是正确的方式,但这是为我工作 首先导入包含您想在组件

中调用的方法的组件
import myComponent from './MyComponent'

然后调用mycomponent的任何方法

myComponent.methods.doSomething()

有时您希望将这些内容包含在组件中。根据DOM状态(当Vue组件实例化时,监听的元素必须存在于DOM中),您可以从Vue组件内部监听组件外部元素上的事件。假设在组件外部有一个元素,当用户单击它时,您希望组件做出响应。

在html中,你有:

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

在你的Vue组件中:

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

使用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

在组件中像这样声明你的函数:

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

并像这样从任何页面调用它:

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

如果你使用Vue 3和<script setup>糖,注意组件的内部绑定是封闭的(从组件外部不可见),你必须使用defineExpose(参见文档)使它们从外部可见。就像这样:

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


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

使用默认关闭的组件