babel-plugin-react-scope-binding
Developing a React application requires a lot of event binding. Let’s review the React component’s event binding methods.
Take the onClick event as an example
-
The rudest way
class MyComponent extends Component { handleClick(e) { this.setState({ key: 'value' }) } render() { return ( <div onClick={this.handleClick.bind(this)}></div> ) } }Copy the code
Write bind directly into the render method. This is a common beginner’s mistake, causing the bind function to be repeatedly triggered when the component state changes and rerenders, which can seriously affect performance. Avoid this practice.
-
Better way
class MyComponent extends Component { handleClick = e => { this.setState({ key: 'value' }) } render() { return ( <div onClick={this.handleClick}></div> ) } }Copy the code
Using ES7 class attribute arrow functions to automatically bind class scopes requires transform-class-properties support. The disadvantage is that this syntax is experimental and has not been formally standardized, and using class methods as attributes is not recommended.
-
The most reasonable way
class MyComponent extends Component { constructor() { super(a)this.handleClick = this.handleClick.bind(this) } handleClick(e) { this.setState({ key: 'value' }) } render() { return ( <div onClick={this.handleClick}></div> ) } }Copy the code
It makes the most sense to write the bind function into the constructor method and only call it when the component is initialized, binding itself to scope. The downside is that every new event added to the component is bound to the constructor method, which is cumbersome to code.
thinking
Comparing the above three approaches, it is concluded that binding events in Constructor makes the most sense. But where is the pain point? The pain point is that when an app contains a large number of DOM events that need to be accessed by this object, you need to manually unbind event scopes in the constructor method one by one, creating a lot of redundant and repetitive code. So, how to solve this problem? We can use the Babel plug-in to automate scoped binding, reducing unnecessary duplication of labor, simplifying workflows, and improving development efficiency. That’s why I developed the Babel plugin.
With this plugin, you don’t need to manually display the scope of the bound event; the This pointer always points to the component itself.
Therefore, you can write code like the following
class MyComponent extends Component {
handleClick(e) {
this.setState({
key: 'value'
})
}
render() {
return (
<div onClick={this.handleClick}></div>
)
}
}Copy the code
It is even easier to pass parameters when the plug-in’s advanced syntax features are enabled
class MyComponent extends Component {
handleClick(e, val) {
this.setState({
key: 'value'
})
console.log(val) // 'hello'
}
render() {
return (
<div onClick={this.handleClick('hello')}></div>
)
}
}Copy the code
What do plugins do for us?
Look inside the component for the event name to bind to and inject the bind statement into the constructor method. For pass-by syntax, automatically converts to arrow function, similar to (e) => {this.handleclick (e, item)}
Realize the principle of
Babel is a JavaScript grammar translator. The workflow can be roughly understood as converting strings of code into tokens flow through lexical analysis, then parsing the tokens flow into an abstract syntax tree, and then entering the transformation stage, deeply traversing the abstract syntax tree. Adding, deleting, and changing nodes is part of your Babel plugin’s job, parsing the translated abstract syntax tree and generating the text of the target string.
Each node in the abstract syntax tree can be described as a JavaScript object, containing the node type and several other properties that your Babel plug-in can change or simply replace, delete, or insert newly constructed nodes, helping us do more with the idea of plug-in visitor injection.
Source code address: github.com/chikara-cha…
Did this article help you? Welcome to join the front End learning Group wechat group: