js 中的函数对象#
要注意区分 funcName()
和 funcName
当我们定义了函数
function addOne(num){
return num++
}
那么 addOne(1)
相当于执行该函数一次。
而 addOne
则是表示函数对象本身。举个例子
let tempFunc = addOne // tempFunc 也是函数,等价于 addOne
let tempResult = addOne(5) // tempResult 为 6
当我们的函数没有参数时,这两种情况更不易区分。
function printHello(){
console.log("Hello")
}
// ---------
printHello() // 1 执行函数,打印出Hello
let great = printHello // great 等同于 printHello
great() // 等价于 1
这个区别在 web 事件处理中很关键。举个例子(vue)
<script setup>
function handleMyEvent(){
console.log("hello")
}
</script>
<template>
<!-- 这里假设有一个自定义组件,内部Emit出事件myEvnet -->
<myComponent @myEvent="handleMyEvent"></myComponent>
<myComponent @myEvent="handleMyEvent()"></myComponent>
<myComponent @myEvent="console.log('hello')"
</template>
上面的代码,第一个组件将事件绑定了一个回调函数,第二个组件则是在事件触发后,执行函数体(打印 hello), 等价于第三个组件。
而我们的组件内部抛出的事件是可以带参数的。当抛出事件带参数时,只有第一种写法可以正确接受参数,此时需要在handleMyEvnet(id)
函数定义时接收参数即可。
下面是几种写法的辨析
<script setup>
const id = ref(1)
const name = ref("David")
function handleEvent(id, name){
console.log(id + ' ' + name)
}
</script>
<template>
<!-- 子组件中 defineEmits(['myEvent', id, name]) -->
<myComponent @myEvent="handleEvnet"></myComponent> <!--✅-->
<myComponent @myEvent="handleEvnet(id,name)"></myComponent> <!-- ❌ -->
<myComponent :id="id" :name="name" @myEvent="handleEvent(id,name)"></myComponen>
<myComponent :id="id" :name="name" @myEvent="handleEvent"></myComponen>
</template>
第三种写法虽然可以正常工作,但当事件触发,其参数并不是从组件内部传递出来的,而是直接将本层组件中的id name
作为参数,执行了函数体。
第四种写法则是,接收了来自子组件内部传递出的参数。
总结#
在父子组件之间传递数据是,要注意不要进行冗余传递。第四种写法虽然可以工作,但是如果该信息在副组件就有,第三种写法要更优。
Vue 监听器#
⚠️ 监听组件属性时,需要传递 getter,而不能直接使用 props.name 的方式。
<script setup>
const props = defineProps(['id','name'])
watch(()=>props.id, function(newValue, oldValue){
// ...
})
</script>