React
The community has been exploring useReact
The way grammar develops small programs, among which the more famous ones areTaro
,nanachi
。 While usingReact
The main difficulty of grammar development isJSX
In grammar,JSX
In essence isJS
, which is too flexible compared with the static template of the applet. The new idea in this paper is to deal with it.JSX
A new way of thinking in grammar, which is a more dynamic way of thinking, is basically not limited to any of the existing solutions.JSX
It lets you handle small programs in a real React way. I hope this new idea can give any aspiration to use it.React
People who develop small programs bring inspiration.
Limitations of existing ideas
Before introducing new ideas, let’s take a lookTaro (latest version 1.3)
,nanachi
How to deal with it on the small program sideJSX
Grammatical. Simply put, it’s mainly through the compilation phase.JSX
Converting to an equivalent programwxml
Come on.React
The code runs on the small program side.
For example, for exampleReact
Logical expression:
xx && <Text>Hello</Text>
It will be converted into an equivalent widget wx:if instruction:
<Text wx:if="{{xx}}">Hello</Text>
This is the right way to do it.JSX
For example, it must recognize the logical expression and then do the correspondingwx:if
Conversion processing.
What are the problems and limitations of the compilation phase? Let’s illustrate with the following examples:
class App extends React.Component {
render () {
const a = <Text>Hello</Text>
const b = a
return (
<View>
{b}
</View>
)
}
}
First of all, we declare thatconst a = <Text>Hello</Text>
And thena
Assign tob
Let’s look at the latest versionTaro 1.3
The conversion is as follows:
This example is not particularly complicated, but it is wrong.
To understand why the above code fails, we first need to understand the compilation phase. Essentially in the compilation stage, the code is actually a string, and the compilation stage processing scheme needs to analyze the necessary information from the string (through theAST
And then do the corresponding equivalent transformation.
And for the example above, what equivalence should be done? We need to analyze it at the compilation stage.b
yesJSX
Fragment:b = a = <Text>Hello</Text>
And then<View>{b}</View>
Medium{b}
Equivalent substitution<Text>Hello</Text>
。 However, at the compilation stage, you want to determineb
The value of B is very difficult. Some people say that it can be traced back to determine the value of B. It’s not impossible, but consider that becauseb = a
Well, first of all, make sure.a
The value of thisa
How to determine the value of? Need tob
Identification in accessible scoping chainsa
However,a
Maybe it comes from the assignment of other variables, cycling and reciprocating. If there are not simple assignments, such as function calls, ternary judgments and other runtime information, traceability will fail.a
In itself, it is a variable hanging on the global object, and traceability is even more impossible to talk about.
So it’s not easy to determine at the compilation stage.b
The value of.
Let’s take a closer look at the error message in the picture above.a is not defined
。
Why?a
Not defined? That’s another issue, we know.<Text>Hello</Text>
, which is equivalent toReact.createElement(Text, null, 'Hello')
AndReact.createElement
The return value of the method is a normal valueJS
Objects, such as
// ReactElement object
{
tag: Text,
props: null,
children: 'Hello'
...
}
So the code above is inJS
When the environment really works, it is roughly equivalent to the following:
class App extends React.Component {
render () {
const a = {
tag: Text,
props: null,
children: 'Hello'
...
}
const b = a
return {
tag: View,
props: null,
children: b
...
}
}
}
However, we just said that the compilation phase needs toJSX
Equivalent treatment requires thatJSX
Convert towxml
So<Text>Hello</Text>
thisJSX
The fragments were specially processed.a
No longer an ordinary personjs
Object, here we seea
Variables are even missing, which exposes a serious problem: code semantics are broken, that is, due to compile-time schema pairsJSX
Special processing, code semantics that really run on small programs are not what you expect. This is a headache.
New ideas
Because compile-time solutions, like the above limitations, often let you have “I’m still writing” when using them.React
” This feeling.
Here we introduce a new way of thinking, which is true during the running of the applet.React
It’s almost the same, and it doesn’t change any code semantics.JSX
Expression will only be processed asReact.createElement
Method call, which is normal in actual operationjs
Object, and ultimately render the widget view in other ways. Next, we will elaborate on the specific content of this idea.
Step 1: Give each individualJSX
Fragments are uniquely identifieduuid
Suppose we have the following code:
const a = <Text uuid="000001">Hello</Text>
const y = <View uuid="000002">
<Image/>
<Text/>
</View>
We givea
Fragmentsy
Clip addeduuid
attribute
Step 2:React
Code passingbabel
Converted to code recognizable by a widget, such asJSX
Equivalent for fragmentsReact.createElement
Replacement, etc.
const a = React.createElement(Text, {
uuid: "000001"
}, "Hello");
Step 3: Extract each individualJSX
Snippets, with small programstemplate
Packaging, Generationwxml
file
<template name="000001">
<Text>Hello</Text>
</template>
<template name="000002">
<View uuid="000002">
<Image/>
<Text/>
</View>
</template>
<! - Placement template - >
<template is="{{uiDes.name}}" data="{{...uiDes}}"/>
Pay attention to every one heretemplate
Ofname
Logo andJSX
Unique identification of fragmentsuuid
It’s the same. Finally, a placeholder template needs to be generated at the end:<template is="{{uiDes.name}}" data="{{...uiDes}}"/>
。
Step 4: AmendmentReactDOM.render
Recursion (React 16.x
Later, not in a recursive way.) Processes, recursive execution stages, aggregationJSX
Fragmentuuid
Attribute, Generate and ReturnuiDes
Data structure.
Step 5: Generate Step 4uiDes
Pass it to the widget environment.uiDes
Set to placeholder template<template is="{{uiDes.name}}" data="{{...uiDes}}"/>
Render the final view.
We are above.App
Component examples illustrate the whole process. First of alljs
Code will be escaped to:
class App extends React.Component {
render () {
const a = React.createElement(Text, {uuid: "000001"}, "Hello");
const b = a
return (
React.createElement(View, {uuid: "000002"} , b);
)
}
}
Simultaneous generationwxml
Document:
<template name="000001">
<Text>Hello</Text>
</template>
<template name="000002">
<View>
<template is="{{child0001.name}}" data="{{...child0001}}"/>
</View>
</template>
<! - Placement template - >
<template is="{{uiDes.name}}" data="{{...uiDes}}"/>
After using our customizationrender
implementReactDOM.render(<App/>, parent)
。 stayrender
In addition to the routine creation of component instances and the execution lifecycle, additional collection of components in the execution process will be performed during the recursion process of _________.uuid
Identification, final generationuiDes
object
const uiDes = {
name: "000002",
child0001: {
name: 000001,
...
}
...
}
The applet gets thisuiDes
Set to placeholder template<template is="{{uiDes.name}}" data="{{...uiDes}}"/>
。 Finally render the applet view.
Throughout the process, all you haveJS
The code is running inReact process
In Chinese, the semantics are identical.JSX
The fragments will not be processed in any particular way, but simplyReact.createElement
Call, and because of theReact process
Just purejs
Operations, execution is very fast, usually only a few Ms. Ultimately one will be output.uiDes
Data to the applet, the applet passes through thisuiDes
Render the view.
Now let’s look at the previous assignment.const b = a
, there won’t be any problems, becausea
It’s just an ordinary object. In addition, there are restrictions on common compile time schemes, such as arbitrary function return.JSX
Fragment, dynamic generationJSX
Fragmentsfor
RecyclingJSX
The fragments and so on can be completely released, becauseJSX
Fragment onlyjs
Object, you can do anything, eventuallyReactDOM.render
Will collect all fragments of execution resultsuuid
Identification, GenerationuiDes
And the applet will follow thisuiDes
The data structure renders the final view.
It can be seen that this new idea is quite different from previous compile-time schemes.JSX
The processing of fragments is dynamic, and you can appear anywhere, anywhere, in any function.JSX
Fragment, the final execution result determines which fragment to render, only the fragment that executes the resultuuid
Will be writtenuiDes
。 This is essentially different from the static identification of schemes in compilation.
epilogue
“Talk is cheap. Show me your code! “Is that just a way of thinking? Or has it been fully realized?
There is a complete implementation, and the Alita project is working on it.JSX
This is the idea used in grammar, which is why Alita can transform the whole React Native project without restricting its writing. In addition, Alita has done a lot of optimization on this idea. If you are interested in the specific implementation of this idea, you can go to read the Alita source code, which is totally open-source https://github.com/areslabs/alita.
Of course, you can also construct your own React applet development program based on this idea.
The above is the whole content of this article. I hope it will be helpful to everyone’s study, and I hope you will support developpaer more.