Skip to content

Latest commit

 

History

History
272 lines (203 loc) · 8.08 KB

README.md

File metadata and controls

272 lines (203 loc) · 8.08 KB

Atomico/core

Atomico es una biblioteca para la creacion de interfaces basada en componentes funcionales todo gracias a una pequeña implementación del virtual-dom ligera(2.6kB) y eficiente.

Índice

  1. Objetivos
  2. Componentes
    1. Uso de eventos
    2. Uso del shadowDom
    3. Uso de contextos
    4. Listas con clave
  3. 🔥 Hooks
    1. useState
    2. useEffect
    3. useRef
    4. useMemo
    5. useContext
  4. Utilidades
    1. Atomico ❤️ web-component
  5. 👷 Ayuda!

Objetivos

  1. Ligero al igual que otras librerías Atomico busca ser sumamente pequeño < 3kB.
  2. Moderno Atomico busca implementar tecnologías actuales dentro de la generación de componentes, sea por ejemplo el uso del shadowDom permitiendo que Atomico se acople sumamente bien a los **web-components **
  3. Simple ya que sus componentes solo serán funciones.

Componentes

Los componentes dentro de atómico son solo funciones, estas pueden representar una parte de la vista y poder poseer opcionalmente uno o mas estados y ciclo de vida.

import { h, render } from "@atomico/core";

function App() {
    return <h1>I'm Atomico!</h1>;
}

render(<App />, document.getElementById("app"));

Note que atomico importa de 2 variables h que es la asaignacion de pragma para transpilar el codigo JSX a JS y render que permite imprimir el contenido asociado al componente.

Uso de eventos

Los eventos dentro de atómico se definen no por prefijo sino por tipo, estos eventos solo se aplican si el nodo es un HTMLElement o SVGElement.

function handler(event) {
    /**...*/
}
<button click={handler} />;

Uso del shadowDom

Ud puede habilitar el shadow-dom para ser usado dentro de un nodo, mediante la definición de la propiedad shadowDom

<div shadowDom>
    <style>{`
		:host{width:100px;height:100px}
	`}</style>
    <h1>inside shadowDom!</h1>
</div>;

Esto permite aislar el nodo del resto del documento.

Uso de contextos

Los contextos dentro de atómico son simples de manipular, mediante la definición de la propiedad context

function ChildComponent(props, context) {
    return <h1>{context.message}</h1>;
}
<ParentComponent context={{ message: "I'm context" }}>
    <ChildComponent />
</ParentComponent>;

Ud también puede recuperar contextos de espacio de nombre mediante useContext, este es ideal para usar dentro de hooks personalizados.

Listas con clave

la propiedad key permite añadir un identificador a un Elemento que debe ser único entre hermanos.

<ul>
    <li key="1">one</li>
    <li key="2">two</li>
    <li key="3">tree</li>
</ul>;

Esto trae como beneficio:

  1. Reducir mutaciones del DOM asociadas a la reordenar listas de nodos sin recrear el elemento
  2. Reducir mutaciones del DOM asociadas a al eliminación de nodos
  3. Reducir mutaciones del DOM asociadas a la inserción de nuevos nodos.

Hooks

Los hooks fueron introducidos por React, estos tiene la gran ventaja de controlar el componente sin conocer el contexto de invocación, ud lograra un código mas reutilizable que una clase.

Los hooks llegan a Atomico para potenciar la creación de componentes funcionales.

import { h, useState } from "@atomico/core";

export function Counter() {
    let [count, setCount] = useState(0);
    return (
        <div>
            {count}
            <button click={() => setCount(count + 1)}>icrement</button>
        </div>
    );
}

useState

El api basa en el useState de react, este permite vincular un estado al componente funcional, ud puede crear tantos como ud necesite.

import { h, useState } from "@atomico/core";

export function Counter() {
    let [count1, setCount1] = useState(0);
    // ud puede usar una funcion para crear el estado inicial
    let [count2, setCount2] = useState(() => 0);
    return (
        <div>
            {count1}
            {count2}
            <button click={() => setCount1(count + 1)}>icrement count 1</button>
            <button
                click={() => {
                    // note que ud puede usar un callback para recuperar el estado y retornar uno nuevo
                    setCount2(state => state + 1);
                }}
            >
                icrement count 2
            </button>
        </div>
    );
}

useEffect

El api se basa en el useEffect de react, permite añadir un callback de ciclo de vida del componente, este posee la ventaja que puede limpiar los efectos sea después de cada renderización o eliminación del elemento.

import { h, useState, useEffect } from "@atomico/core";

export function AutoCounter() {
    let [count, setCount] = useState(0);
    useEffect(() => {
        setTimeout(() => {
            setCount(count + 1);
        }, 1000);
    });
    return <div>{count}</div>;
}

El ejemplo anterior no es beneficioso ya que no controla la eliminacion de setTimeout

EL ciclo de vida al que accede useEffect es Created ,Updated y Remove, este ultimo es solo escuchado por el retorno del primer callback.

import { h, useState, useEffect } from "@atomico/core";

export function AutoCounter() {
    let [count, setCount] = useState(0);
    useEffect(() => {
        let timeout = setTimeout(() => {
            setCount(count + 1);
        }, 1000);
        return () => clearTimeout(timeout);
    });
    return <div>{count}</div>;
}

este ejemplo permite limpiar los efectos creados previamente dentro del mismo callback.

useEffect admite un segundo argumento capas de controlar la ejecucion del callback a base de un arreglo, ejemplo si ninguna propiedad ha cambiado entre render el callback asociado a useEffect no cambiara.

import { h, useState, useEffect } from "@atomico/core";

export function AutoCounter(props) {
    let [count, setCount] = useState(0);
    useEffect(() => {
        let interval = setInterval(() => {
            setCount(++count);
        }, props.ms);
        return () => clearInterval(interval);
    }, [props.ms]);
    return <div>{count}</div>;
}

useMemo

el api se basa en useMemo de React, este permite recordad el retorno de un callback limitando su ejecución a la comparación del segundo argumento entre renders. El segundo argumento debe ser un arreglo

import { h, useMemo } from "@atomico/core";

function Component(){
    let list = useMemo(() => {
        let list = [];
        for (let key = 0; key < props.length; key++) list.push({ key });
        return list;
    }, [props.length]);
}

useRef

el api se basa en useRef de React, este crea un objeto para trabajar como referencia, la instancia inicial de este objeto no se pierde entre renders

import { h, useRef } from "@atomico/core";

function Component(){
    let ref = useRef();
    return <button ref={ref}>...</button>;
}

Utilidades

Atomico + web-components

Atomico en su primeras versiones se basaba en clases, similar a como opera hoy LitElement, pero esto no me trajo beneficio, en cambio preferi independizar su proceso de virtual-dom y manejar externamente la fusión con web-components, registrar un componente con atomico es usar JSX.

import { register } from "@atomico/web-component";

function App(props) {
    return (
        <h1>
            {props.name}
            {props.age * 2}
        </h1>
    );
}

register(
    <my-app name age={Number}>
        {App}
    </my-app>
);

Ayuda

El código de Atomico lo he reescrito en tan solo 2 días y requiere pruebas, actualmente usa Jest, pero es mejor migrar a Karma para verificar de mejor forma el manejo de listas con clave y las mutaciones asociadas al dom, sin el uso de JSDOM