v1.18.3

DOM reativo.
Sem etapa de build.

Um pequeno sistema de modelagem baseado em padrões da web que traz reatividade, estado e componentes para o vanilla JavaScript. Sem empacotadores. Sem JSX. Sem mágica.

7,6 KBCDN gzip
0dependências de terceiros
100%padrões da web
javascript
import { html, state, effect } from '@beforesemicolon/markup'

const [count, updateCount] = state(0)

const doubleCount = () => count() * 2

effect(() => {
    console.log(count())
})

const countUp = () => updateCount((prev) => prev + 1)
const countDown = () => updateCount((prev) => prev - 1)

const App = html`
    <h1>Conunter</h1>
    <p><strong>Current count</strong>: ${count}</p>
    <p><strong>Double count</strong>: ${doubleCount}</p>
    <button type="button" onclick="${countDown}">-</button>
    <button type="button" onclick="${countUp}">+</button>
`

App.render(document.getElementById('app'))

Amplie a forma como você desenvolve.

Use Markup sozinho para modelos reativos ou adicione pacotes complementares focados quando seu aplicativo precisar de elementos personalizados, roteamento ou localização.

Web Components

@beforesemicolon/web-component

Uma camada reativa sobre a API Web Components nativa. Mantenha o modelo de modelo do Markup ao adicionar props, estado, ciclos de vida e estilos com escopo.

Ler a documentação

Router

@beforesemicolon/router

Roteamento declarativo como tags de componentes da web. Componha páginas, layouts aninhados, rotas de consulta e visualizações de carregamento lento sem adotar um roteador de estrutura.

Ler a documentação

Intl

@beforesemicolon/intl

Localização para interfaces que priorizam os componentes. Adicione escopos de localidade, mensagens traduzidas e auxiliares de formatador que se ajustam naturalmente à interface do usuário orientada por Markup.

Ler a documentação

A plataforma é a estrutura.

Padrões da Web, APIs da Web e JavaScript moderno são tudo que você precisa. Markup apenas adiciona reatividade.

Reativo

Literais e funções de modelo criam DOM reativo com estado, ciclos de vida e efeitos colaterais.

Minúsculo - menos de 8 KB gzip

A compilação do navegador CDN transfere cerca de 7,6 KB gzip. Envie aplicativos empresariais sem um megabyte de estrutura.

Padrões da Web

Três APIs simples que ampliam a plataforma que você já conhece. Sem abstrações proprietárias.

Plug & Play

Insira uma tag de script e pronto. Nenhuma etapa de construção, nenhum JSX, nenhum arquivo de configuração.

Web Components

Sobrecarregue o Web Components nativo com reatividade. Ignore a manipulação manual do DOM.

Atualizações Cirúrgicas

A renderização baseada em dados significa que o DOM atualiza apenas onde e quando realmente necessário.

Parece HTML. Parece mágica.

Estado reativo, composição de componentes e ciclo de vida — tudo a partir das primitivas JavaScript que você já conhece.

EXEMPLO 01
Tarefas + localStorage
javascript
import { html, state, effect, repeat } from '@beforesemicolon/markup'

const [todos, setTodos] = state(
    JSON.parse(localStorage.getItem('todos') ?? '[]')
)

effect(() => {
    localStorage.setItem('todos', JSON.stringify(todos()))
})

const addTodo = () => {
    const text = window.prompt('What needs doing?')?.trim()

    if (text) setTodos((prev) => [...prev, { text, done: false }])
}

const toggle = (i) =>
    setTodos(todos().map((t, idx) => (idx === i ? { ...t, done: !t.done } : t)))

html`
    <button type="button" onclick="${addTodo}">Add</button>
    <ul>
        ${repeat(
            todos,
            (todo, i) => html`
                <li
                    class="${todo.done ? 'done' : ''}"
                    onclick="${() => toggle(i)}"
                >
                    ${todo.text}
                </li>
            `
        )}
    </ul>
`.render(document.querySelector('#app'))
EXEMPLO 02
Componente de botão usando WebComponent
javascript
import { WebComponent, html } from '@beforesemicolon/web-component'
import stylesheet from './button.css' with { type: 'css' }

class Button extends WebComponent {
    static observedAttributes = ['disabled', 'type']

    type = 'button'
    disabled = false

    stylesheet = stylesheet

    handleClick = (evt) => {
        evt.stopPropagation()
        this.dispatch('click')
    }

    render = () => {
        return html`
            <button ${this.props} class="btn" onclick="${this.handleClick}">
                <slot></slot>
            </button>
        `
    }
}

customElements.define('bfs-button', Button)
EXEMPLO 03
Suspense (assíncrono)
javascript
import { html, suspense } from '@beforesemicolon/markup'

const loadUser = async () => {
    const res = await fetch('/api/me')
    return res.json()
}

const renderUser = async () => {
    const user = await loadUser()
    return html`
        <article>
            <h2>${user.name}</h2>
            <p>${user.bio}</p>
        </article>
    `
}

html`
    <h1>Profile</h1>

    ${suspense(
        renderUser,
        html`<p>Loading profile...</p>`, // fallback
        (err) => html`<p>Failed: ${err.message}</p>` // catch
    )}
`.render(document.querySelector('#app'))
EXEMPLO 04
Roteamento de página
html
<!-- in <head>:
<script src="https://unpkg.com/@beforesemicolon/router/dist/client.js"></script>
-->

<nav>
    <page-link path="/">Home</page-link>
    <page-link path="/about">About</page-link>
    <page-link path="/users">Users</page-link>
</nav>

<page-route path="/">
    <h1>Welcome home</h1>
</page-route>

<page-route path="/about" src="./pages/about.js"></page-route>

<page-route path="/users" exact="false">
    <page-route src="./pages/users.js"></page-route>
    <page-route path="/:userId" src="./pages/user.js"></page-route>
</page-route>

<page-route path="/404"> 404 - Page not found! </page-route>

<page-redirect path="/404" title="404 - Page not found!"></page-redirect>
EXEMPLO 05
Ciclos de vida do modelo
javascript
import { html, state } from '@beforesemicolon/markup'

const [seconds, setSeconds] = state(0)

html` <p>Elapsed: ${seconds}s</p> `
    .onMount(() => {
        // runs once when attached to the DOM
        const id = setInterval(() => setSeconds(seconds() + 1), 1000)
        return () => clearInterval(id)
    })
    .onUpdate(() => {
        // runs every time a tracked value changes
        console.log('tick', seconds())
    })
    .render(document.querySelector('#app'))

Instale em segundos.

Escolha sua arma. Markup funciona em qualquer lugar que o JavaScript seja executado.

<script src="https://unpkg.com/@beforesemicolon/markup/dist/client.js"></script>
npm install @beforesemicolon/markup
yarn add @beforesemicolon/markup
pnpm add @beforesemicolon/markup

Construa a Web, do seu jeito.

Junte-se aos desenvolvedores que entregam mais rápido com uma estrutura que respeita a plataforma e o seu tempo.