SolidJS Typescript 开发指南(3) 生命周期和流程控制

本文介绍了SolidJS的生命周期和流程控制。在生命周期方面,SolidJS有onMount、onCleanup、onError三个钩子函数,控制组件存活与销毁。流程控制上,SolidJS将其封装为组件,如Show、For、Switch等,可提升性能、加强语义化,还能处理渲染错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

生命周期

SolidJS对比其他的几个主流框架,在生命周期的设计思想中不同的是:
–> SolidJS只有三个生命周期函数,所有组件的存活状态和是否销毁都由SolidJS控制

1. onMount

生命周期的第一个钩子函数,发生在所有初始渲染完成之后且只运行一次
onMount函数支持异步语法,在这里可以调用获取数据的方法

import type { Component } from 'solid-js';
import { createSignal, onMount, For } from 'solid-js';
type photoData = {
    thumbnailUrl: string,
    title: string
}
const App: Component = () => {
    const [photos, setPhotos] = createSignal<Array<photoData>>([]);
    onMount(async () => {
        const res = await fetch(
            `https://jsonplaceholder.typicode.com/photos?_limit=20`
        );
        setPhotos(await res.json());
    });

    return <>
        <h1>Photo album</h1>

        <div class="photos">
            <For each={photos()} fallback={<p>Loading...</p>}>{(photo: photoData) =>
                <figure>
                    <img src={photo.thumbnailUrl} alt={photo.title} />
                    <figcaption>{photo.title}</figcaption>
                </figure>
            }</For>
        </div>
    </>;
};

export default App;

1. onCleanup

等同于其他框架中的beforeDestory钩子函数,但不同的是onCleanup适用于任何范围,不仅仅是在某个组件中调用,在某些外部调用也是可以的,最终由SolidJS统一管理

// App.tsx
import type { Component } from 'solid-js';
import { createSignal, onCleanup } from 'solid-js';
const App: Component = () => {
    const [count, setCount] = createSignal<number>(0);

    const timer = setInterval(() => setCount(count() + 1), 1000);
    onCleanup(() => clearInterval(timer));

    return <div>Count: {count()}</div>;
};
export default App;
// tools.ts
import { onCleanup } from 'solid-js';
function listenClick(el: HTMLButtonElement, fn: (ev: MouseEvent) => void) {
    const onClick = (ev: MouseEvent) => {
        fn(ev);
    }
    el.addEventListener('click', onClick);
    onCleanup(() => { el.removeEventListener('click', onClick) });
}
export default listenClick;

3. onError

SolidJS允许创建一个捕捉当前组件时发生的错误的钩子函数,这样即使在发生错误的情况下不会影响当前组件渲染和其他组件正常运行

import type { Component } from 'solid-js';
import { onError } from 'solid-js';
const App: Component = () => {
    const throwError = () => { throw new SyntaxError('custom error'); }
    const Error = () => <div>{throwError()}</div>
    onError(err => {
        console.log(err.message)
    })
    return <div>
        <Error></Error>
        Count: {0}
    </div>;
};

export default App;

流程控制

在SolidJS中流程控制被重新封装为组件来使用,因此除了在dom中嵌入带Array.prototype.map之类的方法之外,还可以通过SolidJS提供的流程控制组件提升性能且加强语义化,这样在数据更新时某些组件无需重新加载

1. Show

通过show组件,可以轻易实现if-else的流程控制
fallback 属性充当 else,在传递给 when 的条件不为 true 时显示

import type { Component } from 'solid-js';
import { createSignal, Show } from 'solid-js';
const App: Component = () => {
    const [loggedIn, setLoggedIn] = createSignal<boolean>(false);
    const toggle = () => setLoggedIn(!loggedIn())
    return (
        <Show
            when={loggedIn()}
            fallback={() => <button onClick={toggle}>Log in</button>}
        >
            <button onClick={toggle}>Log out</button>
        </Show>
    );
};

export default App;

2. For

通过for组件可以循环出可迭代对象,并且在数据变更对其进行优化以更新或移动行而不是重新创建它们,这样充分减少了重新创建dom的次数

import type { Component } from 'solid-js';
import { createSignal, For } from 'solid-js';
const App: Component = () => {
    const [arr, setArr] = createSignal<Array<number>>([]);
    return (
        <div>
            <button onclick={() => setArr(arr().concat(arr().length))}>Add</button>
            <For each={arr()}>
                {(item, i) => (<li>
                    {i()} : {item}
                </li>)}
            </For>
        </div>
    );
};

export default App;

在For组件内部的回调函数中,第一项参数也就是充当arr()[i]item并不是响应式的,但第二项参数index是响应式的,因此在使用第二项参数时要注意加括号来调用

3. Switch

Switch组件对应JS流程控制中的switch,在Show的基础上更加简洁地展示出分支状态

import type { Component } from 'solid-js';
import { createSignal, Switch, Match } from 'solid-js';
const App: Component = () => {
    const [x] = createSignal<number>(7);

    return (
        <Switch fallback={<p>{x()} is between 5 and 10</p>}>
            <Match when={x() > 10}>
                <p>{x()} is greater than 10</p>
            </Match>
            <Match when={5 > x()}>
                <p>{x()} is less than 5</p>
            </Match>
        </Switch>
    );
};

export default App;

4. Dynamic

Dynamic组件在传入某个函数式组件的基础上,动态地给该函数式组件传入prop

import type { Component, JSX } from 'solid-js';
import { Dynamic } from 'solid-js/web';
import { createSignal, For } from 'solid-js';

const RedThing = (props: { name: string }): JSX.Element => <strong style="color: red">Red Thing {props.name}</strong>;
const GreenThing = (props: { name: string }): JSX.Element => <strong style="color: green">Green Thing {props.name}</strong>;
const BlueThing = (props: { name: string }): JSX.Element => <strong style="color: blue">Blue Thing {props.name}</strong>;

const options: { [key: string]: (props: { name: string }) => JSX.Element } = {
    "red": RedThing,
    "green": GreenThing,
    "blue": BlueThing
}
const App: Component = () => {
    const [selected, setSelected] = createSignal<string>("red");

    return (
        <>
            <select value={selected()} onInput={e => setSelected(e.currentTarget.value)}>
                <For each={Object.keys(options)}>{
                    color => <option value={color}>{color}</option>
                }</For>
            </select>
            <Dynamic component={options[selected()]} name={selected()} />
        </>
    );
};

export default App;

5. Portal

Portal组件可以让包裹的dom脱离当前位置,一般用于处理类似模态框类浮动元素的渲染上下文,默认插入位置位于document.body中

import type { Component } from 'solid-js';
import { Portal } from 'solid-js/web';
const App: Component = () => {
    return (
        <div class="app-container">
            <p>Just some text inside a div that has a restricted size.</p>
            <Portal>
                <div class="popup">
                    <h1>Popup</h1>
                    <p>Some text you might need for something or other.</p>
                </div>
            </Portal>
            <p>Just some text inside a div that has a restricted size.</p>
        </div>
    );
};

export default App;

dom层级结构
如上图所示className为popup的元素被插入到最外层

6. Error Boundary

类似于生命周期的钩子函数onError,ErrorBoundary作为一个组件包裹的dom元素可以捕捉渲染时出现的错误
不同的是ErrorBoundary在组件中可以传入一个fallback回调,这个回调返回的内容可以在页面中显示,并且替换掉原先发生错误的内容

import type { Component, JSX } from 'solid-js';
import { ErrorBoundary } from 'solid-js';

const Broken: JSX.Element = () => {
    throw new Error("Oh No");
    return <div>some component</div>
}
const App: Component = () => {
    return (
        <>
            <div>Before</div>
            <ErrorBoundary fallback={err => <div>something is wrong</div>}>
                <Broken />
            </ErrorBoundary>
            <div>After</div>
        </>
    );
};

export default App;

捕捉错误
本文链接:https://blog.csdn.net/weixin_41907106/article/details/126335449

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值