guangliang2019 / Prototype-UI

Headless UI with Web Component
https://prototype-ui.dev
MIT License
5 stars 0 forks source link

feat: 上下文组件升级 & trigger 能力抽象化 #34

Closed guangliang2019 closed 1 month ago

guangliang2019 commented 1 month ago

这次 PR 主要解决两个问题:

  1. 每个 consumer 各自独立维护一份 context 并不合理,现在改成与 provider 共享同一个 context 对象的引用,也就是说

    • 现在 consumer 可以通过访问 this._contextValue 对上下文进行不会通知更新的修改,方便进行初始化
    • 只有通过 provider 的 setContext 方法,且 notify 设置为 true 的更新操作,才会触发 consumer 的 onContextChange
    • 顺便给 onContextChange 添加了一个可选参数,内容是本次更新的键名,consumer 可以根据这个参数进行性能优化,减少不必要的逻辑处理
  2. 现在基本每个组件都会有 trigger,例如 tooltip 是 hover tooltipTrigger 一段时间之后弹出提示,dialog 是点击 dialogTrigger 触发弹窗,button 本身就是一个 trigger,点击时触发触发点击事件等等

    • 假设现在有一个既有 tooltip 点击后又触发 dialog 的 button,那么就会有三个可以获得焦点的组件嵌套在一起,这对于键盘导航来说是极度不合理的
    • 所以写了一个叫做 trigger 的基类,无论多少个 trigger 嵌套在一起,最终实际表现为一个复合了多种能力的 trigger
    • trigger 递归寻找第一个不是 trigger 的子元素作为实际事件与焦点的管理者,如果不存在合适的对象,他会以最内层的没有 children 的 trigger 作为目标对象。
vercel[bot] commented 1 month ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
prototype-ui ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 28, 2024 2:50pm
guangliang2019 commented 1 month ago

trigger 的设计嗯这下父级挺好确定了 不过不使用 this._contextValue,调用 provider 的 setContext (notify = false) 好像也是相同效果呀

区别在于 consumer 默认并不持有 setContext 方法,setContext 必须由 provider 进行封装后分发,或者干脆不分发,consumer 通知其他 consumer 的途径比较受限。

这样数据流的整体设计还是倾向于自顶向下的,只不过给 consumer 开放了惰性的更新 context 能力(因为不会立刻通知所以很适合更新一些不会立刻生效的东西,例如事件函数指针)