UNPKG

6.36 kBMarkdownView Raw
1Composi
2=======
3
4Contents
5--------
6- [Installation](../README.md)
7- [JSX](./jsx.md)
8- Hyperx
9 - [Hyperx](#Hyperx)
10 - [Installation](#Installation)
11 - [Importing Hyperx for Use](#Importing-Hyperx-for-Use)
12 - [Using Template Literals](#Using-Template-Literals)
13 - [Partial Attributes in Template Literals](#Partial-Attributes-in-Template-Literals)
14 - [Hyperx with Components](#Hyperx-with-Components)
15 - [Custom Tags](#Custom-Tags)
16 - [Handling Sibling Tags](#Handling-Sibling-Tags)
17- [Hyperscript](./hyperscript.md)
18- [Functional Components](./functional-components.md)
19- [Mount, Render and Unmount](./render.md)
20- [Components](./components.md)
21- [State](./state.md)
22- [Lifecycle Methods](./lifecycle.md)
23- [Events](./events.md)
24- [Styles](./styles.md)
25- [Unmount](./unmount.md)
26- [State Management with DataStore](./data-store.md)
27- [Third Party Libraries](./third-party.md)
28- [Deployment](./deployment.md)
29- [Differrences with React](./composi-react.md)
30
31## Hyperx
32
33If you do not like JSX, you can instead use Hyperx. This lets you define your component markup with ES6 template literals. At build time, Hyperx converts the template literals into hyperscript functions that Composi's virtual DOM can understand.
34
35## Installation
36
37First you will need to install Hyperx in your project. Open your terminal and run:
38
39```sh
40npm i -D hyperx
41```
42
43Then open your project's `gulpfile.js`. Scroll down to the `build` task and look for `commonjs(),`. Update it to the following:
44
45```javascript
46commonjs({
47 include: 'node_modules/**'
48}),
49```
50
51You will need to update this by adding in a new line: `ignoreGlobal: true`. This will enable Rollup to import Hyperx like a noraml ES6 module:
52
53```javascript
54commonjs({
55 include: 'node_modules/**',
56 ignoreGlobal: true
57}),
58```
59
60## Importing Hyperx for Use
61
62Next you'll need to import Hyperx into any file where you want to use it. That means any file in which you are importing Composi's `Component` class, you'll want to also import Hyperx. Besides importing it, you'll also need to let Hyperx know that it should use Composi's `h` function when it converts template literals into functions. You do that by importing the `h` function and passing it to Hyperx:
63
64```javascript
65import {h, Component} from 'composi'
66import {hyperx} from 'hyperx'
67
68// Tell Hyperx to use the Composi h function:
69const html = hyperx(h)
70```
71
72We can now use the `html` function to define template literals as markup for Composi components. If you have not used template literals before, you might want to read up on [how they work](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals).
73
74
75## Using Template Literals
76
77You can use template literals just as you normally would. Whereas JSX uses `{someVariable}` to evaluate variables, template literals use `${someVariable}`. Notice how we capture Hyperx as a tagged template literal function `html`, which we then use to define markup:
78
79```javascript
80import {h, Component} from 'composi'
81import {hyperx} from 'hyperx'
82const html = hyperx(h)
83
84// Use class attribute as normal:
85function header(data) {
86 return html`
87 <header>
88 <h1 class='title'>${data.title}</h1>
89 <h2 class='subtitle'>${data.subtitle}</h2>
90 </header>
91 `
92}
93```
94
95## Partial Attributes in Template Literals
96
97Unlike JSX, Hyperx does support partial attribute values. The following code will work without a problem:
98
99```javascript
100import {h, Component} from 'composi'
101import {hyperx} from 'hyperx'
102const html = hyperx(h)
103
104function userList(users) {
105 return html`
106 <ul>
107 {
108 users.map(user => <li class='currently-${user.employed ? "employed" : "unemployed"}'>${user.name}</li>)
109 }
110 </ul>
111 `
112}
113```
114
115
116## Hyperx with Components
117
118We can use Hyperx directly inside a Component as part of the `render` function. Notice that when we need to loop over the arrray of items, we use `html` to define the list item. If we instad made that part a template literal, the markup would be returned as an escaped string. Of course, if that is what you want, that is how you would do it.
119
120```javascript
121const fruitsList = new Component({
122 container: '#fruit-list',
123 state: fruits,
124 render: (fruits) => html`
125 <ul class='list'>
126 ${
127 fruits.map(fruit =>
128 html`<li>
129 <div>
130 <h3>{fruit.title}</h3>
131 <h4>{fruit.subtitle}</h4>
132 </div>
133 <aside>
134 <span class='disclosure'></span>
135 </aside>
136 </li>`
137 )
138 }
139 </ul>
140 `
141})
142```
143
144## Custom Tags
145
146JSX has the concept of custom tags that allow you to break up complex markup into smaller, reusable pieces. You can accomplish the same thing with Hyperx. Define the functions that return the markup and then use them inside the parent render function as methods inside dollar sign curly braces:
147
148```javascript
149function listItem(fruit) {
150 return html`
151 <div>
152 <h3>${fruit.name}</h3>
153 <h4>${fruit.price}</h4>
154 </div>`
155}
156
157// Function to return static markup:
158function disclosure() {
159 return html`
160 <aside>
161 <span class='disclosure'></span>
162 </aside>`
163}
164
165//Now that we have some custom tags, we can use them as follows:
166
167const fruitsList = new Component({
168 container: '#fruit-list',
169 state: fruits,
170 render: (fruits) => html`
171 <ul class='list'>
172 {
173 fruits.map(fruit => (
174 <li>
175 ${listItem(fruit)}
176 ${disclosure()}
177 </li>
178 )
179 }
180 </ul>
181 `
182})
183```
184
185## Handling Sibling Tags
186
187Like JSX, your markup must always have one enclosing tag. Although it is legal to return a set of sibling elements in an ES6 template literal, this will not work with Composi's `h` function. That's because each tag you define will be converted into a function. As such, there needs to be one final, top-most function that returns the markup.
188
189Bad markup:
190
191```javascript
192const badHyperx = new Component({
193 container: '#list',
194 render: () => html`
195 <li>One</li>
196 <li>Two</li>
197 <li>Three</li>
198 `
199})
200```
201
202The above code will not build. Instead you need to create the entire list like this and insert it in some higher element as the container:
203
204```javascript
205const goodHyperx = new Component({
206 container: '#listDiv',
207 render: () => html`
208 <ul>
209 <li>One</li>
210 <li>Two</li>
211 <li>Three</li>
212 </ul>
213 `
214})
215```