学习《SolidJS》(八)异步

171 阅读3分钟

lazy

我们一般引用组件的时候都是直接使用import,然后在JSX中直接使用。

SolidJS也提供了另外一种引用组件的方式,那就是lazy。

//一般引用
// import Greeting from "./greeting";

//lazy进行引用
const Greeting = lazy(() => import("./greeting"));

我们使用的打包工具,在编译import XXX的时候,一般都是直接放到同一个文件里面的。如果项目特别大,那首屏加载就会很慢。

所以很自然的就想到了拆分文件,使用import(XXX)打包的时候就有可能拆分文件,但是拆分文件不是一件简单的事情。如果将组件直接按文件进行拆分,那引入的同步的函数(组件本身就是函数),这个时候是没有办法进行处理的,因为Solid调用函数之后要马上拿到返回的Dom对象进行使用。

拆分文件之后,必定是需要经过网络下载对应的js文件,然后才可以调用函数。所以返回的值就是一个Promise,只有等待Promise.then之后可以使用,在这之前就需要一个占位的东西。

那就是lazy,它做的就是这个事情,它会在第一次渲染时在内部动态加载底层导入的代码,此时会暂停渲染分支直到代码可用。

对于使用React的人来说,要注意它不需要Suspense也能正常使用,下面这样就行(来自SolidJS官方)

import { render } from "solid-js/web";
import { lazy } from "solid-js";

const Greeting = lazy(() => import("./greeting"));

function App() {
  return (
    <>
      <h1>Welcome</h1>
      <Greeting name="Jake" />
    </>
  );
}
render(() => <App />, document.getElementById("app"));

createResource

在我的第二篇文章的时候有说到过一种加载资源的方式。代码如下:

import { createSignal, createEffect } from 'solid-js';

const [userId, setUserId] = createSignal(1);

const [userDetail, setUserDetail] = createSignal(null);

createEffect(() => {
    fetch(`http://xxx.com/userDetail/${userId()}`) 
    .then(response => response.json()) 
    .then(data => setUserDetail(data));
})

//后续导出或直接使用userDetail,又或者添加其它衍生的Signal

其实可以使用createResource,修改之后如下:

import { createSignal } from 'solid-js';

const [userId, setUserId] = createSignal(1);

const fetchUser = async (id) =>
  (await fetch(`http://xxx.com/userDetail/${id}`)).json();

const [user, { mutate, refetch }] = createResource(userId, fetchUser);

// 像Accessor使用就行了
let usrDetail = user()

//后续导出或直接使用user,又或者添加其它衍生的Signal

也就是提供了更强大的功能,我们可以直接使用,比如user.loading可以判断是否加载完成 mutate直接用来更新user,其实就是一个Setter。总结来说user和mutate对应于上面的userDetail和setUserDetail。 还提供了refetch来刷新,当前的user。

Suspense

既然lazy和createResource都可以单独使用,那为什么SolidJS还要提供Suspense呢?

其实在使用lazy的时候其实也看到了,UI是直接从无到有的,这个出现其实有点突兀。 而createResource虽然有loading可以进行单独的判断,但是如果不仅仅一个组件需要显示loading,那就涉及到需要一个统一的loading进行处理。 所以就用到了Suspense这个组件,对没有加载完成的状态进行统一处理,显示一个加载占位。

<> 
    <h1>Welcome</h1> 
    <Suspense fallback={<p>Loading...</p>}> 
        <Greeting name="Jake" /> 
    </Suspense> 
</>

用法就是上面这样很简单,fallback就是未加载完成的时候显示,children就是要监听有异步状态的组件

SuspenseList

由于SuspenseList基本用不上,我就不做具体的介绍了。它其实就是有多个Suspense的时候可以进行协调,控制先显示哪个Suspense的fallback或者不显示

Transition

真心的,这个我其实没有看懂。建议直接去看官方的代码样例 solidjs.com/tutorial/as… 在看SolidJS的源码的时候,会发现Transition到处都是,所以没那么容易看懂。 如果以后看懂了我再把这一部分给补上吧!!!