生命周期
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;
如上图所示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