Rumah > hujung hadapan web > tutorial css > Tidak Semuanya Memerlukan Komponen

Tidak Semuanya Memerlukan Komponen

DDD
Lepaskan: 2024-11-26 03:32:12
asal
268 orang telah melayarinya

Not Everything Needs a Component

Pada awal 2000-an, istilah baharu, Divitis, telah dicipta untuk merujuk kepada Amalan mengarang kod halaman web dengan banyak elemen div dalam tempat unsur HTML semantik yang bermakna. Ini adalah sebahagian daripada usaha untuk meningkatkan kesedaran tentang semantik dalam HTML dalam kerangka teknik Peningkatan Progresif.

Fast forward 20 tahun - Saya menyaksikan sindrom baharu yang menjejaskan pembangun web, yang saya panggil componentitis. Berikut ialah definisi rekaan saya:

Komponentitis: amalan mencipta komponen untuk setiap aspek UI sebagai ganti penyelesaian yang lebih ringkas dan boleh digunakan semula.

Komponen

Jadi, pertama sekali, apakah itu komponen? Saya rasa React mempopularkan istilah itu untuk merujuk kepada blok binaannya:

React membolehkan anda menggabungkan markup, CSS dan JavaScript anda ke dalam "komponen" tersuai, elemen UI boleh guna semula untuk apl anda.
Dokumentasi React - Komponen Pertama Anda

Walaupun konsep elemen UI boleh guna semula bukanlah sesuatu yang baharu pada masa itu (dalam CSS, kami sudah mempunyai teknik seperti OOCSS, SMACSS dan BEM), perbezaan utamanya ialah pendekatan asalnya terhadap lokasi penanda, gaya dan interaksi. Dengan komponen React (dan semua pustaka UI berikutnya), adalah mungkin untuk mencari bersama semua dalam satu fail dalam sempadan komponen.

Jadi, menggunakan pustaka CSS terbaru Facebook Stylex, anda boleh menulis:

import * as stylex from "@stylexjs/stylex";
import { useState } from "react";

// styles
const styles = stylex.create({
    base: {
        fontSize: 16,
        lineHeight: 1.5,
        color: "#000",
    },
});

export function Toggle() {
    // interactions
    const [toggle, setToggle] = useState(false);
    const onClick = () => setToggle((t) => !t);

    // markup
    return (
        <button {...stylex.props(styles.base)} type="button" onClick={onClick}>
            {toggle}
        </button>
    );
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Anda boleh menjadi peminat atau tidak menulis CSS dalam tatatanda objek (saya tidak), tetapi tahap lokasi bersama ini selalunya merupakan cara yang baik untuk menjadikan projek berasaskan komponen lebih boleh diselenggara: semuanya boleh dicapai dan terikat secara jelas.

Di perpustakaan seperti Svelte, lokasi bersama lebih jelas (dan kodnya lebih ringkas):

<script>
    let toggle = $state(false)
    const onclick = () => toggle = !toggle
</script>

<button type='button' {onclick}>
    {toggle}
</button>

<style>
button {
    font-size: 16px;
    line-height: 1.5;
    color: #000;
}
</style> 
Salin selepas log masuk
Salin selepas log masuk

Dari masa ke masa, corak ini telah mendapat begitu banyak daya tarikan sehinggakan semuanya terkandung dalam komponen. Anda mungkin pernah mengalami komponen halaman seperti ini:

export function Page() {
    return (
        <Layout>
            <Header nav={<Nav />} />
            <Body>
                <Stack spacing={2}>
                    <Item>Item 1</Item>
                    <Item>Item 2</Item>
                    <Item>Item 3</Item>
                </Stack>
            </Body>
            <Footer />
        </Layout>
    );
}
Salin selepas log masuk
Salin selepas log masuk

Lokasi bersama satu

Kod di atas kelihatan bersih dan konsisten: kami menggunakan antara muka komponen untuk menerangkan halaman.

Tetapi kemudian, mari kita lihat kemungkinan pelaksanaan Stack. Komponen ini biasanya merupakan pembalut untuk memastikan semua elemen anak langsung disusun secara menegak dan jarak yang sama:

import * as stylex from "@stylexjs/stylex";
import type { PropsWithChildren } from "react";

const styles = stylex.create({
    root: {
        display: "flex",
        flexDirection: "column",
    },
    spacing: (value) => ({
        rowGap: value * 16,
    }),
});

export function Stack({
    spacing = 0,
    children,
}: PropsWithChildren<{ spacing?: number }>) {
    return (
        <div {...stylex.props(styles.root, styles.spacing(spacing))}>
            {children}
        </div>
    );
}
Salin selepas log masuk
Salin selepas log masuk

Kami hanya menentukan gaya dan elemen akar komponen.

Dalam kes ini, kami juga boleh mengatakan bahawa satu-satunya perkara yang kami cari bersama ialah blok gaya memandangkan HTML hanya digunakan untuk memegang rujukan kelas CSS dan tiada interaktiviti atau perniagaan logik.

Kos fleksibiliti (boleh dielakkan).

Sekarang, bagaimana jika kita mahu dapat menjadikan elemen akar sebagai bahagian dan mungkin menambah beberapa atribut? Kita perlu memasuki alam komponen polimorfik. Dalam React dan dengan TypeScript ini mungkin akan menjadi seperti berikut:

import * as stylex from "@stylexjs/stylex";
import { useState } from "react";

// styles
const styles = stylex.create({
    base: {
        fontSize: 16,
        lineHeight: 1.5,
        color: "#000",
    },
});

export function Toggle() {
    // interactions
    const [toggle, setToggle] = useState(false);
    const onClick = () => setToggle((t) => !t);

    // markup
    return (
        <button {...stylex.props(styles.base)} type="button" onClick={onClick}>
            {toggle}
        </button>
    );
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Pada pendapat saya, ini tidak begitu boleh dibaca pada pandangan pertama. Dan ingat: kami hanya memaparkan elemen dengan 3 pengisytiharan CSS.

Kembali kepada asas

Suatu ketika dahulu, saya sedang mengusahakan projek haiwan peliharaan di Angular. Kerana digunakan untuk berfikir dalam komponen, saya menghubungi mereka untuk membuat Tindanan. Ternyata dalam komponen polimorfik sudut adalah lebih kompleks untuk dibuat.

Saya mula mempersoalkan reka bentuk pelaksanaan saya dan kemudian saya mendapat pencerahan: mengapa menghabiskan masa dan baris kod pada pelaksanaan yang kompleks sedangkan penyelesaiannya telah ada di hadapan saya selama ini?

<script>
    let toggle = $state(false)
    const onclick = () => toggle = !toggle
</script>

<button type='button' {onclick}>
    {toggle}
</button>

<style>
button {
    font-size: 16px;
    line-height: 1.5;
    color: #000;
}
</style> 
Salin selepas log masuk
Salin selepas log masuk

Sungguh, itu adalah asli pelaksanaan Stack . Sebaik sahaja anda memuatkan CSS dalam reka letak, ia boleh digunakan serta-merta dalam kod anda:

export function Page() {
    return (
        <Layout>
            <Header nav={<Nav />} />
            <Body>
                <Stack spacing={2}>
                    <Item>Item 1</Item>
                    <Item>Item 2</Item>
                    <Item>Item 3</Item>
                </Stack>
            </Body>
            <Footer />
        </Layout>
    );
}
Salin selepas log masuk
Salin selepas log masuk

Tambahkan jenis-keselamatan dalam rangka kerja JavaScript

Penyelesaian CSS sahaja tidak menyediakan penaipan mahupun pelengkapan automatik IDE.

Selain itu, jika kami tidak menggunakan variasi jarak, mungkin terasa terlalu bertele-tele untuk menulis kedua-dua kelas dan atribut gaya dan bukannya prop jarak. Dengan mengandaikan anda menggunakan React, anda boleh memanfaatkan JSX dan mencipta fungsi utiliti:

import * as stylex from "@stylexjs/stylex";
import type { PropsWithChildren } from "react";

const styles = stylex.create({
    root: {
        display: "flex",
        flexDirection: "column",
    },
    spacing: (value) => ({
        rowGap: value * 16,
    }),
});

export function Stack({
    spacing = 0,
    children,
}: PropsWithChildren<{ spacing?: number }>) {
    return (
        <div {...stylex.props(styles.root, styles.spacing(spacing))}>
            {children}
        </div>
    );
}
Salin selepas log masuk
Salin selepas log masuk

Perhatikan bahawa React TypeScript tidak membenarkan sifat CSS yang tidak diketahui. Saya menggunakan penegasan jenis untuk ringkas, tetapi anda harus memilih penyelesaian yang lebih mantap.

Jika anda menggunakan varian, anda boleh mengubah suai fungsi utiliti untuk memberikan pengalaman pembangun yang serupa dengan corak PandaCSS:

import * as stylex from "@stylexjs/stylex";

type PolymorphicComponentProps<T extends React.ElementType> = {
    as?: T;
    children?: React.ReactNode;
    spacing?: number;
} & React.ComponentPropsWithoutRef<T>;

const styles = stylex.create({
    root: {
        display: "flex",
        flexDirection: "column",
    },
    spacing: (value) => ({
        rowGap: value * 16,
    }),
});

export function Stack<T extends React.ElementType = "div">({
    as,
    spacing = 1,
    children,
    ...props
}: PolymorphicComponentProps<T>) {
    const Component = as || "div";
    return (
        <Component
            {...props}
            {...stylex.props(styles.root, styles.spacing(spacing))}
        >
            {children}
        </Component>
    );
}
Salin selepas log masuk

Elakkan pertindihan kod dan nilai berkod keras

Sesetengah daripada anda mungkin menyedari bahawa, dalam contoh terakhir, saya mengekodkan nilai jangkaan jarak dalam kedua-dua CSS dan fail utiliti. Jika nilai dialih keluar atau ditambah, ini mungkin menjadi isu kerana kita mesti memastikan kedua-dua fail itu segerak.

Jika anda membina pustaka, ujian regresi visual automatik mungkin akan menangkap isu seperti ini. Bagaimanapun, jika ia masih mengganggu anda, penyelesaian mungkin adalah untuk mencapai Modul CSS dan sama ada menggunakan typed-css-modules atau membuang ralat masa jalan untuk nilai yang tidak disokong:

<div>





<pre class="brush:php;toolbar:false">.stack {
  --s: 0;
    display: flex;
    flex-direction: column;
    row-gap: calc(var(--s) * 16px);
}
Salin selepas log masuk
export function Page() {
    return (
        <Layout>
            <Header nav={<Nav />} />
            <Body>
                <div className="stack">



<p>Let's see the main advantages of this approach:</p>

<ul>
<li>reusability</li>
<li>reduced complexity</li>
<li>smaller JavaScript bundle and less overhead</li>
<li><strong>interoperability</strong></li>
</ul>

<p>The last point is easy to overlook: Not every project uses React, and if you’re including the stack layout pattern in a Design System or a redistributable UI library, developers could use it in projects using different UI frameworks or a server-side language like PHP or Ruby.</p>

<h2>
  
  
  Nice features and improvements
</h2>

<p>From this base, you can iterate to add more features and improve the developer experience. While some of the following examples target React specifically, they can be easily adapted to other frameworks.</p>

<h3>
  
  
  Control spacing
</h3>

<p>If you're developing a component library you definitely want to define a set of pre-defined spacing variants to make space more consistent. This approach also eliminates the need to explicitly write the style attribute:<br>
</p>

<pre class="brush:php;toolbar:false">.stack {
  --s: 0;
  display: flex;
  flex-direction: column;
  row-gap: calc(var(--s) * 16px);

  &.s\:1 { --s: 1 }
  &.s\:2 { --s: 2 }
  &.s\:4 { --s: 4 }
  &.s\:6 { --s: 6 }
}

/** Usage:
<div>



<p>For a bolder approach to spacing, see Complementary Space by Donnie D'Amato.</p>

<h3>
  
  
  Add better scoping
</h3>

<p>Scoping, in this case, refers to techniques to prevent conflicts with other styles using the same selector. I’d argue that scoping issues affects a pretty small number of projects, but if you are really concerned about it, you could:</p>

<ol>
<li>Use something as simple as CSS Modules, which is well supported in all major bundlers and frontend frameworks.</li>
<li>Use cascade layers resets to prevent external stylesheets from modifying your styles (this is an interesting technique).</li>
<li>Define a specific namespace like .my-app-... for your classes.</li>
</ol>

<p>Here is the result with CSS Modules:<br>
</p>

<pre class="brush:php;toolbar:false">.stack {
  --s: 0;
  display: flex;
  flex-direction: column;
  row-gap: calc(var(--s) * 16px);

  &.s1 { --s: 1 }
  &.s2 { --s: 2 }
  &.s4 { --s: 4 }
  &.s6 { --s: 6 }
}

/** Usage
import * from './styles/stack.module.css'

<div className={`${styles.stack} ${styles.s2}`}>
    // ...
</div>  
*/
Salin selepas log masuk

Alternatif

Jika anda masih fikir komponen polimorfik adalah lebih baik, benar-benar tidak dapat menangani HTML biasa, atau tidak mahu menulis CSS dalam fail berasingan (walaupun saya tidak pasti mengapa), cadangan saya seterusnya ialah lihat PandaCSS dan buat corak tersuai atau teroka pilihan lain seperti ekstrak vanila. Pada pendapat saya, alatan ini ialah bahasa CSS yang terlalu direkayasa tetapi masih lebih baik daripada komponen polimorfik.

Alternatif lain yang patut dipertimbangkan ialah Tailwind CSS, yang mempunyai kelebihan untuk saling beroperasi antara bahasa dan rangka kerja.

Menggunakan skala jarak lalai yang ditakrifkan oleh Tailwind, kita boleh mencipta pemalam tindanan seperti ini:

import * as stylex from "@stylexjs/stylex";
import { useState } from "react";

// styles
const styles = stylex.create({
    base: {
        fontSize: 16,
        lineHeight: 1.5,
        color: "#000",
    },
});

export function Toggle() {
    // interactions
    const [toggle, setToggle] = useState(false);
    const onClick = () => setToggle((t) => !t);

    // markup
    return (
        <button {...stylex.props(styles.base)} type="button" onClick={onClick}>
            {toggle}
        </button>
    );
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Sebagai nota sampingan: adalah menarik bahawa Tailwind menggunakan model mental komponen dalam matchComponents untuk menerangkan set peraturan CSS yang kompleks, walaupun ia tidak mencipta sebarang komponen sebenar. Mungkin satu lagi contoh betapa meluasnya konsep itu?

Bawa pulang

Kes Componentitis, di luar aspek teknikalnya, menunjukkan kepentingan berhenti seketika untuk memeriksa dan mempersoalkan model dan tabiat mental kita. Seperti banyak corak dalam pembangunan perisian, komponen muncul sebagai penyelesaian kepada masalah sebenar, tetapi apabila kami mula lalai kepada corak ini, ia menjadi sumber kerumitan yang senyap. Komponentitis menyerupai kekurangan nutrisi yang disebabkan oleh diet terhad: masalahnya bukan dengan mana-mana makanan tunggal tetapi dengan kehilangan semua yang lain.

Atas ialah kandungan terperinci Tidak Semuanya Memerlukan Komponen. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan