I have the following code in a Nuxtjs app in SSR mode.
<Component
:is="author.linkUrl ? 'a' : 'div'"
v-bind="!author.linkUrl && { href: author.linkUrl, target: '_blank' }"
@click="author.linkUrl ? handleAnalytics() : null"
>
The click event in case it's an a
tag, will only fire if it's written as handleAnalytics()
, but handleAnalytics
will not work.
Don't get me wrong the code is working, but I don't understand why.
CodePudding user response:
In javascript functions are a reference to an object. Just like in any other language you need to store this reference in memory.
Here are a few examples that might help you understand on why its not working:
function handleAnalytics() { return 'bar' };
const resultFromFunction = handleAnalytics();
const referenceFn = handleAnalytics;
resultFromFunction
will have bar
as it's value, while referenceFn
will have the reference to the function handleAnalytics
allowing you to do things like:
if (someCondition) {
referenceFn();
}
A more practical example:
function callEuropeanUnionServers() { ... }
function callAmericanServers() { ... }
// Where would the user like for his data to be stored
const callAPI = user.preferesDataIn === 'europe'
? callEuropeanUnionServers
: callEuropeanUnionServers;
// do some logic
// ...
// In this state you won't care which servers the data is stored.
// You will only care that you need to make a request to store the user data.
callAPI();
In your example what happens is that you are doing:
@click="author.linkUrl ? handleAnalytics() : null"
What happens in pseudo code is:
- Check the author has a
linkUrl
- If yes, then EXECUTE
handleAnalytics
first and then the result of it pass to handler@click
- If not, simply pass
null
Why it works when you use handleAnalytics
and not handleAnalytics()
?
- Check the author has a
linkUrl
- If yes, then pass the REFERENCE
handleAnalytics
to handler@click
- If not, simply pass
null
Summary
When using handleAnalytics
you are passing a reference to @click
. When using handleAnalytics()
you are passing the result returned from handleAnalytics
to @click
handler.
CodePudding user response:
With classical event binding (@click="handleAnalytics
), Vue will auto bind it for you because it sees it's a function.
But when provided a ternary condition, it's not auto binded but wrapped into a anonymous function instead. So you have to call it with parenthesis otherwise you're just returning the function without executing it.
To be clearer, you can write it this way: @click="() => author.linkUrl ? handleAnalytics() : null"
Note: when having a dynamic tag component, I'd suggest to use the render
function instead.
This is an advanced technique, but this way you won't bind things to an element that doesn't need it (without having the kind of hack to return null
).
Example:
export default {
props: {
author: { type: Object, required: true },
},
render (h: CreateElement) {
const renderLink = () => {
return h('a', {
attrs: {
href: author.linkUrl,
target: '_blank',
},
on: {
click: this.handleAnalytics
},
)
}
const renderDiv = () => {
return h('div')
}
return this.author.linkUrl ? renderLink() : renderDiv()
}
}