Published on

2024-03-1-前端快报

Authors
  • avatar
    Name
    noodles
    每个人的花期不同,不必在乎别人比你提前拥有

unplugin-parcel-macros

parcel的macro宏定义功能可以实现在其他打包工具中的支持了,macros可以定义编译时逻辑,在编译时执行对应的逻辑生成函数或者自定义流程。参考它的一个例子:

        // 代码内容
        import regexgen from 'regexgen' with {type: 'macro'};

        const regex = regexgen(['foobar', 'foobaz', 'foozap', 'fooza']);
        console.log(regex);
        
        // 编译结果
        console.log(/foo(?:zap?|ba[rz])/); 

上面最后的编译结果只在代码中生成一个regexgen生成的正则表达式,剔除了regexgen的内容。可以使用这种宏能力在编译时做一些动态逻辑。

wasmer

wasmer是一个WebAssembly的执行容易,可以实现在不同语言环境中执行WebAssembly。

fx

一个在命令行浏览和处理json数据的库

React Native Skia

React Native 2D动画库. 提供了图表等能力,开箱即用了。

Eloquent JavaScript Goes Fourth

JavaScript编程精讲第四版

wxt

下一代浏览器扩展插件的编写框架,特性如下

  • 支持Vue/React/Svelte等语言
  • 支持HMR
  • 支持远程代码的引入

优化工具

knip

可以帮助查找代码中无用的文件或者依赖的库,可以定期对代码仓库进行扫描,治理代码

million

一个可以优化React组件性能的库,官网上看可以达到70%的优化,看Star已经15k了,值得关注

Dependency cruiser

可以校验和视图化文件依赖的工具

  • 可以自定义校验规则,对代码的引入进行治理
  • 视图化代码引入可以生成引入之间的关系,在项目设计上提供一些思路

源码解读

react-resizable-panels

react-resizable-panels是一个实现可伸缩容器的库,简单用法如下

        <PanelGroup direction="horizontal">
                <Panel defaultSize={30} minSize={20} style={{ background: 'blue', height: '200px' }} >
                        left
                </Panel>
                <PanelResizeHandle />
                <Panel minSize={30} style={{ background: 'red', height: '200px' }} >
                        middle
                </Panel>
                <PanelResizeHandle />
                <Panel defaultSize={30} minSize={20}  style={{ background: 'green', height: '200px' }}>
                        right
                </Panel>
        </PanelGroup>
  • PanelGroup 通过PanelGroup包裹需要伸缩的容器
  • Panel 需要伸缩的容器
  • PanelResizeHandle 容器件控制伸缩的组件

现在从这三个组件开始梳理react-resizable-panels如何实现容器的伸缩功能的

Panel

// panelDataRef 存在了当前Panel的id和在暴露出来的一些回调函数(onResize/onCollapse等)
const style = getPanelStyle(panelDataRef.current, defaultSize);
return createElement(Type, {
        ...rest,
        children,
        className: classNameFromProps,
        id: idFromProps,
        style: {
        // 属性合并逻辑  styleFromProps在这里会应用上 比如设置最大宽度最小宽度等
        ...style,
        ...styleFromProps,
        },
        // CSS selectors
        "data-panel": "",
        "data-panel-collapsible": collapsible || undefined,
        "data-panel-group-id": groupId,
        "data-panel-id": panelId,
        "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1),
});

panel整体上是通过context上的getPanelStyle方法来确定样式,并且有相应的通知变更能力

PanelGroup

        const style: CSSProperties = {
                display: "flex",
                // PanelGroup是一个flex容器,在子容器变化的时候,通过Context上的getPanelStyle设置子
                // 容器的flex-basic 
                flexDirection: direction === "horizontal" ? "row" : "column",
                height: "100%",
                overflow: "hidden",
                width: "100%",
        };
        return createElement(
                PanelGroupContext.Provider,
                //  将全局的方法通过Context的方式共享,包括Panel,ResizeHandle的注册逻辑和变更通知接口
                { value: context },
                createElement(Type, {
                ...rest,
                children,
                className: classNameFromProps,
                id: idFromProps,
                ref: panelGroupElementRef,
                style: {
                        // style样式合并
                        ...style,
                        ...styleFromProps,
                },
                // CSS selectors
                "data-panel-group": "",
                "data-panel-group-direction": direction,
                "data-panel-group-id": groupId,
                })
        );

PanelResizeHandle

PanelResizeHandle主要实现了容器大小的改变逻辑,主要有相应事件的订阅、通知变更

在PanelResizeHandle里面通过registerResizeHandle注册相应事件的监听函数。 注册Handler
在registerResizeHandle内部主要通过Set结构管理ResizeHandle相关的数据(回调函数等)并且完成在body上事件的绑定与移除。 注册细节
listener
在对应时间的处理逻辑中,以处理mousemove的handlePointerMove为例 回调出发逻辑
最终走到PanelGroup中的registerResizeHandle方法,根据event动态调整对应panel的样式属性 flexAdjust