1. Try not to write the inline script in the template if there are more than 2 lines of code
VSCode cannot check any syntax error of the inline script in the template. So try not to write the inline script in the template. If you write the inline script in the template, it's no different than writing code in Notepad. There are 2 drawbacks:
VS Code cannot check the syntax error
If you are using Typescript
, VS Code
can identify the syntax error for you. You might think I'd be able to spot those syntax errors, but actually, we don't. For example, in this code, the inline script only has 2 lines of code.
<div @click="alert('hello world'); doSomething();" />
The even handler is
doSomething(event: Event) {
// do something ...
}
There is no errors in VS Code
. But when you run this code, you will find that the event
parameter is undefined
.
If you extract the line move console.log('do something'); doSomething();
into a method sayHelloAndDoSomething()
sayHelloAndDoSomething() {
console.log('do something');
this.doSomething();
}
Then you will see there is an error
It turns out that doSomething
has a required parameter event
. The worse thing is this inline script seems to be working fine. But the parameter event
of doSomething
arguments is undefined
. We create a defect in this way. This example looks dumb. But there similar cases I've met at work.
Hard to debug the code in production
The inline script will be compiled in 1 line js code in production. It's not able to debug this code. If you put the code in a method/computed of the component. You can still be able to debug it even it's already minified.
If there is an error, we can still debug this code. It's not difficult to know what is the e
or n
variable based on the source code.
Imagine how convenient it will be if you can debug the code in production. That really help me for several times. So try to extract inline script code into component method/computed, it will help you eventually.
2. Try not to use watcher
Vue.js documentation already suggest us not to use watcher.
Why? Because watcher is an implicit dependency. Implicit dependency brings the following problems:
- Logic becomes more scattered, and there is no explicit correlation between them. It makes it difficult to understand the code. This is especially difficult when troubleshooting.
- When you update the feature, you won't be able to notice that somewhere a logic has been broken. Just because this logic is triggered by a watcher.
In addition to the problems brought by implicit dependencies, watcher
has other problems of his own:
- The watcher won't be triggered when Vue.js rendering the component as
watch
is lazy by default unless you useimmediate: true
. So if you expect some logic in a watcher will be called whenv-if
turn totrue
, you may be disappointed. We did meet a defect caused by this. - The watcher cannot be paused. Sometimes we don't want to disable the watcher, we just want to pause it. Unfortunately, watcher doesn't provide the pause feature. this comment mentioned that the only way to pause the watcher is doing a conditional check. When I have a similar problem at work, I usually add a flag like
watcherEnabled
to pause the watchers in some scenarios. But this flag also brought me some defects.
There are 5 better approaches than watcher
From child to parent
Use custom events
If you need to trigger the method of the parent component. You can use custom event
From parent to child
Move method from child to parent
If the metod you want to trigger is in child method. Instead of using $refs
, it will be better to move the method to the parent component. Then you can directly call it or use custom event
Use ref attribute
If the method you want to trigger cannot be moved to the parent. Or you don't want to take the risk to refactor the task. You can use ref attribute
But remember that using $refs
is not a good practice. $refs has its own problem as well. The component $refs
is undefined
when the component is rendering. So if you use $refs
it in the template, it might be undefined. If you are using $refs
in the computed
. The computed
might be broken. For example, there is a computed
to get the child component scrollLeft attribute.
get childScollLeft() {
return this.$refs.child.scrollLeft;
}
This computed
won't work as you expect. Because when the variable you want to watch in the computed is undefined at the beginning, then this computed will not be reactive. Not even after the $refs
loaded.
Use props
If you want to update the child component UI. You can use props
From anywhere
Use Vuex
If you want to update the parent/child/sibling component UI. You can use Vuex. The only downside is that this may increase code complexity.
3. Try not to pass functions as props
Passing functions as props an anti-pattern in Vue.js. There is a sentence in the article that is really good.
As the application grows larger in size and other developers come on board, they will look at the child component code and have to figure out which callback function prop it is and where it is from.
That's the issue that I meet in my project. Sometimes I need to figure out where are those methods come from.
I agree with it. But this is not the main reason I don't recommend passing functions as props. The main reason is when I read the code it takes some effort to get familiar with the context of this component. If there is a function was passed as a prop, then I need to be familiar with the context of another component. If that were all it was, it wouldn't be so bad. The worse is I need to switch between different components contexts when reading the method.
I recommend using custom event instead of passing functions as props.
Top comments (0)