-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
39 changed files
with
7,430 additions
and
3,387 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
repos: | ||
- repo: https://github.com/standard/standard | ||
rev: v17.1.0 | ||
hooks: | ||
- id: standard |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,122 @@ | ||
# else.js | ||
# one.js | ||
|
||
Build web apps with atomic components. | ||
A lightweight library to build reactive web apps — fast. | ||
|
||
One is in alpha and is under heavy development. You *can* use this for building web apps today, but the library is still considered very immature. All discussions, questions, ideas and PR's are welcome! | ||
|
||
## Usage | ||
|
||
```js | ||
import {e} from 'else' | ||
|
||
e( | ||
'div', | ||
({context}) => [ | ||
e('div', `Hello ${context.text}`), | ||
e('button', 'Click me!', { | ||
onclick() { | ||
context.text = context.text.split('').reverse().join('') | ||
}, | ||
}), | ||
], | ||
{ | ||
data() { | ||
return {text: 'World!'} | ||
}, | ||
mount: document.querySelector('#app'), | ||
} | ||
) | ||
import {o, mount} from 'one' | ||
|
||
const MyComponent = { | ||
data() { | ||
return { | ||
name: 'John Doe', | ||
} | ||
), | ||
view({ data }) { | ||
return o('div', [ | ||
o('p', `Hello ${data.name}`), | ||
]) | ||
}, | ||
} | ||
|
||
mount(document.body, MyComponent) | ||
``` | ||
### Router | ||
## Gotchas | ||
Since One is as lightweight as it is, there are a couple of gotchas that you should | ||
be aware of. Feel free to submit a PR if you've found a lightweight way of fixing these. | ||
However, these are gotchas, and can easily be avoided. | ||
### Conditional rendering | ||
When using conditional rendering in a components `view` function, you should | ||
structure your view in such a way, that you don't break the natural render tree. | ||
```js | ||
import {e, createRouter} from 'else' | ||
|
||
const Layout = e('div', [ | ||
e('header', 'Header'), | ||
e('main', [], {view: true}), | ||
e('footer', 'Footer'), | ||
]) | ||
|
||
const Home = e('div', e('div', 'This is home')) | ||
|
||
const AboutUs = e('div', e('div', 'This is all about us')) | ||
|
||
createRouter( | ||
[ | ||
{path: '/', component: Home}, | ||
{path: '/about-us', component: AboutUs}, | ||
], | ||
{ | ||
fallback: '/', | ||
layout: Layout, | ||
root: document.querySelector('#app'), | ||
// ok | ||
const Component = { | ||
view({ data }) { | ||
return o('div', [ | ||
o('ul', | ||
data.items.length | ||
? data.items.map(item => o('li', `${item.name}`)) | ||
: o('li', 'Loading') | ||
) | ||
]) | ||
} | ||
) | ||
} | ||
|
||
const Component = { | ||
view({ data }) { | ||
return o('div', | ||
data.items.length | ||
? o('nav', data.items.map(item => o('a', `${item.name}`))) | ||
// Notice that both ternaries return same root element. | ||
: o('nav', o('div', 'Loading...')) | ||
) | ||
} | ||
} | ||
|
||
const Component = { | ||
view ({ data }) { | ||
return o( | ||
'ul', | ||
data.items.map(item => o('li', `${item.name}`)) | ||
) | ||
} | ||
} | ||
|
||
// not ok | ||
const Component = { | ||
view({ data }) { | ||
return data.items.length | ||
? o('ul', data.items.map(item => o('li', `${item.name}`))) | ||
: o('div', o('p', 'Loading...')) | ||
} | ||
} | ||
|
||
const Component = { | ||
view({ data }) { | ||
return o('div', | ||
data.items.length | ||
? o('ul', data.items.map(item => o('li', `${item.name}`))) | ||
: o('div', o('p', 'Loading...')) | ||
) | ||
} | ||
} | ||
|
||
const Component = { | ||
view({ data }) { | ||
if (!data.items.length) { | ||
return o('div', 'Loading') | ||
} | ||
|
||
return o('div', 'p', 'Items loaded...') | ||
} | ||
} | ||
``` | ||
### Dangling TextNodes | ||
One is built around diffing HTML elements and not text nodes. This means that you shouldn't have "dangling" text nodes. | ||
A dangling text node is a text node with HTML element siblings. See below for examples. | ||
It *is* possible, but since One doesn't care about text nodes, they will often be removed from the DOM during rendering. | ||
```js | ||
// ok | ||
o('div', | ||
o('h1', 'This is a heading'), | ||
o('p', 'This is a paragraph'), | ||
) | ||
|
||
// not ok | ||
o('div', | ||
o('h1', 'This is a heading'), | ||
'This is a "dangling" text node', | ||
) | ||
``` |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,41 @@ | ||
import {createRouter} from '../dist/else' | ||
import {Home, About, Layout, Form, Post} from './pages' | ||
import { o, mount } from '../dist/one' | ||
import { getItems } from './services/get-items' | ||
|
||
createRouter( | ||
[ | ||
{path: '/', component: Home}, | ||
{path: '/about-us', component: About}, | ||
{path: '/about-us/:id', component: About}, | ||
{path: '/form', component: Form}, | ||
{path: '/post/:id', component: Post}, | ||
{path: '/some/:param/:id', component: About}, | ||
], | ||
{ | ||
fallback: '/', | ||
layout: Layout, | ||
root: document.querySelector('#app'), | ||
const Component = { | ||
data () { | ||
return { | ||
items: [] | ||
} | ||
}, | ||
async onmount ({ data }) { | ||
data.items = await getItems() | ||
}, | ||
view ({ data }) { | ||
return o('div', [ | ||
o('h1', 'Items'), | ||
o(List, { items: data.items }) | ||
]) | ||
} | ||
) | ||
} | ||
|
||
const List = { | ||
view ({ props }) { | ||
return o('div', [ | ||
o('ul', | ||
props.items.length | ||
? props.items.map(item => o('li', `${item.name}`)) | ||
: o('li', 'Loading') | ||
) | ||
]) | ||
} | ||
} | ||
|
||
const View = { | ||
view () { | ||
return o('div', [ | ||
o(Component) | ||
]) | ||
} | ||
} | ||
|
||
mount(View, document.body) |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.