solid: react导演剪辑终极扑街版

写在最后

为啥是写在最后呢?因为这段话是文章写完才打的 标题里的扑街也是写完才加的

原因是solid的路由库非常垃圾 既不支持<RouteView>嵌套路由 也不能接受剩余的路径参数

这下算白忙活了 我自己做小项目也不会用这种东西的 我真傻 真的

solid优点是有的 而且非常明显 不过就是典型的一问都在夸 二问没人用

一句话solid

js 复制代码
const App: Component = () => {
  const [count, setCount] = createSignal(0);
  const increment = () => setCount(count() + 1);
  return (
    <button onClick={increment}>{count()}</button>
    );
};

等价于

js 复制代码
class App extends Component {
  constructor() {
    super();
    this.state = {
      count: 0
    };
  }
  increment() {
    this.setState({ count: this.state.count + 1 });
  };
  render() {
    return (
      <button onClick={()=>this.increment()}>{this.state.count}</button>
    );
  }
}

感动吗?solid甚至不需要eslint

solid在保持了简洁的同时 规避了函数组件最大的缺点

solid的state是一个getter函数->组件函数只需要被调用一次->不必担心闭包问题->不需要反复理解此state为什么不是彼state

重要api

createEffect

基本用法

和useEffect很类似 但会自动收集依赖

在组件创建和渲染完毕后,调用一次effect函数,无论组件函数中是否变更过signal

之后每当依赖变更 调用effect函数

scss 复制代码
  createEffect(() => {
    console.log(count());
  });

如果想从上一次effect中得到一些信息

effect函数可以拥有一个参数

第一次调用时,effect函数会接受createEffect的参数2作为参数(也可以不写 那样的话就是undefined)

后续的每次调用 都会以effect函数的返回值作为参数

js 复制代码
  createEffect((flag: boolean) => {
    if (flag) {
      return
    }
    console.log(count())
    return count() > 5;
  }, false);

也可以用于保存prevValue

js 复制代码
  createEffect((prevValue?: number) => {
    console.log('prev:' + prevValue)
    return count()
  });

以上情况对于数组均适用

说明

  • effect函数的参数类型必须显式写出来 不能通过其返回值和初始值的类型得出 这与typescript的机制有关系 参考这篇文章
  • 依赖收集仅限同步部分 如果有回调函数、promise、setTimeout中执行的代码 这样做
js 复制代码
  createEffect(() => {
    const value = count();
    setTimeout(() => console.log(value), 0);
  });
  • 不要把effect函数设置为异步函数
  • 不用担心if for等语句影响依赖收集
  • 不建议用这个函数获取数据 参考后文createResource

on

手动控制createEffect的依赖项 类似于vue里的watch
createEffect(on(deps,fn,{ defer?: boolean}))

defer

defer为true则不执行第一次

deps

scss 复制代码
const [a] = createSigal(0)
const b = createMemo(()=>a()*2)
const c = ()=>a()*2
const d = ()=> ({ a:a:(), d:1 })

const deps = a
// const deps = [b,c]
// const deps = ()=>d().d

createEffect(on(deps,fn))

注意 d().d虽然不变 但是依旧会触发fn 需要这样写

scss 复制代码
const e = createMemo(()=>d().d)

fn

函数签名

php 复制代码
fn: (input: T, prevInput: T, prevValue?: U) => U

input 这次的deps

prevInput 上次的deps

prevValue createEffect的初始值 或者上次调用fn的返回值

onMount

scss 复制代码
onMount(fn)

挂载后调用一次fn 只执行一次的effect

不建议用这个函数获取数据 参考后文createResource

onCleanup

在effect中调用onCleanup 清理函数会在下次effect之前被调用

js 复制代码
createEffect(()=>{
    onCleanup(xxx)
})

直接写在组件函数中则是卸载时调用

js 复制代码
onCleanup(xxx)

createMemo

基本用法

类似于useMemo 依赖收集、同步异步、清理函数等和createEffect相同

js 复制代码
const doubleValue = createMemo(() => count() * 2);

<button>{doubleValue()}<button>

与createEffect类似 memo函数也可以接受一个参数

第一次调用时 这个参数是createMemo的参数2 后续则是上次memo函数调用的返回值

如果不需要memo

js 复制代码
// 正确
const doubleValue = () => count() * 2;

<button>{doubleValue()}<button>

// 错误
const doubleValue = count() * 2;

<button>{doubleValue}<button>

说明

  • createMemo和useMemo作用相同 可以缓存复杂计算的结果
  • createMemo可以获取上次计算的结果
  • createMemo可以接受一个自定义的equals函数
js 复制代码
createMemo(xxx,xxx,{ equals: Object.is })

createResource

基本用法

类似于useActionState 管理异步状态

这个函数比较复杂 建议参考文档 这里只做简单介绍

js 复制代码
const [data, { mutate, refetch }] = createResource(fetchData)

参数和返回值

fetchData
  • 数据获取函数 不会自动收集其中的依赖
  • 可以是异步的
  • 组件创建时会被立刻调用
  • 不会出现先发后至的问题 之前一次发起的请求比后一次晚结束 data也会取后一次请求的值 因此不需要管理队列
data

data() 从fetchData里获取的数据
data.loading
data.error
data.latestfetchData返回的最新值
data.state 值为"unresolved" | "pending" | "ready" | "refreshing" | "errored" 比loading和error更详细 以上都是singal

mutate

强制将data置为某个值

refetch

重新获取data

fetchData相关

createResource也可以写做createResource(source,fetchData)

source可以是一个普通值 也可以是一个getter函数

如果source(或者其返回值)是false、null、undefined则fetchDate总是不会被调用

如果source是getter函数 且它的返回值不是上述空值且发生了变化 则fetchData被自动调用

fetchData接受这样的参数

js 复制代码
fetchData(source,info:{ value, refetching })

如果没有source 则fetchData的参数1是true

createContext

基本用法

和React.createContext差不多

ini 复制代码
const ValueContext = createContext<number>() // 可以传一个defaultValue

// 直接传递一个值
const num = 1
<ValueContext.Provider value={num}>xxx</ValueContext.Provider>

// 如果想让子组件取得信号 应该直接把getter传下去
const [count] = createSignal(0)
<ValueContext.Provider value={count}>xxx</ValueContext.Provider>

const num = 1
<ValueContext.Provider value={num}>xxx</ValueContext.Provider>

// 获取传下来的值
useContext(ValueContext)

说明

文档建议

ref

基本用法

获取dom的引用

js 复制代码
let dom
<div ref={dom} />

let comp
<Comp ref={comp}/>
const Comp = props=>{
    return <div ref={props.ref}/>
}

获取组件的引用

不存在"组件的引用" 需要从子组件中获取什么 直接这样写就可以了

javascript 复制代码
let someValue

<Comp setter={val=>someValue=val} />

const Comp = props=>{
    props.setter(1)
    return <div/>
}

样式

class

solid中没有className 而是使用class

style

style可以是字符串或对象 但不支持驼峰写法

js 复制代码
// 错误
style={{ backgroundColor: 'red' }}
// 正确
style={{ 'background-color': 'red' }}

因为底层是style.setProperty

ParentComponent

等效于FC<PropsWithChildren> 在props添加children属性

不重要的api

children

js 复制代码
import { children } from 'solid-js'

const resolved = children(()=>props.children)

作用是惰性加载children(比如条件渲染 不一定用得到) 还会对做一些jsx专属的操作

不一定是children属性 只要是一个返回jsx的getter函数都可以

createStore

对象或数组的signal 感觉不如immer

createUniqueId

约等于useId

ini 复制代码
const id = createUniqueId()

id是string 不是getter 直接用

on:*

这种事件会被直接放在dom上而不被委托

js 复制代码
<div on:DOMContentLoaded={(e) => console.log("Welcome!")} />

untrack

在这个函数里面所读取的signal不会被收集为依赖

<Suspense>

和react类似 但仅由createResource触发

js 复制代码
const MyComponentWithSuspense = () => {
  const [data] = createResource(async () => {xxx})
  return (
    <Suspense fallback={xxx}>
        {data()}
    </Suspense>
  )
}

其他

<ErrorBoundary> lazy懒加载 等和react类似
For.map Showa?b:c等据说有优化 但不是特别必要

还有一些底层api 与ssr和开发第三方库有关 可以自行翻阅文档

第三方库

内容比较多 可以去我的模板里看

相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊4 小时前
jwt介绍
前端
爱敲代码的小鱼4 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax