Do NOT throw warning when assigment in `v-if` happens
See original GitHub issueWhat problem does this feature solve?
[UPDATE] I borrowed the idea “Optional Binding” from Swift which is famous. Unfortunately, this makes the topic astray… Please be noted that the real core here is “assigment in v-if
”.
First off, what is “Optional Binding”?
Sounds fashionable. Yes, it is, in Swift.
In case you don’t quite recall, below is the statement of this useful feature of Swift:
if let constantName = someOptional {
statements (using that constantName)
}
Which is also called “if let” statement.
And the doc is here: https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html#ID333
So, what’s its counterpart in Vue?
For example:
I have data of a list of trainees and a dictionary of training records.
For some reason, the two are separated.
I have to check if a trainee has records, and if so, show details of the records.
.trainee-cards
.trainee-card(v-for="trainee in trainees" key="trainee.id")
.trainee-name {{trainee.name}}
section.training-records
.training-records-details(v-if="training-records-by-trainee[trainee.id]")
.count Count: {{training-records-by-trainee[trainee.id].count}}
.last-date Last trained on {{training-records-by-trainee[trainee.id].recent-records[training-records-by-trainee[trainee.id].recent-records.length - 1].date}}
.recent-records
.record(v-for="record in training-records-by-trainee[trainee.id].recent-records")
... (a line chart of last 5 trainings) ...
.no-records(else) No records yet.
You can see training-records-by-trainee[trainee.id]
is used many times and the codes are terribly long and messy.
This example is a bit extreme, but you can get the idea.
The good news is: we can assign a local variale in v-if!
...
.training-records-details(v-if="record-data = training-records-by-trainee[trainee.id]")
.count Count: {{record-data.count}}
.last-date Last trained on {{record-data.recent-records[record-data.recent-records.length - 1].date}}
.recent-records
.record(for="record in record-data.recent-records")
... (a line chart of last 5 trainings) ...
This makes life much easier.
Alternatives?
Yes, I know, we can always use a component to handle record-data
.
But that would be overkill, unless the component can be reused.
Another way to ease the pain would be baking data beforehand.
For example,
data: function(){
trainees.forEach((trainee)=>{
trainee.record-data = training-records-by-trainee[trainee.id]
});
return {
trainees
};
Then we can write trainee.record-data
.
Neeter than training-records-by-trainee[trainee.id]
, but not as neet as “optional binding”.
So, what’s the problem?
This “optional binding” already works well and is as helpful just as in Swift.
Then, here’s the bad news: it invites such a warning (actually, a red error):
[Vue warn]: Property or method "record-data" is not defined on the instance but referenced during render.
This is an eyesore.
What does the proposed API look like?
Just make vue recognize optional binding and thus do not warn about the local variable, which IS “defined on the instance”.
Possible controversy
Some people may dislike the idea of “allowing” or even “encouraging” assignment in if
condition.
An example is issue #7631: “warn when assignment in v-if in development mode”
As @posva said, “this is a js common pitfall for beginners” to mistakenly write “=” when they actually want “==”.
And they usually would lean the lesson in hard way, having paid much for such mistakes.
I was one of them, of course. So I know how natural it is to have a reflexive aversion to “optional binding” when learning Swift.
But after a while, I realized we should not object to a very good thing only because of some other mistake, which is not its fault.
In pure js, even today, you can still make such a mistake like if(a = b){console.log(a);}
, and you get a global window.a
as an unexpected result.
I hope someday “strict mode” will forbid this noxious pitfall and optional binding will be introduced into JavaScript, just like “for let” which already is in ES5.
Anyway, in vue, there is no worry about mistakenly creating a global variale via assignment in v-if.
No matter why, vue has the feature “optional binding” already, partially but effectively!
It is just unknown to the public. It is a hidden gem.
And that warning makes developers feel uneasy, although it is not a result of intention of guarding “=” in “v-if” at all.
Issue Analytics
- State:
- Created 4 years ago
- Comments:22 (9 by maintainers)
Top GitHub Comments
I’d rather use
computed
to create a better data structure for your case, with properfilter
/map
transformations on the original input. It’ll look much cleaner than doing all the heavy work inside templates.That’s probably not gonna happen…it’s only in Stage 1.