在Vue中,你可以传递字符串、数组、数字和对象作为props。
但是你能传递一个函数作为道具吗?
虽然你可以传递一个函数作为道具,但这几乎总是一个坏主意。相反,Vue可能有一个特性是专门为解决你的问题而设计的。
在这篇文章中,我将向您展示:
- 如何传递函数作为道具-即使你可能不应该
- 为什么React和Vue在传递方法作为props时不同
- 为什么事件或作用域插槽可能是更好的解决方案
- 如何在子组件中访问父组件的作用域
作用域槽通常是这里的正确答案,但让我们首先介绍一下为什么在Vue中不传递函数。
将函数作为道具传递
获取一个函数或方法并将其作为prop传递给子组件是相对简单的。实际上,它与传递任何其他变量完全相同:
Parent.vue
xml
<template>
<ChildComponent :function="myFunction" />
</template>
<script setup>
const myFunction () => {
// ...
}
</script>
但正如我之前所说,这是你永远不应该在Vue中做的事情。
为什么?为什么?
好吧,Vue有更好的东西...
使用事件
事件是我们在Vue中与父组件通信的方式。
这里有一个简短的例子来说明事件是如何工作的。
首先,我们将创建子组件,它在创建时发出一个事件:
ChildComponent.vue
ini
const emit = defineEmits(['created']);
emit('created');
在我们的父组件中,我们将监听该事件:
Parent.vue
xml
<template>
<ChildComponent @created="handleCreate" />
</template>
<script setup>
const handleCreate = () => {
console.log('Child has been created.');
};
</script>
有很多事情可以通过事件来完成,而这只是触及表面。我强烈建议你查看官方的Vue文档来了解更多关于事件的信息。绝对值得一读!
但事件并不能完全解决我们所有的问题。
从子组件中移除父组件的作用域
在许多情况下,您试图解决的问题是从不同的范围访问值。
父组件有一个作用域,子组件有另一个作用域。
通常,您希望从父组件访问子组件中的值,或者从子组件访问父组件中的值。
Vue阻止我们直接这样做,这是一件好事。
它使我们的组件更加封装,并提高其可重用性。这使你的代码更干净,从长远来看可以防止很多麻烦。
但是您可能会尝试将函数作为props来传递,以解决这个问题。
从父级获取值
如果你想让一个子组件访问父组件的方法,那么很明显,直接把方法作为一个道具传递下去就行了。
然后孩子可以立即访问它,并可以直接使用它。
在parent组件中,我们可以这样做:
Parent.vue
xml
<template>
<ChildComponent :method="parentMethod" />
</template>
<script setup>
const parentMethod = () => {
// ...
};
</script>
在我们的子组件中,我们将使用该方法:
ChildComponent.vue
javascript
import { onMounted } from 'vue';
const props = defineProps({
method: {
type: Function,
}
});
// Call the method
onMounted(() => props.method());
那有什么不对的
这并不完全是错的,但在这种情况下使用事件要好得多。
然后,子组件在需要时不会调用函数,而只是发出一个事件。然后父组件将接收该事件,调用该函数,然后传递给子组件的属性将被更新。
这是达到同样效果的更好方法。
从子对象获取值
在其他情况下,我们可能想从子对象中获取一个值到父对象中,我们正在使用函数。
例如,你可能会这样做。parent的函数接受来自child的值,并对它做一些事情:
Parent.vue
xml
<template>
<ChildComponent :method="parentMethod" />
</template>
<script setup>
const parentMethod = (valueFromChild) => {
// Do something with the value
console.log('From the child:', valueFromChild);
}
</script>
在子组件中,当调用它时传入值的位置:
ChildComponent.vue
javascript
import { ref, onMounted } from 'vue';
const props = defineProps({
method: {
type: Function,
}
});
const message = ref('A message from the child component');
onMounted(() => {
// Pass a value to the parent through the function
props.method(message.value);
});
再说一次,这并不是完全错误的。
这样做是可行的。
只是这不是在Vue中做事情的最佳方式。相反,事件更适合解决这个问题。
我们可以使用事件来实现同样的事情:
Parent.vue
xml
<template>
<ChildComponent @send-message="handleSendMessage" />
</template>
<script setup>
const handleSendMessage = (event, value) => {
// Our event handler gets the event, as well as any
// arguments the child passes to the event
console.log('From the child:', value);
};
</script>
在子组件中,我们发出事件:
ChildComponent.vue
csharp
import { ref, onMounted } from 'vue';
const emit = defineEmits(['send-message'])
const message = ref('A message from the child component');
onMounted(() => {
// Pass a value to the parent through the function
emit('send-message', message.value);
});
事件在Vue中非常有用,但它们也不能100%解决我们的问题。
有时我们需要以不同的方式从父级访问子级的作用域。