dioxus-compose 가이드

시작하기

빈 크레이트에서 배치된 페이지까지

이 페이지에서는 크레이트를 추가하고, HTML 과 CSS 로 페이지를 쓰고, 배치하고, 클릭해 봅니다. HTML 경로가 아직 화면에 그리지 않으므로 지금 결과는 창이 아니라 상자 목록입니다 (#43).

크레이트 추가

crates.io 에서 크레이트를 추가합니다. 0.0.1 에는 두 경로가 다 있고 compose-rust 0.0.1 에 의존합니다. 0.0.x 는 초기 릴리스이고 API 는 바뀝니다.

shell
cargo add dioxus-compose@0.0.1
cargo add dioxus-hooks@0.7 dioxus-signals@0.7

dioxus-hooks 와 dioxus-signals 는 예제들이 쓰는 대로 use_signal 과 시그널 트레이트를 줍니다. 첫 빌드는 compose-rust 의 빌드 스크립트를 거쳐 렌더러도 내려받습니다. 위젯 경로는 그것으로 그리고, HTML 화면은 아직 쓰지 않습니다.

페이지 쓰기

페이지는 컴포넌트 하나와 스타일시트 하나입니다. 예제들은 둘을 한 파일에 두고 app 과 STYLE 로 내보냅니다. 그래서 창은 그 페이지를 보여 줄 수 있고, 테스트는 창 없이 배치할 수 있습니다.

src/main.rs: 페이지는 samples/hello 를 줄인 것
use dioxus_compose::html::prelude::*;
use dioxus_hooks::use_signal;

pub const STYLE: &str = r#"
body { margin: 0; font-family: system-ui, sans-serif; font-size: 16px; line-height: 1.5; }
.page { padding: 40px 48px; }
h1 { margin: 0 0 16px; font-size: 32px; line-height: 40px; }
p { margin: 12px 0; }
"#;

pub fn app() -> Element {
    let mut hellos = use_signal(|| 0u32);
    let status = match hellos() {
        0 => "Nobody has said hello yet".to_string(),
        1 => "You said hello once".to_string(),
        n => format!("You said hello {n} times"),
    };

    rsx! {
        main { class: "page",
            h1 { id: "title", "Hello, Dioxus" }
            p { id: "action",
                a {
                    id: "greet",
                    href: "#",
                    onclick: move |event| {
                        event.prevent_default();
                        hellos += 1;
                    },
                    "Say hello"
                }
            }
            p { id: "status", "{status}" }
        }
    }
}

요소는 Dioxus 자체의 HTML 요소이고, 웹이나 데스크톱 Dioxus 앱이 쓰는 것과 같습니다. 속성은 class, 이벤트는 onclick 과 oninput 이며, event.prevent_default() 도 웹에서처럼 동작합니다.

배치하기

HtmlDom 이 앱을 실행하고, CSS 픽셀 단위의 뷰포트 크기와 CSS 픽셀당 장치 픽셀 배율로 배치합니다. 돌려받는 그리기 목록에는 상자마다 항목이 하나씩 그리는 순서대로 있습니다.

src/main.rs, 이어서
fn main() {
    let mut dom = HtmlDom::with_config(app, HtmlConfig {
        stylesheets: vec![STYLE.to_string()],
        ..HtmlConfig::default()
    });

    let list = dom.layout(800.0, 600.0, 1.0);
    for entry in &list.entries {
        println!("{:<6} {:?}", entry.tag, entry.rect);
    }
}

cargo run 은 상자를 출력하고 끝납니다. 창은 열리지 않습니다. 상자를 그리는 일이 아직 없는 다리의 몫이기 때문입니다. HtmlConfig 는 텍스트 측정기, 색 구성표, 기준 URL, 이미지 리졸버도 받으며, 뒤 페이지에서 다룹니다.

클릭하기

한 점을 누르면 렌더러가 보낼 포인터 이벤트처럼 그 아래 요소의 핸들러로 갑니다. 아래는 hello 예제의 테스트를 줄인 것입니다. 수치는 스타일시트와, 모든 글자를 글꼴 크기의 절반 폭으로 재는 테스트용 측정기에서 나옵니다.

samples/hello/tests/hello.rs, 줄임
let mut dom = HtmlDom::with_config(hello::app, config(hello::STYLE, Measurer::new()));
dom.layout(800.0, 600.0, 1.0);

let run = &entry(&dom, "action").texts[0];
assert_eq!(run.text, "Say hello");
assert_rect(run.rect, 48.0, 132.0, 72.0, 24.0, "the link's text");

let (x, y) = centre(run.rect);
assert_eq!(dom.click(x, y), Some(node(&dom, "greet")));
dom.render();
dom.layout(800.0, 600.0, 1.0);
assert_eq!(text_of(entry(&dom, "status")), "You said hello once");

핸들러는 click 안에서 실행됩니다. render 가 핸들러가 바꾼 것을 문서에 적용하고, 다음 layout 에 그것이 나타납니다.

예제 돌리기

samples/ 의 예제 열한 개가 이렇게 쓰여 있고, 하나가 크레이트 하나입니다. 이 가이드의 나머지 페이지는 이 예제들을 인용합니다. 각 예제의 테스트는 모든 배치를 손으로 계산한 수치와 비교하고, 렌더러가 부를 것과 같은 호출로 클릭하고 입력하고 제출합니다. 저장소 체크아웃에서 다음과 같이 돌립니다.

shell
cargo test -p sample-html-hello
cargo test -p sample-html-hello -p sample-html-chat -p sample-html-todo
예제보여 주는 것페이지
hello제목, 인라인 굵게와 기울임, 클릭 수를 세는 링크텍스트
article제목, 줄바꿈되는 문단, 목록, 인용, 코드 블록텍스트
dashboard상단 바, 사이드바, 줄바꿈되는 지표 카드. 모두 flexbox레이아웃
gallery그라디언트 헤더 아래 CSS grid 사진 목록이미지
settings폼: 텍스트 입력란, 텍스트 영역, select, 체크박스, 라디오 그룹폼
table옆으로 스크롤되는 HTML 표, 금액 머리글로 정렬레이아웃
chat아래에 고정된 입력 줄 위로 스크롤되는 대화스크롤
todo키가 있는 행의 추가, 체크, 삭제, 순서 바꾸기폼
overlay드롭다운 메뉴, 고정 배경 위 대화 상자, 잘린 미리보기오버레이
themeCSS 사용자 정의 속성으로 쓴 색, 어두운 세트, 덮어쓰기 버튼테마
workbench작은 코드 편집기: 액티비티 바, 파일 트리, 탭, 상태 표시줄레이아웃

지금 그려지는 위젯 경로

Compose 위젯 이름으로 쓴 앱은 같은 의존성으로 지금 창에서 돕니다. dioxus_compose::launch(app) 가 창을 열고, cargo run 이 빌드하고 실행합니다. 렌더러는 compose-rust 에서 오며, 그 빌드 스크립트가 대상 플랫폼의 렌더러를 내려받습니다. 이런 앱을 쓰는 방법은 rsx! 의 위젯에 있고, 예제는 compose-rust/samples/ 에 있습니다.

이 저장소에서 작업하기

이 저장소는 모두 Rust 이므로 테스트는 명령 하나입니다.

shell
cargo test --workspace

./scripts/check.sh 가 전체 검사입니다. 포맷, 경고를 오류로 다루는 Clippy, 테스트, 벤치마크입니다. 렌더러와 그 빌드, 디자인 시스템은 compose-rust 에 있고, 그쪽 작업 방법은 그 README 에 있습니다.