Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lewis-wow/kiq
Blazing fast virtual DOM class component based library for reactive UI
https://github.com/lewis-wow/kiq
blazing-fast component declarative-ui dom front-end html javascript reactive ui virtual virtual-dom-library
Last synced: about 2 months ago
JSON representation
Blazing fast virtual DOM class component based library for reactive UI
- Host: GitHub
- URL: https://github.com/lewis-wow/kiq
- Owner: lewis-wow
- License: mit
- Created: 2021-02-07T18:03:23.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2023-09-26T10:29:33.000Z (over 1 year ago)
- Last Synced: 2024-11-08T02:09:40.342Z (2 months ago)
- Topics: blazing-fast, component, declarative-ui, dom, front-end, html, javascript, reactive, ui, virtual, virtual-dom-library
- Language: TypeScript
- Homepage:
- Size: 719 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Kiq.js
Blazing fast virtual DOM class component based library for reactive UI
## Inspiration
React.js, Jason Yu that creates simple virtual DOM library in about 50 minutes
## Goal
Goal is to create very simple, lightweight and very fast virtual DOM library with smart diff algorithm and performance optimalizations.
## Optimalizations
First render is called with requestAnimationFrame, so the main thread is no blocked and components will render when browser is ready to reflow and repaint the page.
Every changes are called as one big bundle of changes in one time, so browser don't reflow and repaint every time for every small change in DOM but 1 repaint and reflow for one state change.
## Components
Components are javascript classes with special methods.
## createElement
There are many posibilities how to create a virtual element. Some of them are with cleaner syntax.
## Virtual element
Virtual element is plain javascript object.
### vanilla js
```js
Kiq.createElement('div', { className: 'test' }, count)
```### htm.js
htm is library that transforms template literals to virtual element.
```js
const html = htm.bind(Kiq.createElement);html`
${count}`
```### babel jsx
jsx is Javascript XML, babel can compile the jsx code to `createElement` functions.
The code must start with jsx pragma.
It provides HTML-like syntax.```js
/** @jsx Kiq.createElement */{count}
```### create components
Produce components is the same as virtual nodes, but the first parameter replace tag name with your component class.
Attributes are props and children are ```props.children```.### props.children
In the component props can be passed as children too.
Your children are then in props.children array.```js
```
```js
Kiq.createElement(Parent, null,
Kiq.createElement(Child)
);
```The Parent component has now access to special ```props.children``` Array where on the first index is `Child` component.
## render
This function should be called only once in the whole app.
It renders your app and produce real DOM objects and mount them to your page.```js
Kiq.render(Kiq.createElement(App), document.getElementById('app'));
```## Components example
``` js
class Counter extends Kiq.Component {
state = {
count: 0,
}Element(props, state) {
return (
this.setState({ count: state.count + 1 })}>
{state.count}
)
}
}
```## Kiq in ES5
If you want to your code is compatible with IE11 and other ES5 browsers you can use some javascript bundler to compile the code down to ES5.
## state and props
These two are data that is used inside component.
Simply props are "function parameters" and state are "function local variables", so props are not private inside component and income from the outside.
State are private in component and there is not way to set state of component in another component (actually there is a way to do that, it is in the article below).
State are reactive object, props are non reactive object, props should be only read-only.## setState
Component.setState component method can be only called if component is rendered, will mount or is mounted, else it throws error.
You shouldn't to mutate the original value of state as you can see in the example, instead of ```++state.count``` use ```state.count + 1```.
Every changes should be immutable.
On every setState call component will rerender, so on multiple changes, use setState only once and do all the changes in one.
setState is synchronnous function.### Can I set props?
No. There is no way to set props, because it is anti-pattern.
Props should be read-only.### How to setState of parent component inside child component?
It is simple, you have to pass the "setter" function to the props of child component like this:
```js
class Parent extends Kiq.Component {
state = {
count: 0,
}setCount() {
this.setState({
count: this.state.count + 1,
})
}Element(props, state) {
return
}
}class Child extends Kiq.Component {
Element(props, state) {
return {props.count}
}
}
```### Kiq.Component vs WebComponents
WebComponents are encapsulated DOM elements, but Kiq.Component is logical encapsulation of element and data definition, where is used declarative DOM management.
### Conditional rendering
```js
class Fetch extends Kiq.Component {
state = {
books: null,
}onComponentRender() {
fetch("https://www.anapioficeandfire.com/api/books")
.then((res) => res.json())
.then((res) => {
this.setState({
books: res,
})
})
}Element() {
if (!this.state.books) {
returnLoading...
}return
{JSON.stringify(this.state.books)}
}
}
```### List rendering
```js
class List extends Kiq.Component {
state = {
arr: [0, 1, 2, 3, 4],
}Element() {
return (
- {item} )}
{this.state.arr.map((item) =>
)
}
}
```
### Simple mouse move
Simple mouse move example to show how easy is declarative way of DOM changes.
Declarative programming means you say what to do, but no how to do.
```js
class MouseMove extends Kiq.Component {
state = {
x: 0,
y: 0,
count: 0,
}
onComponentRender() {
window.addEventListener("mousemove", (e) => {
this.setState({
x: e.x,
y: e.y,
})
})
}
Element(props, state) {
return (
this.setState({ count: state.count + 1 })}
style={{
position: "absolute",
left: this.state.x + "px",
top: this.state.y + "px",
}}
>
{state.count}
)
}
}
```