Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to build Mini Program by React

2025-01-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "how React builds Mini Program". In daily operation, I believe many people have doubts about how to build Mini Program with React. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful for you to answer the doubts about "how to build Mini Program with React". Next, please follow the editor to study!

Project description

In order to describe the implementation process more clearly, we treat the implementation as a project.

Project requirements: make the React code with the following counter function run to WeChat Mini Programs platform.

Import React, {Component} from 'react'import {View, Text Button} from'@ leo/components'import'. / index.css'export default class Index extends Component {constructor () {super () this.state = {count: 0} this.onAddClick = this.onAddClick.bind (this) this.onReduceClick = this.onReduceClick.bind (this)} componentDidMount () {console.log ('execute componentDidMount') this.setState ({count: 1})} onAddClick () {this.setState ( {count: this.state.count + 1})} onReduceClick () {this.setState ({count: this.state.count-1})} render () {const text = this.state.count% 2 = 0? 'even': 'odd' return (count: {this.state.count} {text} + 1-1)}}

If you have used frameworks such as Taro or Remax, you should have a sense of deja vu for the above code, which formally mimics the React DSL writing of such frameworks. If you want to see the effect of implementing this requirement, click the project source code to obtain the source code, and then run the project according to the prompt, and you can observe the following effect:

At this point, it is clear to know the requirements of the project and what the final implementation result is, and then focus on the specific implementation of the process from the requirement point to the result.

Implement the solution and build the Mini Program framework product

Students who have developed Mini Program know that the Mini Program framework contains a body and a page, in which the main body is composed of three file students, and must be placed in the root directory, these three files are: app.js (essential, Mini Program logic), app.json (essential, Mini Program public configuration), app.wxss (optional, Mini Program public style sheet). So to build React code into Mini Program code, you first need to write app.js and app.json files. Because the app.js file is not involved in this conversion, the app.js content can be replaced by writing dead App ({}) directly. App.json is a configuration file. You can directly add an app.config.js to the React project to fill in the configuration content, that is, the React code project directory is as follows:

├── src │ ├── app.config.js / / Mini Program configuration file, which is used to generate app.json content │ └── pages │ └── index │ ├── index.css │ └── index.jsx / / React code, that is, the above counter code └── tsconfig.json

App.config.js content is the global configuration content of Mini Program, as follows:

Module.exports = {pages: ['pages/index/index'], window: {navigationBarTitleText:' react-wxapp', navigationBarBackgroundColor:'# 282c34'}}

With this configuration file, you can generate app.js and app.json files as follows.

/ * outputDir generates directories for Mini Program code * / fs.writeFileSync (path.join (outputDir,'. / app.js'), `App ({}) `) fs.writeFileSync (path.join (outputDir,'. / app.json'), JSON.stringify (config, undefined, 2)) / / config is the content of app.config.js file

Mini Program page is composed of four types of files, namely, js (required, page logic), wxml (required, page knot is structured), json (optional, page configuration), wxss (optional, page style sheet). And the React code to Mini Program, mainly considering how to convert the React code to the corresponding js and wxml type files, which will be described in detail later.

Scheme Analysis of running React to Mini Program platform

To achieve the React code to run on the Mini Program platform, there are two main ways, one is the compile-time implementation, the other is the run-time implementation, if you have looked at the project source code, you can find that the source code is also reflected in these two ways (compile-time implementation directory: packages/compile-core; runtime implementation directory: packages/runtime-core).

Compile-time rendering is mainly achieved by converting JSX to the corresponding template of Mini Program through static compilation, similar to Taro1.0 and 2.0. the performance of this method is close to that of native Mini Program, but the syntax is very limited. The runtime implementation is to redefine a React renderer in Mini Program platform through react-reconciler, so that React code can really run into Mini Program, such as Taro3.0, Remax, etc., so there are no syntax restrictions in this way, but the performance will be poor. The source code of this project is implemented with reference to the source code of frameworks such as Taro and Remax and simplifies many details, so the source code of this project is only suitable for learning and cannot be used in actual business.

Next, we will describe how to run React to the Mini Program platform at compile time and run time, respectively.

Compile-time implementation

Before we talk about the specific implementation process, we first need to understand the concept of implementation at compile time. First of all, the compilation here is not the traditional high-end "compilation". In the traditional sense, the compilation generally compiles the high-level language to the low-level language, but here it just converts the same level language, that is, compiling the javascript code string into another javascript code string, so the compilation here is more like "translation". Second, although it is called compile-time implementation here, not all implementation processes are compiled, and a small number of implementations need runtime cooperation, so this approach is more appropriate to call re-compilation and light run mode. Similarly, the run-time implementation also contains a small number of compile-time implementations, which can also be called heavy-run light compilation.

In order to facilitate the implementation of compiling javascript code strings into another kind of javascript code strings, Babel tool is directly used here. Due to space problems, we will not describe the usage of Babel in detail here. If you are not familiar with Babel, you can take a look at this article and simply understand it (yes, just advertise yourself). Next, let's analyze the compile-time implementation steps:

1. Convert JSX to the template corresponding to Mini Program

React renders the view through JSX, while Mini Program renders the view through wxml. To run React on Mini Program, the focus is on how to convert JSX to the corresponding wxml of Mini Program. The conversion rule is to convert JSX syntax into Mini Program syntax with the same function, for example:

Tag element conversion: View, Text, Button and other tags are directly mapped to the Mini Program basic component itself (changed to lowercase)

Style class name conversion: className changed to class

= = >

Event conversion: for example, onClick is changed to bindtap

= = >

Circular conversion: map syntax changed to wx:for

List.map (I = > {I}) = > {{item}}

Syntax conversion is much more than the above types. If you want to ensure that developers can develop Mini Program with a variety of JSX grammars, you need to enumerate as many syntax conversion rules as possible, otherwise it is likely that developers will not support conversion if they use one writing method. In fact, some writing methods (such as dynamic generation of JSX fragments, etc.) can not support conversion at all, which is why the disadvantage of the implementation scheme at compile time is that the syntax is limited, developers can not code at will, and need to be limited by the development rules of the framework itself.

As the syntax of the above conversion JSX code is relatively simple, only a few simple syntax rule transformations are needed. The converted wxml results are posted here, and the corresponding implementation code is located at: packages/compile-core/transform/parseTemplate.ts.

Count: {{count}} + 1-1

two。 Runtime adaptation

As mentioned earlier, although this scheme is called compile-time implementation, it still needs to be adapted at run time to run the React code on the Mini Program platform driver. Adaptation processing is mainly implemented in Mini Program js logic, which mainly includes three parts: data rendering, event processing and lifecycle mapping.

Mini Program js logic registers through an object parameter configuration declaration period, event, etc., and triggers view rendering through the setData method:

Component ({data: {}, onReady () {this.setData (..)}, handleClick () {}})

The counter React code declares a component logic through class, similar to:

Class CustomComponent extends Component {state = {} componentDidMount () {this.setState (..)} handleClick () {}}

As you can see from the above two pieces of code, Mini Program is declared through object, and React is declared through class. In addition, Mini Program triggers View (wxml) rendering through setData, and React triggers View rendering (render method) through setState. So to make the React logic run on the Mini Program platform, you can add a run-time gasket to correspond to the two logical writing methods through the gasket. Before introducing the specific implementation of the runtime gasket, we also need to simply convert the above React counter code, and the finished code is as follows:

Import React, {Component} from ".. /.. / npm/app.js"; / / 1.app.js is the gasket implementation file export default class Index extends Component {static $$events = ["onAddClick", "onReduceClick"]; / / 2. Collect JSX event name constructor () {super (); this.state = {count: 0}; this.onAddClick = this.onAddClick.bind (this); this.onReduceClick = this.onReduceClick.bind (this);} componentDidMount () {console.log ('execute componentDidMount'); this.setState ({count: 1}) } onAddClick () {this.setState ({count: this.state.count + 1});} onReduceClick () {this.setState ({count: this.state.count-1});} createData () {/ / 3.render function to createData, delete this.__state = arguments [0] / / the original JSX code, return the updated state / / and provide it to Mini Program for setData const text = this.state.count% 2 = = 0? 'even': 'odd'; Object.assign (this.__state, {text: text}); return this.__state;}} Page (require ('.. /.. / npm/app.js') .createPage (Index)). / / 4. Initialize using the createPage / / method provided by the runtime gasket

As in the code above, there are four areas that need to be dealt with:

Component is rewritten, and the rewriting logic is implemented in the runtime gasket file, that is, app.js. The specific logic will be posted later.

Collect the callback method name corresponding to the click event of the original JSX, so that the gasket can register the event on the Mini Program platform at run time.

Because the JSX fragment in the original render method is converted to wxml, here the render method can delete the JSX fragment. In addition, because the render method is triggered every time React executes setState, and the latest state data is received in the render method to update the view, the latest state generated here is the setData method that needs to be provided to Mini Program, thus triggering the data rendering of Mini Program. For this reason, the name of render is renamed to createData (data data for production Mini Program), and the internal logic is rewritten to return the latest state generated.

Initialize using the createPage method provided by the run-time gasket (the createPage method will be posted later after implementing the specific logic), and register through the Page method provided by the Mini Program platform, from which we can know that the data returned by the createPage method must be of type object.

The runtime gasket (app.js) implementation logic is as follows:

Export class Component {/ / rewrite the implementation logic of Component constructor () {this.state = {}} setState (state) {/ / setState finally triggers Mini Program's setData update (this.$scope.$component, state)} _ init (scope) {this.$scope = scope}} function update ($component) State = {}) {$component.state = Object.assign ($component.state State) let data = $component.createData (state) / / execute createData to get the latest state data ['$leoCompReady'] = true $component.state = data $component.$scope.setData (data) / / pass state to setData for update} export function createPage (ComponentClass) {/ / createPage implementation logic const componentInstance = new ComponentClass () / / instantiate the Class group passed into React Const initData = componentInstance.state const option = {/ / declare the literal amount of an object in Mini Program logic data: initData OnLoad () {this.$component = new ComponentClass () this.$component._init (this) update (this.$component, this.$component.state)} OnReady () {if (typeof this.$component.componentDidMount = 'function') {this.$component.componentDidMount () / / Life Logic Mapping} const events = ComponentClass [' $$events'] / / get all event callback methods in the React component named if (events) {events.forEach (eventHandlerName = > {if) (option [eventHandlerName]) return option [eventHandlerName] = function () {this.$ operator [eventHandlerName] .call (this.$component)}} return option}

It was mentioned above that the specific implementation logic of overriding the Component class and the createPage method is shown in the code above.

The state declared in Component executes a update method. In the update method, the new state generated by React is merged with the old state, then the merged state is obtained by the createData method mentioned above, and the latest state is passed to Mini Program for setData, thus achieving Mini Program data rendering.

The createPage method logic first instantiates the React component, then constructs a corresponding literal quantity of the Mini Program logic, and binds the relevant methods of the React component instance with the literal quantity of the Mini Program logical object. Secondly, it carries on the life cycle binding: starts the React component corresponding to the componentDidMount life cycle in the Mini Program onReady cycle. It is best to bind events: through the callback event name mentioned above, retrieve the corresponding events in the React component instance, and register these events in the corresponding literal amount of Mini Program logic, so as to complete the Mini Program platform event binding. Finally, the literal amount of this object is returned for registration by the Page method mentioned earlier.

At this point, you can achieve the React code to run on the Mini Program platform, you can execute npm run build:compile in the project source code to see the effect. Compile-time implementation scheme is mainly through the combination of static compilation of JSX code and run-time gasket to complete the React code to run to the Mini Program platform, this scheme basically has no performance loss, and can do some optimization in the run-time gasket (such as removing unnecessary rendering data, reducing the amount of setData data), so its performance is similar to or even better than the development using Mini Program native syntax. However, the disadvantage of this solution is the syntax limitation (mentioned above), which makes the development unfriendly, which leads to the birth of the runtime implementation.

Runtime implementation

As you can see from the above, the syntax limitation of the compile-time implementation is mainly because it does not really let React run on the Mini Program platform, while the runtime implementation scheme can, the principle is to implement a React custom renderer on the Mini Program platform to render React code. Here we explain the implementation of the remax framework, and the runtime implementation in the source code of this project is also implemented with reference to the remax framework.

If you have developed Web using React, the entry file has a piece of code similar to this:

Import React from 'react'import ReactDom from' react-dom'import App from'. / App'ReactDom.render (App, document.getElementById ('root'))

You can see that rendering a Web page requires a reference to a module called react-dom, so what is the purpose of this module? React-dom is the renderer of the Web platform, which is mainly responsible for rendering the Vitrual DOM data after React execution to the Web platform. Similarly, for React to render to Native, there is also a renderer for the Native platform: React Native.

React implements a multi-platform approach by implementing a React renderer on each platform, as shown in the following figure.

If you want to run React to the Mini Program platform, you only need to develop a custom Mini Program renderer. React officially provides a react-reconciler package specifically for implementing custom renderers, and officially provides a simple demo to rewrite react-dom.

There are two main steps to implement the renderer using react-reconciler. The first step is to implement the rendering function (render method), similar to the ReactDOM.render method:

Import ReactReconciler from 'react-reconciler'import hostConfig from'. / hostConfig' / / Host configuration / / create a Reconciler instance and pass HostConfig to Reconcilerconst ReactReconcilerInst = ReactReconciler (hostConfig) / * provide a render method, similar to the ReactDom.render method * same as ReactDOM Receive three parameters * render (, container, () = > console.log ('rendered')) * / export function render (element, container, callback) {/ / create root container if (! container._rootContainer) {container._rootContainer = ReactReconcilerInst.createContainer (container, false) Update root container return ReactReconcilerInst.updateContainer (element, container._rootContainer, null, callback);}

The second step, such as the import hostConfig from'. / hostConfig' referenced in the figure above, needs to implement the host configuration (HostConfig) through react-reconciler. HostConfig provides a series of adapter schemes and configuration items in the hosting environment, defining how to create node instances, build node trees, submit and update, and other operations. You can click to view the complete list. It is worth noting that the Mini Program platform does not provide DOM API operation, so the data can only be transferred to the view layer through setData. Therefore, Remax redefines a node of type VNode, so that React does not directly change the DOM during the reconciliation process, but first updates the content of the VNode,hostConfig file as follows:

Interface VNode {id: number; / / Node id, which is a self-incrementing unique id that identifies the node. Container: Container; / / similar to the second parameter in ReactDOM.render (, document.getElementById ('root'), children: VNode []; / / child node. Type: string | Type of symbol; / / node, that is, the basic components in Mini Program, such as view, text, etc. Attributes of the props?: any; / / node. Parent: VNode | null; / / parent node text?: string; / / text node text appendChild (node: VNode): void; removeChild (node: VNode): void; insertBefore (newNode: VNode, referenceNode: VNode): void .} / / implement host configuration const hostConfig = {. / / execute after reconciler submission, trigger container update data (setData that actually triggers Mini Program) resetAfterCommit: (container) = > {container.applyUpdate ();}, / / create host component instance, initialize VNode node createInstance (type, newProps, container) {const id = generate (); const node = new VNode ({...}) Return node;}, / / insert node appendChild (parent, child) {parent.appendChild (child);}, / / insertBefore (parent, child, beforeChild) {parent.insertBefore (child, beforeChild);}, / / remove node removeChild (parent, child) {parent.removeChild (child);}.}

In addition to the above configuration, you also need to provide a container for formatting VNode data into JSON data for Mini Program setData to pass to the view layer. This container class is implemented as follows:

Class Container {constructor (context) {this.root = new VNode ({..}) / / Root node} toJson (nodes, data) {/ / format VNode data JSON const json = data | | [] nodes.forEach (node = > {const nodeData = {type: node.type, props: node.props | | {}, text: node.text, id: node.id Children: []} if (node.children) {this.toJson (node.children, nodeData.children)} json.push (nodeData)}) return json} applyUpdate () {/ / resetAfterCommit method for HostConfig configuration executes const root = this.toJson ([this.root]) [0] console.log (root) this.context.setData ({root}) }...}

Next, we encapsulate a createPageConfig method to perform the rendering, where the Page parameter is the React component, which is the component of the counter above.

Import * as React from 'react';import Container from'. / container'; / / Containerimport render from'. / render' defined above / / render method export default function createPageConfig (component) {/ / component defined above is the literal quantity of React component const config = {/ / Mini Program logical object for Page method to register data: {root: {children: [],}}, onLoad () {this.container = new Container (this, 'root') Const pageElement = React.createElement (component, {page: this,}); this.element = render (pageElement, this.container);}}; return config;}

At this point, the mini program renderer has been basically implemented. In order to make the code run, you also need to modify the React counter component through static compilation, which is to insert a sentence of code at the end:

Import React, {Component} from 'react';export default class Index extends Component {constructor () {super (); this.state = {count: 0}; this.onAddClick = this.onAddClick.bind (this); this.onReduceClick = this.onReduceClick.bind (this);}.}} / / app.js encapsulates the above createPage method Page (require ('.. / npm/app.js') .createPage (Index))

In this way, you can make the React code really run on Mini Program, but here we still have a process that hasn't been introduced. How to update the page JSON data generated in the applyUpdate method of the above Container class to the view? First, let's take a look at what this JSON data looks like:

/ / the question of space Only some data {"type": "root", "props": {}, "id": 0, "children": [{"type": "view", "props": {"class": "container"}, "id": 12 "children": [{"type": "view", "props": {"class": "conut"}, "id": 4 "children": [{"type": "text", "props": {}, "id": 3 "children": [{"type": "plain-text", "props": {}, "text": "count:" "id": 1, "children": []}, {"type": "plain-text", "props": {} "text": "1", "id": 2 "children": []}]}...}]}

You can see that JSON data is actually Tree UI-like data. To render these data to the page, you can use the Temlate provided by Mini Program to render. Due to the problem of recursive nesting of Mini Program templates (WeChat Mini Programs platform limitation), you need to provide multiple templates of the same component type for recursive rendering, as shown below:

.

At this point, you can really achieve the React code to run to Mini Program, you can execute npm run build:runtime in the project source code to see the effect.

At this point, the study on "how to build Mini Program by React" is over. I hope I can solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report