Skip to content

Başlangıç ​

PreffX, reaktif DOM oluşturmaya yönelik, kendine güvenen bir JS kütüphanesidir. React ve Preact'ten esinlenmiş olsa da, sinyal tabanlı kendine has bir yaklaşım sunar.

⚠️ Proje şu anda deneysel aşamadadır; üretim (production) ortamında kullanmayınız ⚠️

Temel prensipler ​

  • React benzeri JSX sözdizimi;
  • Reaktivite çekirdeği olarak Preact sinyalleri;
  • Yalnızca sinyaller yeniden oluşturmayı (rerender) tetikler;
  • Her bileşen yalnızca bir kez çalıştırılır;
  • Bileşen özellikleri (props) ilk argüman olarak, tüm yardımcı araçlar (utilities) ise ikinci argüman olarak gelir; bunları ayrıca içe aktarmanıza (import) gerek yoktur;
  • Hem senkron hem de asenkron fonksiyon bileşenleri desteklenir;
  • Özellikler (properties) ve nitelikler (attributes) arasında ayrım yapılır (tüm özelliklerin başına $ işareti eklenir) — örneğin, $value bir özellik (property), value ise bir niteliktir (attribute).

Kurulum ​

Önerilen yöntem, proje için isim, dil ve CSS çözümünü belirlemenize olanak tanıyan etkileşimli create-preffx aracını kullanmaktır:

bash
npx create-preffx

Alternatif olarak degit kullanabilirsiniz:

bash
npx degit msabitov/vite-preffx preffx-starter 
cd preffx-starter         
npm install        
npm run dev

Ayrıca StackBlitz demosunu da deneyebilirsiniz.

Hızlı başlangıç ​

Bir kök (root) oluşturun ve bileşeninizi bağlayın (mount edin):

tsx
import { createRoot } from 'preffx';
import { App } from './App';

createRoot().mount(App, { node: document.getElementById('app')! });

Bileşeni tanımlayın; props ve yardımcı araçlar (utilities) argüman olarak gelir:

tsx
import type { PC } from 'preffx';

export const App: PC = (props, { signal }) => {
    const count = signal(0);
    return (
        <button onClick={() => { count.value += 1 }}>
            Count is {count}
        </button>
    );
};

Örnekler ​

  • Basit sayaç:
tsx
import type { PC } from 'preffx';

export const App: PC = (props, { signal }) => {
    const count = signal(0);
    return <button
        onClick={() => {
            count.value += 1
        }}
    >
        Count is {count}
    </button>
};
  • Eleman referansları nasıl oluşturulur:
tsx
import type { PC } from 'preffx';

export const App: PC = (props, { signal }) => {
    const signalRef = signal();
    return <div $ref={signalRef}>
        <div
            $ref={(refVal) => {
                // it will be called after element mounted with refVal = HTMLDivElement
                // and before element destroyed with refVal = null
            }}
            $onMount={(refVal) => {
                // it will be called after element mounted with refVal = HTMLDivElement
            }}
            $onDestroy={() => {
                // it will be called before element destroyed with refVal = HTMLDivElement
            }}
        >
            Refs
        </button>
    </div>
};
  • Yaşam döngüsü kancaları:
tsx
import type { PC } from 'preffx';

export const App: PC = (props, { onMount, onDestroy }) => {
    const { count } = props;

    onMount(() => {
        // some mount logic
    });
    
    onDestroy(() => {
        // some destroy logic
    });
    return <button
        onClick={() => {
            count.value += 1
        }}
    >
        Count is {count}
    </button>
};
  • Liste oluşturma:
tsx
import type { PC } from 'preffx';

export const App: PC = (props, { For }) => {
    const items = signal([
        {
            name: 'First'
        },
        {
            name: 'Second'
        }
    ]);

    return <ul>
        <For
            items={items}
            callback={(item) => <li>Item with name: {item.name}</li>}
            fallback={<li>No items</li>}
        />
    </ul>;
};
  • Bağlam yönetimi:
tsx
import type { PC } from 'preffx';

const contextKey = 'ctx-counter';

const AnotherComponent: PC = (props, { context }) => {
    // read context
    const counter = context[contextKey];
    return <span>
        {counter}
    </span>;
};

export const App: PC = (props, { signal, context }) => {
    const counter = signal(0);
    // modify context
    context[contextKey] = counter;
    return <p>
        {valueFromContext}
        <AnotherComponent />
    </p>;
};
  • Asenkron bileşenler:
tsx
import type { APC } from 'preffx';
import { getData } from './data';
import { AnotherComponent, AnotherAsyncComponent } from './components';

const AsyncComponent: APC<{
    name: string;
}> = async (props, utils) => {
    const data = await getData()
    const componentRoot = await <AnotherAsyncComponent name='nested'/>;
    return <div>
        <AnotherComponent data={data} />
        {componentRoot}
    </div>;
}
  • Hata yönetimi:
tsx
import type { PC } from 'preffx';
import { AnotherComponent } from './components';

export const App: PC = (props, { Catch }) => {
    return <div>
        Sometimes components return errors
        <Catch fallback={<div>Catched!</div>}>
            <AnotherComponent />
        </Catch>
    </div>;
};
  • Ertelenmiş değer işleme:
tsx
import type { PC } from 'preffx';
import { AsyncComponent } from './components';

export const App: PC = (props, { computed, Defer }) => {
    const def = computed(() => <AsyncComponent id={props.id} />);
    return <Defer
        value={def}
        initial={<div>Please wait</div>}
    />;
};
  • Portal:
tsx
import type { PC } from 'preffx';

export const App: PC = (props, { Portal }) => {
    return <>
        <span>Some text inside current tree</span>
        <Portal root={document.getElementById('portal')}>
            <div>Text inside portal</div>
        </Portal>
    </>;
};
  • Benzersiz tanımlayıcılar:
tsx
import type { PC } from 'preffx';

export const App: PC = (props, { id }) => {
    // get unique id
    const inputId = id();
    return <>
        <label>
            Password:
            <input
                type="password"
                aria-describedby={inputId}
            />
        </label>
        <p id={inputId}>
            The password should contain at least 18 characters
        </p>
    </>;
};
  • Basit yönlendirme:
tsx
import type { PC } from 'preffx';

export const App: PC = (props, { computed, url }) => {
    const routeContent = computed(() => {
        // depends on url signal
        switch(url.value.pathname) {
            case '/home':
                return <div>Home page content</div>
            case '/contacts':
                return <div>Contacts page content</div>;
            default:
                return <div>Other page content</div>
        }
    });
    return <div>
        <a href='/home'>Home</a>
        <a href='/contacts'>Contacts</a>
        {routeContent}
    </div>;
};
  • i18n örneği:
tsx
import type { PC } from 'preffx';

const dictionary = {
    en: {
        openProfile: 'Open profile',
        showStats: 'Show statistics'
    },
    ru: {
        openProfile: 'Открыть профиль',
        showStats: 'Показать статистику'
    }
};

export const App: PC = (props, { computed, lang }) => {
    const captions = computed(() => {
        // depends on lang signal
        return dictionary[lang.value] || dictionary.en;
    });
    return <div>
        <button>{captions.openProfile}</button>
        <button>{captions.showStats}</button>
    </div>;
};

Apache Lisansı 2.0 altında yayınlanmıştır