This repository was archived by the owner on Sep 3, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintroducing-jsx.html
302 lines (268 loc) · 16.8 KB
/
introducing-jsx.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="description" content="Composi is a JavaScript library for creating component-based interfaces. It uses the virtual dom to make efficient updates to the DOM based on a component's data or state.">
<meta name="keywords" content="javascript, framework, performance, small, fast, UI, programming, code, component, composi, chocolatechipui, chocolatechip-ui, reactive, virtual dom">
<title>Composi - Tutorials</title>
<link rel="stylesheet" href="../css/styles.css">
<link rel="stylesheet" href="../css/styles.css">
<link rel="stylesheet" href="../css/prism-tomorrow.css">
</head>
<body class='tutorial-page'>
<nav>
<ul class='nav--menu'>
<li class='nav--menu__item'>
<a class='nav--menu__item__link' href="../index.html">
<svg id='composi-logo' viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Composi Logo</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Composi-Logo-Solid" fill="#fff">
<path d="M1.77635684e-15,0 L95,0 L95,38 L209,38 L209,0 L300,0 L300,94 L265,93.8571663 L265,209 L300,209 L300,300 L209,300 L209,265 L95,265 L95,300 L1.77635684e-15,300 L1.77635684e-15,209 L40,209 L40,94 L1.77635684e-15,93.8571663 L1.77635684e-15,0 Z M107,107 L107,192 L192,192 L192,107 L107,107 Z" id="Combined-Shape"></path>
</g>
</g>
</svg>
<span class='logo__link--text'>Composi</span></a>
</li>
<li class='nav--menu__item'>
<a class='nav--menu__item__link' href="../docs/installation.html">Docs</a>
</li>
<li class='nav--menu__item selected'>
<a class='nav--menu__item__link' href="./index.html">Tutorials</a>
</li>
<li class='nav--menu__item'>
<a class='nav--menu__item__link external' target='__blank' href="https://github.com/composor/awesome-composi">Resources
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="14px" height="14px" viewBox="0 0 511.626 511.627" style="enable-background:new 0 0 511.626 511.627;"
xml:space="preserve">
<path fill='#fff' d="M392.857,292.354h-18.274c-2.669,0-4.859,0.855-6.563,2.573c-1.718,1.708-2.573,3.897-2.573,6.563v91.361
c0,12.563-4.47,23.315-13.415,32.262c-8.945,8.945-19.701,13.414-32.264,13.414H82.224c-12.562,0-23.317-4.469-32.264-13.414
c-8.945-8.946-13.417-19.698-13.417-32.262V155.31c0-12.562,4.471-23.313,13.417-32.259c8.947-8.947,19.702-13.418,32.264-13.418
h200.994c2.669,0,4.859-0.859,6.57-2.57c1.711-1.713,2.566-3.9,2.566-6.567V82.221c0-2.662-0.855-4.853-2.566-6.563
c-1.711-1.713-3.901-2.568-6.57-2.568H82.224c-22.648,0-42.016,8.042-58.102,24.125C8.042,113.297,0,132.665,0,155.313v237.542
c0,22.647,8.042,42.018,24.123,58.095c16.086,16.084,35.454,24.13,58.102,24.13h237.543c22.647,0,42.017-8.046,58.101-24.13
c16.085-16.077,24.127-35.447,24.127-58.095v-91.358c0-2.669-0.856-4.859-2.574-6.57
C397.709,293.209,395.519,292.354,392.857,292.354z"/>
<path fill='#fff' d="M506.199,41.971c-3.617-3.617-7.905-5.424-12.85-5.424H347.171c-4.948,0-9.233,1.807-12.847,5.424
c-3.617,3.615-5.428,7.898-5.428,12.847s1.811,9.233,5.428,12.85l50.247,50.248L198.424,304.067
c-1.906,1.903-2.856,4.093-2.856,6.563c0,2.479,0.953,4.668,2.856,6.571l32.548,32.544c1.903,1.903,4.093,2.852,6.567,2.852
s4.665-0.948,6.567-2.852l186.148-186.148l50.251,50.248c3.614,3.617,7.898,5.426,12.847,5.426s9.233-1.809,12.851-5.426
c3.617-3.616,5.424-7.898,5.424-12.847V54.818C511.626,49.866,509.813,45.586,506.199,41.971z"/>
</svg></a>
</li>
</ul>
</nav>
<article class='tutorial__article'>
<section>
<div class='tutorial'>
<h1>Introducing JSX</h1>
<p class="tutorial__intro">The following code has a line of JSX:</p>
<pre><code class="language-javascript">function Title() {
return <h1>This is a Title!</h1>
}</code></pre>
<p>JSX is a special syntax for defining markup inside JavaScript. It resembles HTML, but it is not. It is in fact an XML dialect. When libraries that use compile, they pass JSX code to a function that converts it into virtual nodes. These are then used to compare with earlier renders to see if the DOM needs to be updated. Based on the differences, only the parts that changed will be updated. This results in very efficient code. Although their are various hyperscript functions that can be used to define markup in JavaScript, JSX is much more concise. As an advantage, JSX more closely resembles the markup that will be created.</p>
<p> </p>
<h2>Embedding Expressions in JSX</h2>
<p>Because JSX is ultimately just JavaScript, you can embed JavaScript expressions in it. In the following example, <code>2 + 2</code>, <code>user.firstName</code>, and <code>formatName(user)</code> are all valid expressions:</p>
<p data-height="300" data-theme-id="6688" data-slug-hash="dZPMQN" data-default-tab="js,result" data-user="rbiggs" data-embed-version="2" data-pen-title="Composi Tuts - JSX-1" class="codepen">See the Pen <a href="https://codepen.io/rbiggs/pen/dZPMQN/">Composi Tuts - JSX-1</a> by Robert Biggs (<a href="https://codepen.io/rbiggs">@rbiggs</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p>We split the JSX over multiple lines for readability. We also recommend wrapping JSX in parentheses to avoid the pitfalls of automatic semicolon insertion caused by new lines.</p>
<h2>JSX is an Expression Too</h2>
<p>After compilation, JSX expressions become regular JavaScript objects, or virtual dom objects that describe markup.</p>
<p>That means that you can include JSX inside of if statements and for loops, assign it to variables, accept it as an argument, and return it from functions:</p>
<p data-height="300" data-theme-id="6688" data-slug-hash="ZaYWmg" data-default-tab="js,result" data-user="rbiggs" data-embed-version="2" data-pen-title="Composi Tuts - JSX-2" class="codepen">See the Pen <a href="https://codepen.io/rbiggs/pen/ZaYWmg/">Composi Tuts - JSX-2</a> by Robert Biggs (<a href="https://codepen.io/rbiggs">@rbiggs</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p> </p>
<h2>Specifying Attributes with JSX</h2>
<p>To specify string literals as attributes, use quotes:</p>
<pre><code class="language-javascript">const element = <div title="This is a DIV!" tabIndex="0"></div></code></pre>
<p>You can also embed a JavaScript expression between curly braces to create a value for an attribute. When you do so, remember not to use quotes around the JavaScript expression. Otherwise, the expression will get converted to a string and used as the attribute's value:</p>
<pre><code class="language-javascript">// Use a JavaScript expression for the image src value:
const element = <img src={user.avatarUrl} /></code></pre>
<p>Unlike React, Preact and Inferno, which require attribute names to use camel case, with Composi you can use their normal HTML versions. In the following example, notice that all the attributes in the JSX resemble normal HTML attributes:</p>
<p data-height="300" data-theme-id="6688" data-slug-hash="QOwNzz" data-default-tab="js,result" data-user="rbiggs" data-embed-version="2" data-pen-title="Composi Tuts - JSX-3" class="codepen">See the Pen <a href="https://codepen.io/rbiggs/pen/QOwNzz/">Composi Tuts - JSX-3</a> by Robert Biggs (<a href="https://codepen.io/rbiggs">@rbiggs</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p> </p>
<h2>JSX Tags Can Have Children</h2>
<p>A JSX tag can be single. In such a case it needs to be close with a forward slash:</p>
<pre><code class="language-javascript">const element = (
<img title='My Avatar' src='avatar.png' />
)</code></pre>
<p>You can also provide a JSX tag with children. When you do so, you insert the children between the parent tag's opening and closing, just like HTML:</p>
<pre><code class="language-javascript">const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
)</code></pre>
<p> </p>
<h2>JSX Prevents Injection Attacks</h2>
<p>JSX automatically encodes any potential script injection code. This helps prevent script injection attacks. It does this by converting all data to strings before rendering it to the DOM.</p>
<pre><code class="language-javascript">const title = function() {
alert('This is a script!')
}
class Test extends Component {
constructor(props) {
super(props)
this.root = 'header'
this.render = (data) => <h1>{data}</h1>
}
}
const test = new Test()
// When we pass the function title as data to the component,
// nothing gets output. The component will not render:
test.update(title)</code>
</pre>
<p>In the case that the data contained markup, this too will be escaped:</p>
<p data-height="300" data-theme-id="6688" data-slug-hash="zPxqeG" data-default-tab="js,result" data-user="rbiggs" data-embed-version="2" data-pen-title="Composi Tuts - JSX-4" class="codepen">See the Pen <a href="https://codepen.io/rbiggs/pen/zPxqeG/">Composi Tuts - JSX-4</a> by Robert Biggs (<a href="https://codepen.io/rbiggs">@rbiggs</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p> </p>
<h2>JSX Represents Objects</h2>
<p>When the JSX gets compiled, it is converted into an object that represents the nodes to be created:</p>
<pre><code class="language-javascript">function header() {
return (
<h1 class='heading' title='This is the header'>This is the Header!</h1>
)
}
const result = header()
// result will equal:
{
type: "h1",
props: {
title: "This is the header!",
class: "header"
},
children: ["This is the Header!"]
}</code></pre><a name='innerHTML2'></a>
<p> </p>
<h2>innerHTML</h2>
<p>By default any markup in data is escaped as a security precaution to help prevent cross-site scripting attacks. You can use the property <code>innerHTML</code> to inject data with markup into the document. <strong style='color: red;'>This is highly risky. Hackers can use this to inject malicious code into the docuemnt. Use it only if you are absolutely sure you can trust the source of the data.</strong></p>
<p>To use <code>innerHTML</code> just provide the data with the markup as the value for it. You could also use a function that returns the markup you want. Below is an example of how to use it:</p>
<pre><code class="language-javascript">function List({data}) {
return (
ul class="list">
{
data.map(item => <li innerHTML={item}></li>)
}
</ul>
)
}
const items = [
'<div><strong>Whatever</strong></div>'
'<div><em>Something else</em></div>']
mount(<List data={items} />, 'section')</code></pre>
<p>Because we are passing the data with markup directly to the list items through the property <code>innerHTML</code>, the markup will get converted into true DOM nodes. The result will look like this:</p>
<ul>
<li><div><strong>Whatever</strong></div></li>
<li><div><em>Something else</em></div></li>
</ul>
<p>In contrast, if we had just passed the data as normal, the markup would have been escaped:</p>
<pre><code class="language-javascript">function List({data}) {
return (
ul class="list">
{
data.map(item => <li>{item}</li>)
}
</ul>
)
}
const items = [
'<div><strong>Whatever</strong></div>'
'<div><em>Something else</em></div>']
mount(<List data={items} />, 'section')</code></pre>
<p>This would result in the following:</p>
<ul>
<li><div><strong>Whatever</strong></div></li>
<li><div><em>Something else</em></div></li>
</ul>
<p><strong>Note:</strong> When using <code>innerHTML</code> on an element, it's best to always have that element not contain any other content. This will replace any other content already in the element.</p>
<p> </p>
</div>
<aside>
<menu>
<ul class="tutorials__menu">
<li class="tutorials__menu__item">
<a href='./index.html'>Hello World</a>
</li>
<li class="tutorials__menu__item selected">
<a href='./introducing-jsx.html'>Introducing JSX</a>
</li>
<li class="tutorials__menu__item">
<a href='./rendering-elements.html'>Rendering Elements</a>
</li>
<li class="tutorials__menu__item">
<a href='./components-n-props.html'>Components and Props</a>
</li>
<li class="tutorials__menu__item">
<a href='./state-n-lifecycle.html'>State and Lifecycle</a>
</li>
<li class="tutorials__menu__item">
<a href='./conditional-rendering.html'>Conditional Rendering</a>
</li>
<li class="tutorials__menu__item">
<a href='./handling-events.html'>Handling Events</a>
</li>
<li class="tutorials__menu__item">
<a href='./lists-n-keys.html'>Lists and Keys</a>
</li>
<li class="tutorials__menu__item">
<a href='./forms.html'>Forms</a>
</li>
<li class="tutorials__menu__item">
<a href='./lifting-state-up.html'>Lifting State Up</a>
</li>
<li class="tutorials__menu__item">
<a href='./thinking-in-composi.html'>Thinking in Composi</a>
</li>
<li class="tutorials__menu__item">
<a href='./jsx-in-depth.html'>JSX In Depth</a>
</li>
<li class="tutorials__menu__item">
<a href='./advanced-state-management.html'>Advanced State Management</a>
</li>
<li class="tutorials__menu__item">
<a href='./composi-datastore.html'>Composi DataStore</a>
</li>
<li class="tutorials__menu__item">
<a href='./integrating-other-libs.html'>Integrating with Other Libraries</a>
</li>
<li class="tutorials__menu__item">
<a href='./composi-without-jsx.html'>Composi Without JSX</a>
</li>
<li class="tutorials__menu__item">
<a href='./immutable-data.html'>Immutable Data</a>
</li>
</ul>
</menu>
</aside>
</section>
</article>
<footer>
<section>
<svg id='composi-logo-footer' viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Composi Logo</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Composi-Logo-Solid" fill="rgba(255,255,255,0.5)">
<path d="M1.77635684e-15,0 L95,0 L95,38 L209,38 L209,0 L300,0 L300,94 L265,93.8571663 L265,209 L300,209 L300,300 L209,300 L209,265 L95,265 L95,300 L1.77635684e-15,300 L1.77635684e-15,209 L40,209 L40,94 L1.77635684e-15,93.8571663 L1.77635684e-15,0 Z M107,107 L107,192 L192,192 L192,107 L107,107 Z" id="Combined-Shape"></path>
</g>
</g>
</svg>
<h3>Composi is open source (MIT) and available on <a href='https://github.com/composor/composi' target='__blank'>Github</a> and <a href="https://www.npmjs.com/package/composi" target='__blank'>NPM</a>.</h3>
</section>
</footer>
<script src="../js/prism.min.js"></script>
<script src="../js/prism-jsx.js"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-115293685-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-115293685-1');
</script>s
</body>
</html>