current position:Home>Why is JSX syntax so popular?
Why is JSX syntax so popular?
2022-06-24 09:47:46【Bai Xiaobai】
Keep creating , Accelerate growth ! This is my participation 「 Nuggets day new plan · 6 Yuegengwen challenge 」 Of the 9 God , Click to see the event details
Preface
Nowadays, although access JSX The framework of grammar (React、Vue) More and more , But there is no doubt that the deepest fate is still React.2013 year , When React With JSX When Hengkong was born , The community used to JSX There has been a lot of controversy , But now , More and more people are facing JSX Say the last sentence “ It's delicious ”! Typical “ It's delicious ” series .
JSX What is it? ?
according to React Official explanation ,JSX It's a JavaScript Grammar extension of , Similar to template syntax , Or something like XML Of ECMAScript Grammar extension , And have JavaScript All the functions of .
There are two key points in this explanation :
- 「JavaScript Grammar extension 」
- 「 Have JavaScript All the functions of 」
JSX The location is JavaScript Of 「 Grammar extension 」, instead of “ A version ”, This determines that the browser will not be like natural support JavaScript As support JSX . This raises a question “JSX How is the JavaScript In effect ?”
JSX How grammar works in JavaScript In effect ?
React
stay React In the frame ,JSX How is the grammar of JavaScript In effect ?React The explanation given on the official website is ,JSX Will be compiled as React.createElement(), React.createElement() Will return a message called “React Element” Of JS object .
about JSX Is compiled by Babel To complete .
Babel It's a tool chain , It's mainly used to use ECMAScript 2015+ Syntax written code into backward compatible JavaScript grammar , To be able to run in current and older browsers or other environments .
Of course Babel Also have the ability to JSX Convert to JS The ability of , Take an example : On the left is us React The syntax written in the development , And it contains a paragraph JSX Code . after Babel After the transformation , It's all about JS Code .
In fact, if you look carefully , Find out JSX More like a grammar sugar , It is described in a way similar to template syntax , Describe function objects . Actually in React Is not mandatory in JSX grammar , We can also use React.createElement function , For example, using React.createElement Function to write such a piece of code .
class Test extends React.Component {
render() {
return React.createElement(
"div",
null,
React.createElement(
"div",
null,
"Hello, ",
this.props.test
),
React.createElement("div", null, "Today is a fine day.")
);
}
}
ReactDOM.render(
React.createElement(Test, {
test: "baixiaobai"
}),
document.getElementById("root")
);
When using JSX after , This code will be written like this :
class Test extends React.Component {
render() {
return (
<div> <div>Hello, {this.props.test}</div> <div>Today is a fine day.</div> </div>
);
}
}
ReactDOM.render(
<Test test="baixiaobai" />,
document.getElementById('root')
);
Through comparison, we found that , On the premise that the actual function effect is consistent ,JSX The code is hierarchical 、 The nesting relationship is clear ; and React.createElement The code gives a very confusing “ Hybridity ”, Such code is not only unfriendly to read , It's hard to write .
JSX The code written by syntax is more concise , And the code structure is more clear .
JSX Syntax sugar allows us developers to write like HTML To write our JS Code . It not only reduces the learning cost, but also improves our R & D efficiency and R & D experience .
Vue
Of course. Vue The framework is no exception JSX grammar , although Vue The default recommended template is still .
Why default recommended template syntax , Quote a paragraph Vue The original words of the official website are as follows :
Any standard HTML It's all legal Vue Templates , This also brings some unique advantages :
- For a lot of people who are used to HTML For the developers , Template is better than JSX It's more natural to read and write . There is, of course, an element of subjective preference , But if this difference leads to an increase in development efficiency , Then it has objective value .
- be based on HTML Make the existing application migrate to Vue It's easier .
- It also makes it easier for designers and new developers to understand and participate in projects .
- You can even use other template preprocessors , such as Pug To write Vue The template of .
Some developers think templates mean learning extra DSL (Domain-Specific Language Domain specific language ) To develop —— We think the difference is superficial . First ,JSX It's not that there's no learning cost —— It is based on JS An extra set of grammars on top of . meanwhile , Just as familiar with JS People learn JSX It's going to be as easy as , be familiar with HTML People learn Vue The template syntax is also very easy . Last ,DSL We can let developers do more with less code , such as v-on All kinds of modifiers for , stay JSX It takes a lot more code to implement the corresponding function in .
More abstract , We can divide components into two categories : One is the partial view (presentational), One is partial logic (logical). We recommend using templates in the former , In the latter use JSX Or render functions . The proportion of these two types of components will vary according to the application type , But on the whole, we find that the components of presentation class are far more than those of logic class .
For example, there is a template syntax .
<anchored-heading :level="1">
<span>Hello</span> world!
</anchored-heading>
Use JSX The grammar will be written like this .
render: function (h) {
return (
<AnchoredHeading level={1}> <span>Hello</span> world! </AnchoredHeading>
)
}
Convert to createElement The conversion JS That's how it became .
createElement(
'anchored-heading', {
props: {
level: 1
}
}, [
createElement('span', 'Hello'),
' world!'
]
);
But whether it's template syntax or JSX grammar , Will not get the browser's natural support , These grammars will eventually be compiled into corresponding h function (createElement function , Not all versions , There are differences in different versions ) Finally become JS object , The compilation here is also the same as React The same thing Babel plug-in unit To complete .
Whether it's React Highly esteems JSX grammar , still Vue Default template syntax , Purpose To make our code more concise , And the code interface level is more clear . It not only reduces the learning cost, but also improves our R & D efficiency and R & D experience .
Read here , I believe you have fully understood “JSX yes JavaScript A grammatical extension of , It's very close to the template language , And have JavaScript All the functions of . ” The meaning behind this definition .
Whether it's React still Vue We all mentioned a function createElement, This function is to put our JSX It maps to DOM Of .
JSX How to map to DOM Of : Bottom up createElement Source code
about creatElement Source code analysis , We also share React and Vue To interpret .
There is no need to discuss the specific version of source code analysis in too much detail , Because it doesn't matter React still Vue For implementing createElement There is little difference between different versions of .
React
export function createElement(type, config, children) {
// propName Variables are used to store the element attributes that need to be used later
let propName;
// props Variable is used to store the collection of key value pairs of element attributes
const props = {};
// key、ref、self、source Are all React Attribute of element , There is no need to delve into
let key = null;
let ref = null;
let self = null;
let source = null;
// config Object stores the attributes of the element
if (config != null) {
// The first thing you do when you come in , Yes, in turn ref、key、self and source Attribute assignment
if (hasValidRef(config)) {
ref = config.ref;
}
// Here will be key Value string
if (hasValidKey(config)) {
key = '' + config.key;
}
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source;
// The next step is to config The properties inside are moved to one by one props In this previously declared object
for (propName in config) {
if (
// Filter out items that can be brought into props Attributes in objects
hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName];
}
}
}
// childrenLength It refers to the number of child elements of the current element , Subtracted 2 yes type and config The length occupied by the two parameters
const childrenLength = arguments.length - 2;
// If you throw away type and config, There is only one parameter left , Generally, it means that the text node appears
if (childrenLength === 1) {
// Directly assign the value of this parameter to props.children
props.children = children;
// Handle the case of nesting multiple child elements
} else if (childrenLength > 1) {
// Declare an array of child elements
const childArray = Array(childrenLength);
// Push the child elements into the array
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
// Finally, assign this array to props.children
props.children = childArray;
}
// Handle defaultProps
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
// Finally, it returns a call ReactElement Execution method , And pass in the parameters just processed
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
}
createElement Function has 3 Input parameters , this 3 The input parameter contains the one we are creating React All information about the element .
- type: Used to identify the type of node . It can be original div 、span In this way HTML label , It can also be React Components , It can also be React fragment( Empty elements ).
- config: An object , All properties of the component ( Does not contain some default properties ) Will be stored in the form of key value pairs config In the object .
- children: It generally refers to all parameters after the second parameter , It records the content nested between component tags , It's called “ Child node ”“ Subelement ”.
From the source point of view ,createElement Function is the data written by the R & D personnel during development 、 attribute 、 Parameters are formatted in one layer , Turn into React Easy to understand parameters , And then deliver it to ReactElement To implement element creation .
So let's see ReactElement function
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// Mark this is a React Element
$$typeof: REACT_ELEMENT_TYPE,
type: type,
key: key,
ref: ref,
props: props,
_owner: owner,
};
return element;
};
The source code is exceptionally simple , That is to say createElement Function conversion parameters , In one process , Packing in element Object to the developer . If you try to return this ReactElement For the output , You will find that there is no very familiar feeling , you 're right , This is what we always talk about 「 fictitious DOM」,JavaScript Object pair DOM Description of .
Finally through ReactDOM.render Method will be virtual DOM Render to the specified container .
Vue
Vue 2
Let's see Vue How to map DOM Of .
export function createElement ( context: Component, tag: any, data: any, children: any, normalizationType: any, alwaysNormalize: boolean ): VNode | Array<VNode> {
...
return _createElement(context, tag, data, children, normalizationType)
}
createElement Function is to _createElement An encapsulation of functions , It allows more flexibility in the parameters passed in , After processing these parameters , Call to really create VNode Function of _createElement:
export function _createElement ( context: Component, tag?: string | Class<Component> | Function | Object, data?: VNodeData, children?: any, normalizationType?: number ): VNode | Array<VNode> {
...
return vnode;
}
_createElement There are methods 5 Parameters :
- context Express VNode Context of .
- tag It means label , It can be a string , It can also be a Component.
- data Express VNode The data of .
- children At present VNode Child nodes of , It's any type of , It then needs to be standardized VNode Array .
- normalizationType Indicates the type of child node specification , Different types of specifications have different methods , It is mainly for reference render Whether the function is compiled or handwritten by the user .
_createElement The implementation content is a little more , There is no detailed analysis here , Anyway, one will be created in the end VNode , Every VNode Yes children,children Each element is also a VNode, And that's what makes a VNode Tree, It's a good description of our DOM Tree.
When VNode Once you've created it , Just come down and put VNode Render into a real DOM And render it . The process is through vm._update Accomplished .Vue Of _update Is a private method of the instance , When it is called 2 individual , One is the first rendering , One is when the data is updated , We'll only see the first rendering here ; When calling _update when , The core is the call vm.patch Method .
patch: This method is actually used on different platforms , such as web and weex The definition is different
Introduce a piece of code to see the specific implementation .
var app = new Vue({
el: '#app',
render: function (createElement) {
return createElement('div', {
attrs: {
id: 'app'
},
}, this.message)
},
data: {
message: 'Hello Vue!'
}
});
stay vm._update That's what's called in the method of patch Methodical :
if (!prevVnode) {
// First render
vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */);
} else {
// to update
vm.$el = vm.__patch__(prevVnode, vnode);
}
First render :
- $el The corresponding is id by app Of DOM Elements .
- vnode The corresponding is render Function by createElement Function created fictitious DOM.
- hydrating In the case of non server rendering, it is false.
After confirming the parameters for the first rendering , Let's see patch Implementation process of . A smelly and long source code .
function patch (oldVnode, vnode, hydrating, removeOnly) {
if (isUndef(vnode)) {
if (isDef(oldVnode)) { invokeDestroyHook(oldVnode); }
return
}
var isInitialPatch = false;
var insertedVnodeQueue = [];
if (isUndef(oldVnode)) {
// empty mount (likely as component), create new root element
isInitialPatch = true;
createElm(vnode, insertedVnodeQueue);
} else {
var isRealElement = isDef(oldVnode.nodeType);
if (!isRealElement && sameVnode(oldVnode, vnode)) {
// patch existing root node
patchVnode(oldVnode, vnode, insertedVnodeQueue, null, null, removeOnly);
} else {
if (isRealElement) {
// mounting to a real element
// check if this is server-rendered content and if we can perform
// a successful hydration.
if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {
oldVnode.removeAttribute(SSR_ATTR);
hydrating = true;
}
if (isTrue(hydrating)) {
if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {
invokeInsertHook(vnode, insertedVnodeQueue, true);
return oldVnode
} else {
warn(
'The client-side rendered virtual DOM tree is not matching ' +
'server-rendered content. This is likely caused by incorrect ' +
'HTML markup, for example nesting block-level elements inside ' +
'<p>, or missing <tbody>. Bailing hydration and performing ' +
'full client-side render.'
);
}
}
// either not server-rendered, or hydration failed.
// create an empty node and replace it
oldVnode = emptyNodeAt(oldVnode);
}
// replacing existing element
var oldElm = oldVnode.elm;
var parentElm = nodeOps.parentNode(oldElm);
// create new node
createElm(
vnode,
insertedVnodeQueue,
// extremely rare edge case: do not insert if old element is in a
// leaving transition. Only happens when combining transition +
// keep-alive + HOCs. (#4590)
oldElm._leaveCb ? null : parentElm,
nodeOps.nextSibling(oldElm)
);
// update parent placeholder node element, recursively
if (isDef(vnode.parent)) {
var ancestor = vnode.parent;
var patchable = isPatchable(vnode);
while (ancestor) {
for (var i = 0; i < cbs.destroy.length; ++i) {
cbs.destroy[i](ancestor);
}
ancestor.elm = vnode.elm;
if (patchable) {
for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) {
cbs.create[i$1](emptyNode, ancestor);
}
// #6513
// invoke insert hooks that may have been merged by create hooks.
// e.g. for directives that uses the "inserted" hook.
var insert = ancestor.data.hook.insert;
if (insert.merged) {
// start at index 1 to avoid re-invoking component mounted hook
for (var i$2 = 1; i$2 < insert.fns.length; i$2++) {
insert.fns[i$2]();
}
}
} else {
registerRef(ancestor);
}
ancestor = ancestor.parent;
}
}
// destroy old node
if (isDef(parentElm)) {
removeVnodes([oldVnode], 0, 0);
} else if (isDef(oldVnode.tag)) {
invokeDestroyHook(oldVnode);
}
}
}
invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch);
return vnode.elm
}
In the first rendering , Because of the oldVnode( id by app Of DOM Elements ) It's actually a DOM container, Then through emptyNodeAt Method to oldVnode convert to VNode object , Then call createElm Method , Create real... Through virtual nodes DOM And insert it into its parent node .
Through the bottom React and Vue Of createElement Source code , Analysis of the JSX How to map to reality DOM Of , The overall direction of the realization idea is the same . So we are all learning from each other , Learn from each other .
Why? React Choose from the beginning JSX?
stay 2013 year ,React With JSX Syntax appears , It was controversial when it first appeared , Why? React Will choose JSX? Not any other grammar . such as :
Templates
The typical template syntax is AngularJS, If you used AngularJS, You will find that a lot of concepts will be introduced into the template , For example, the new template syntax 、 New template directive .
<div ng-controller="Ctrl1">
Hello <input ng-model='name'> <hr/>
<span ng-bind="name"></span> <br/>
<span ng:bind="name"></span> <br/>
<span ng_bind="name"></span> <br/>
<span data-ng-bind="name"></span> <br/>
<span x-ng-bind="name"></span> <br/>
</div>
angular.module('test', [])
.controller('Ctrl1', function Ctrl1($scope) {
$scope.name = '1';
});
React The original intention of the design is **「 Separation of concerns 」,React The basic unit of concern itself is the component , High cohesion within the component , Low coupling between components . The template syntax cannot . also JSX It will not introduce too many new concepts .** It can also be seen that React The code is simpler , More readable , Closer to HTML.
const App = (props) => {
return (
<div> xxx </div>
)
}
Template string
JSX The syntax of is a bit like a template string , If in the early years , Have used PHP + JQuery Students of the technology stack may have written code with such a syntax .
var box = jsx` <${Box}> ${ true ? jsx`<${Box.Comment}> Text Content </${Box.Comment}>` : jsx` <${Box.Comment}> Text Content </${Box.Comment}> ` } </${Box}> `;
I don't know what you think , Anyway, when I was writing such code, it was very painful , And the code results become more complex , Not conducive to later maintenance .
JXON
<catalog>
<product description="Cardigan Sweater"> 1111 </product>
<script type="text/javascript"></script>
</catalog>
But finally give up JXON The reason for this scheme is , Braces cannot be the starting and ending positions of elements in the tree , Provide good syntax hints .
template
<template>
<div>1</div>
<template>
<script>
....
<script>
Then why can't it be with Vue The use of Template syntax ? JSX Nature is JavaScript, To achieve conditional rendering, you can use if else, You can also use ternary expressions , You can also use any legal JavaScript grammar . in other words ,JSX Can support more dynamic requirements . and template Because of grammatical restrictions , It can't be like JSX That can support more dynamic requirements . This is a JSX Compared with template An advantage of . JSX Compared with template There's another advantage , Yes, you can return multiple components in one file .
But just Vue Come on , Default choice template Grammar also has a reason ,template Because the syntax is fixed , There are many optimizations that can be done at the compilation level , For example, static tags can really update on demand ; and JSX Due to the strong dynamics , Optimization can only be done in limited scenarios , Although the performance is not as good as template good , But in some scenes with high dynamic requirements ,JSX It's standard , This is also used by many component libraries JSX The main reason is .
summary
By comparing various schemes , Find out JSX He has his own advantages ,JSX The code written by syntax is more concise , And the code structure is more clear .JSX Syntax sugar allows us developers to write like HTML To write our JS Code . It not only reduces the learning cost, but also improves our R & D efficiency and R & D experience .
also JSX There is not much grammar in itself , Nor do we expect to introduce more standards . actually , stay 16 In the year ,JSX Published 2.0 The construction plan and a small number of new features , But soon Facebook Give up . The whole plan was stopped within two months after it was announced . One reason is JSX Design intention of , I don't want to introduce too many standards , Not expected JSX Join the browser or ECMAScript standard .
Reference resources
- reactjs.org/docs/glossa…
- www.babeljs.cn/docs/
- babeljs.io/repl#?brows…
- reactjs.org/docs/introd…
- v3.cn.vuejs.org/guide/compo…
- time.geekbang.org/column/arti…
- github.com/vuejs/jsx-v…
- github.com/vuejs/babel…
- kaiwu.lagou.com/course/cour…
- ustbhuangyi.github.io/vue-analysi…
- ustbhuangyi.github.io/vue-analysi…
- kaiwu.lagou.com/course/cour…
- blog.csdn.net/qq_39200185…
copyright notice
author[Bai Xiaobai],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/175/202206240859173403.html
The sidebar is recommended
- The birth of atomic quantum circuit marks a major breakthrough in quantum computer technology
- How to locate lock waiting in Dameng database
- Easily play with IOS 16 lock screen interface
- How to open an account online for new bonds? Please bless me
- React usestate storage function
- What else can the project implementation engineer do without the project?
- Precautions when applying to upgrade springcloud Version (Dalston to Edgware)
- A docker implemented by shell script
- Android studio simulator modify system language / enable Developer mode / customize resolution and size
- Android uses itemtouchhelper to realize item dragging position exchange and side sliding deletion of recyclerview
guess what you like
Why does the menu bar created with QT in vs report errors
Oauth2 released methods cannot be accessed
About pyopengl: why is the obj model (dinosaur) read and displayed like this? How can it display the same material effect as the teapot
CSS problem, card jitter
Jpprofiler monitors the problem of excessive memory deployed under Tomcat
A HashMap talked with the interviewer for half an hour
Java interview experience in a small company
I have made an application to visually generate echarts code, so I don't have to look at complex documents anymore (attached with project source code)
Can you do it as soon as possible? There is not much time
For non front and rear end separation projects, how can the front and rear ends be separated and packaged separately?
Random recommended
- () is a linear table that restricts the internal structure of data elements to only one character. A. Stack B. queue C. string D. array
- TS cannot find global variable for NPM package
- Java, what should I do if there is an edit configuration in the idea when it runs
- C++ code. Freshmen have just come into contact with this language
- Tnsnames Ora file configuration
- Handling method of Oracle data file header SCN inconsistency
- Oracle database listening file configuration
- Oracle database expdp only exports tables
- Windows method for checking network port occupation and kill process
- Oracle viewing data file header SCN information
- Ora-28000 error after upgrading Oracle 12C to 19C
- [talk about serviceregistryendpoint of springcloud]
- [springcloud service registration and anti registration AOP interception]
- [springboot source code analysis - @endpoint annotation validation principle analysis]
- [elegant offline and grayscale release of spring cloud]
- PostgreSQL
- Reactnative 0.69 release
- The new design can be called a new generation. The gradient borderless grille has a high appearance value. The application drawing of Changan Ruicheng plus
- Linux general command summary
- Render external link address URL video page via iframe - Vue
- Detailed explanation of Linux system tuning (VII) -- network status viewing command nethogs
- Vue failed to parse source for import analysis because the content contains invalid JS syntax
- Differences between front-end set and map
- Difference between front-end foreach and map
- Front end array flattening
- How the front end judges the data type
- Front end CSS style expand and collapse
- Front end array de duplication
- Front end throttling and anti shake
- Analysis of 43 cases of MATLAB neural network: Chapter 33 prediction algorithm of fuzzy neural network -- water quality evaluation of Jialing River
- Java & c++ problem solving and expansion -- leetcode30 Concatenate substrings of all words [new knowledge of Mo]
- Eclipse customizes and calls the header file [c/c++]
- Detailed explanation of Vue Foundation
- Unity determines whether all toggles are selected or not
- Program reverse output and print results
- Ubuntu modify time zone
- Linux Installation maven
- Okhttp source code analysis of Android network framework
- Android adds system service interfaces and test cases
- Ubuntu deployment according to Vue version