0
# Rendering System
1
2
Universal rendering engine that works across multiple platforms through pluggable driver system. Enables Rax applications to run on Web, Weex, Node.js, Alibaba MiniApp, WeChat MiniProgram, and other platforms.
3
4
## Capabilities
5
6
### Render Function
7
8
Renders Rax elements to a container using the specified platform driver. This is the main entry point for displaying Rax applications.
9
10
```javascript { .api }
11
/**
12
* Renders a Rax element tree to a container
13
* @param element - Root Rax element to render
14
* @param container - DOM container or platform-specific container
15
* @param options - Render options including driver and other settings
16
* @param callback - Optional callback executed after render completion
17
* @returns Component instance of the root element
18
*/
19
function render(element, container, options, callback);
20
21
/**
22
* Simplified render function (callback as third parameter)
23
* @param element - Root Rax element to render
24
* @param container - DOM container or platform-specific container
25
* @param callback - Optional callback executed after render completion
26
* @returns Component instance of the root element
27
*/
28
function render(element, container, callback);
29
```
30
31
**Usage Examples:**
32
33
```javascript
34
import { createElement, render, Component } from 'rax';
35
import * as DriverDOM from 'driver-dom'; // Web platform driver
36
37
// Basic functional component
38
function App() {
39
return createElement('div', null,
40
createElement('h1', null, 'Hello Rax!'),
41
createElement('p', null, 'Universal React-compatible rendering')
42
);
43
}
44
45
// Render to DOM (Web platform)
46
const appInstance = render(
47
createElement(App),
48
document.getElementById('root'),
49
{ driver: DriverDOM },
50
() => {
51
console.log('App rendered successfully');
52
}
53
);
54
55
// Simplified usage with callback
56
render(
57
createElement(App),
58
document.body,
59
() => {
60
console.log('Render complete');
61
}
62
);
63
```
64
65
### Render Options
66
67
The render function accepts various options to customize rendering behavior:
68
69
```javascript { .api }
70
interface RenderOptions {
71
/**
72
* Platform driver for rendering (required)
73
* Defines how elements are created and managed on the target platform
74
*/
75
driver: Driver;
76
77
/**
78
* Enable hydration mode for server-side rendered content
79
* When true, Rax will attach to existing DOM instead of creating new elements
80
*/
81
hydrate?: boolean;
82
83
/**
84
* Parent element context for nested rendering
85
* Used internally for component composition
86
*/
87
parent?: RaxElement;
88
}
89
```
90
91
### Platform Drivers
92
93
Rax uses drivers to abstract platform-specific rendering logic. Each platform has its own driver implementation:
94
95
**Web Platform (driver-dom):**
96
97
```javascript
98
import { createElement, render } from 'rax';
99
import * as DriverDOM from 'driver-dom';
100
101
function WebApp() {
102
return createElement('div', null,
103
createElement('button', {
104
onClick: () => alert('Clicked!')
105
}, 'Click me')
106
);
107
}
108
109
render(createElement(WebApp), document.body, { driver: DriverDOM });
110
```
111
112
**Server-Side Rendering:**
113
114
```javascript
115
import { createElement, render } from 'rax';
116
import * as DriverServer from 'driver-server';
117
118
function ServerApp() {
119
return createElement('html', null,
120
createElement('head', null,
121
createElement('title', null, 'SSR App')
122
),
123
createElement('body', null,
124
createElement('h1', null, 'Server Rendered'),
125
createElement('p', null, 'This was rendered on the server')
126
)
127
);
128
}
129
130
// Server-side rendering
131
const htmlString = render(createElement(ServerApp), null, { driver: DriverServer });
132
```
133
134
**Weex Platform:**
135
136
```javascript
137
import { createElement, render } from 'rax';
138
import * as DriverWeex from 'driver-weex';
139
140
function WeexApp() {
141
return createElement('div', {
142
style: {
143
flex: 1,
144
justifyContent: 'center',
145
alignItems: 'center'
146
}
147
},
148
createElement('text', {
149
style: { fontSize: 48, color: '#333' }
150
}, 'Weex App')
151
);
152
}
153
154
render(createElement(WeexApp), null, { driver: DriverWeex });
155
```
156
157
### Hydration
158
159
Hydration allows Rax to attach to server-side rendered HTML instead of creating new DOM elements:
160
161
```javascript { .api }
162
/**
163
* Hydrates server-side rendered content
164
* Attaches Rax to existing DOM elements instead of creating new ones
165
*/
166
function hydrate(element, container, options, callback);
167
```
168
169
**Hydration Usage Example:**
170
171
```javascript
172
import { createElement, render } from 'rax';
173
import * as DriverDOM from 'driver-dom';
174
175
function HydratedApp() {
176
return createElement('div', { id: 'app' },
177
createElement('h1', null, 'Hydrated App'),
178
createElement('button', {
179
onClick: () => console.log('Hydrated click!')
180
}, 'Interactive Button')
181
);
182
}
183
184
// Hydrate existing server-rendered HTML
185
render(
186
createElement(HydratedApp),
187
document.getElementById('app'),
188
{
189
driver: DriverDOM,
190
hydrate: true
191
},
192
() => {
193
console.log('Hydration complete - app is now interactive');
194
}
195
);
196
```
197
198
### Multiple Root Rendering
199
200
Rax supports rendering multiple independent component trees:
201
202
**Multiple Roots Example:**
203
204
```javascript
205
import { createElement, render } from 'rax';
206
import * as DriverDOM from 'driver-dom';
207
208
// Header component
209
function AppHeader() {
210
return createElement('header', null,
211
createElement('h1', null, 'My App'),
212
createElement('nav', null,
213
createElement('a', { href: '/' }, 'Home'),
214
createElement('a', { href: '/about' }, 'About')
215
)
216
);
217
}
218
219
// Sidebar component
220
function AppSidebar() {
221
return createElement('aside', null,
222
createElement('h2', null, 'Sidebar'),
223
createElement('ul', null,
224
createElement('li', null, 'Item 1'),
225
createElement('li', null, 'Item 2')
226
)
227
);
228
}
229
230
// Main content component
231
function AppMain() {
232
return createElement('main', null,
233
createElement('h2', null, 'Main Content'),
234
createElement('p', null, 'This is the main content area')
235
);
236
}
237
238
// Render to different containers
239
render(createElement(AppHeader), document.getElementById('header'), { driver: DriverDOM });
240
render(createElement(AppSidebar), document.getElementById('sidebar'), { driver: DriverDOM });
241
render(createElement(AppMain), document.getElementById('main'), { driver: DriverDOM });
242
```
243
244
### Render Lifecycle
245
246
The rendering process follows these steps:
247
248
1. **Element Creation**: `createElement` creates virtual DOM elements
249
2. **Driver Initialization**: Platform driver is initialized with options
250
3. **Component Instantiation**: Components are instantiated and lifecycle methods are called
251
4. **DOM/Platform Updates**: Driver creates or updates platform-specific elements
252
5. **Callback Execution**: Optional callback is executed after render completion
253
254
**Lifecycle Integration Example:**
255
256
```javascript
257
import { createElement, render, Component } from 'rax';
258
import * as DriverDOM from 'driver-dom';
259
260
class LifecycleDemo extends Component {
261
constructor(props) {
262
super(props);
263
console.log('1. Constructor called');
264
this.state = { mounted: false };
265
}
266
267
componentDidMount() {
268
console.log('3. componentDidMount called');
269
this.setState({ mounted: true });
270
}
271
272
componentDidUpdate() {
273
console.log('4. componentDidUpdate called');
274
}
275
276
render() {
277
console.log('2. render called');
278
return createElement('div', null,
279
createElement('p', null, `Mounted: ${this.state.mounted}`)
280
);
281
}
282
}
283
284
render(
285
createElement(LifecycleDemo),
286
document.body,
287
{ driver: DriverDOM },
288
() => {
289
console.log('5. Render callback executed');
290
}
291
);
292
```
293
294
### Error Handling
295
296
Rax provides error boundaries and error handling during rendering:
297
298
```javascript
299
import { createElement, render, Component } from 'rax';
300
import * as DriverDOM from 'driver-dom';
301
302
class ErrorBoundary extends Component {
303
constructor(props) {
304
super(props);
305
this.state = { hasError: false, error: null };
306
}
307
308
componentDidCatch(error, errorInfo) {
309
console.error('Error caught by boundary:', error, errorInfo);
310
this.setState({ hasError: true, error });
311
}
312
313
render() {
314
if (this.state.hasError) {
315
return createElement('div', null,
316
createElement('h2', null, 'Something went wrong'),
317
createElement('p', null, this.state.error?.message || 'Unknown error')
318
);
319
}
320
321
return this.props.children;
322
}
323
}
324
325
function ProblematicComponent() {
326
throw new Error('This component has an error!');
327
}
328
329
function App() {
330
return createElement(ErrorBoundary, null,
331
createElement('h1', null, 'My App'),
332
createElement(ProblematicComponent)
333
);
334
}
335
336
render(createElement(App), document.body, { driver: DriverDOM });
337
```
338
339
## Types
340
341
```javascript { .api }
342
// Render function signatures
343
interface RenderFunction {
344
(element: RaxElement, container: any, options: RenderOptions, callback?: Function): any;
345
(element: RaxElement, container: any, callback?: Function): any;
346
}
347
348
// Render options interface
349
interface RenderOptions {
350
driver: Driver;
351
hydrate?: boolean;
352
parent?: RaxElement;
353
}
354
355
// Driver interface (platform-specific implementation)
356
interface Driver {
357
createElement(type: string, props?: Object): any;
358
createTextNode(text: string): any;
359
createBody(): any;
360
updateElement(element: any, props: Object, prevProps?: Object): void;
361
appendChild(parent: any, child: any): void;
362
removeChild(parent: any, child: any): void;
363
insertBefore(parent: any, child: any, beforeChild: any): void;
364
// Additional platform-specific methods...
365
}
366
367
// Container types (platform-specific)
368
type DOMContainer = Element | Document;
369
type WeexContainer = any; // Weex-specific container type
370
type ServerContainer = null; // Server rendering doesn't use container
371
372
// Render callback type
373
type RenderCallback = () => void;
374
375
// Component instance type (returned by render)
376
interface ComponentInstance {
377
setState?(partialState: any, callback?: Function): void;
378
forceUpdate?(callback?: Function): void;
379
// Additional component instance methods...
380
}
381
```