工作总结 - 前两周 flex、context、版心布局、shadcn

评估工作量要看提纯 - 单个不重复元素的多少,奇形怪状的增加时间,而不是内容的长短,如果多重复那就没什么做的,

第一个(首页)时间长一点,后面的时间可以短,因为可以复用可以搭建。

如果不重复就很麻烦 !!!!!

感觉得给单独样式留一整天,我这个改太慢了。!!!!很不熟悉。

我发现单独打div然后tab就可以补全!

flex的布局问题,子元素放大缩小不能正常

子元素有问题:一个是px太长,一个是元素太长溢出,导致子项占比太长。

不管了,从头开始。

一定要多用flex-shrik和grow,去定义,

style={{ minWidth: 0 }} // 确保能正常收缩

例子:下面这个虽然设置了flex1,但是也无法等比例显示:因为fle

<div class="container">
  <div class="item">特别特别特别特别特别特别特别长的内容</div>
  <div class="item">正常内容</div>
  <div class="item">正常内容</div>
</div>

<style>
.container {
  display: flex;
  width: 600px;
  border: 2px solid red;
}

.item {
  flex: 1;
  border: 1px solid #ccc;
}
</style>

 

 

版心布局适配心得(!!!)

希望左边宽度固定,右边宽度自适应,最大宽度1440,用flex布局怎么实现?

可能的结构是将整个flex容器包裹在一个外层div中,外层div设置max-width:1440px和margin:auto,这样在宽屏时居中显示,内容不超过1440px。

左边元素的宽度设为固定值,比如200px,右边元素则使用flex:1,

正确的结构应该是外层div负责最大宽度和居中,内层flex容器负责左右布局

(不要用一层flex实现!!!!flex这里会有问题,扩大的时候直接左边不见,且没有滚动条,详见上一篇。因为max width和flex有些冲突,是说!!!

shrink-0 不收缩。grow-0,不扩张 (有多的情况下)

注意 右边超出的部分设置min-width: 0; /* 关键:允许内容收缩 */

不然右边会大出一大块,非常多。

即使是flex1了,但是如果没有min-width 0 也会出现宽度不等的情况,尤其是 存在一些字符串,字符串太长,删掉字符串没问题。字符串太长又设置了line-clamp-3,的情况下,就被给默认不允许压缩了

 

PS: 样式调试经验:

git保存代码后,里面内容直接清空换颜色块,观察是内部元素问题,还是父元素的样式问题;

对于子元素,一块一块注释,二分找错误地方。

子元素严格等宽度:

flex-1 shrink-0 basis-[calc((100%-2.5rem)/3)] grow-0 min-w-0

注意basis

code尚未验证,但是意思真的差不多。

<!DOCTYPE html>
<html>
<head>
<style>
/* 外层容器 - 控制最大宽度和居中 */
.container-wrapper {
  max-width: 1440px;
  margin: 0 auto;
  padding: 0 20px; /* 可选:添加左右内边距 */
  box-sizing: border-box;
}

/* flex容器 */
.flex-container {
  display: flex;
  gap: 20px; /* 可选:列间距 */
  min-height: 100vh; /* 仅为演示高度 */
}

/* 左侧固定宽度 */
.left-column {
  flex: 0 0 200px; /* 不增长,不收缩,固定200px */
  background: #f0f0f0;
  padding: 20px;
}

/* 右侧自适应 */
.right-column {
  flex: 1; /* 占满剩余空间 */
  min-width: 0; /* 关键:允许内容收缩 */
  background: #fff;
  padding: 20px;
}

/* 响应式处理(可选) */
@media (max-width: 768px) {
  .flex-container {
    flex-direction: column;
  }
  .left-column {
    flex-basis: auto;
    width: 100%;
  }
}
</style>
</head>
<body>

<div class="container-wrapper">
  <div class="flex-container">
    <div class="left-column">
      <h2>固定侧边栏</h2>
      <p>宽度固定为200px</p>
    </div>
    
    <div class="right-column">
      <h1>自适应内容区</h1>
      <p>此区域会自适应填充剩余空间</p>
      <p>最大宽度限制为1440px(包含左右边距)</p>
    </div>
  </div>
</div>

</body>
</html>

(终于实现了。。。。先这样吧,适配的再说了,搞太久了

谁能知道最后宽度不一致的原因是多写了一个h-full呢。。。。

真的就纯凭实验。。。。。。。

注意,之前h-full的理解是错的

你设置 height: 100% 时,子元素会继承父元素的完整高度(100vh),而不是"剩余高度"。CSS 的百分比高度是基于父元素的完整高度计算的,而不是基于"剩余可用空间"。

Flexbox 或 Grid 布局是解决这类问题的最佳方案,因为它们专门设计用于处理这种动态空间分配。

想实现的话,用flex-1和column来做

1.overflow-y-auto比scroll更好,auto是只有超过的时候才显示进度条,scroll一直有

2.next 路由:只有page级别的,才能自动有路由,index.tsx不行,所以说大层的路由只有一个。

Next.js 13+ 版本中,引入了新的 App Router 系统,它使用 app 目录而不是 pages 目录,并且使用 page.tsx 文件 (再之前是index.js )现在pages

3. 不是,啊,svg的fill=currentColor是要用text-color去覆盖的,直接bg更改的是后面的颜色是整体的,要text-color!!!!

为什么渲染了两次???

👇 这个问题莫名其妙的好了?把console的报错解决掉—- sheet.trigger里加了as child (不能button嵌套button)之后就解决了??

shadcn/ui 的 Sheet 基于 Radix UIDialog 实现,其底层会通过 React Portal 将内容渲染到 <body> 末端。这会触发

  • 首次渲染:组件初始化
  • Portal 挂载:内容插入到 DOM 新位置,导致组件树结构变化,触发二次渲染

可以给sheet挂isopen才渲染

也可以用ref标记,虽然会二次渲染但是应该不会再影响接口了,

if (isFirstRender.current) {
      isFirstRender.current = false;
      return;
    }

为什么fetch请求的headers看不了?因为headers内部封装了,**不可直接枚举,无法正确序列化,**打印也只是快照,得这样

console.log('Headers 内容:', Object.fromEntries(requestHeaders.entries()));

fetch有一个 no-cors,但是只支持有限的请求头,且不能自定义请求头,而且看不到响应的信息!!!!!

此时的响应类型为opaque,然而在opaque的返回类型中,咱们简直不能查看到任何有价值的信息,比方不能查看response,status, url。

tw规范

第一级,宽高边距

第二级,ls

第三级,颜色

您直接使用 useSWRMutation 返回的 data 导致值未更新,原因是 SWR 的 data 状态更新存在延迟,而您没有正确等待异步操作完成

—- 子组件得包裹memo,否则读取值都读不到。。。

👆 跟这没关系。。。得use effect去监听,因为是运行时再去获取的

  • useEffect是在DOM改变之后触发,useMemo在DOM渲染之前就触发

  • useMemo是在DOM更新前触发的

  • 父组件将一个 【值】 传递给子组件,若父组件的其他值发生变化时,子组件也会跟着渲染多次,会造成性能浪费; useMemo是将父组件传递给子组件的值缓存起来,只有当 useMemo中的第二个参数状态变化时,子组件才重新渲染useMemo便是用于缓存该函数的执行结果,仅当依赖项改变后才会重新计算

  • 父组件将一个 【值】 传递给子组件,若父组件的其他值发生变化时,子组件也会跟着渲染多次,会造成性能浪费; useMemo是将父组件传递给子组件的值缓存起来,只有当 useMemo中的第二个参数状态变化时,子组件才重新渲染

  • useMemo便是用于缓存该函数的执行结果,仅当依赖项改变后才会重新计算

useMemo不会再参与dom渲染期间才需要变动的事情!!

tailwind css动态渲染

需要注意,只是不支持处理掉他预设的类名,比如 w-[100] —> w-[aaaa]

但是固定的动态计算还是好使的,比如 “” : aaa=1这时候成立

憋动到样式里面去就ok。

有关context

我理解,现在这更像是重写provider的方式来去提供一个context

context的一般用法:

1 最外层 createContext,

2 之后用provider去提供context,

3 读取的时候直接在组件内部use context

似乎可以直接在组件内部掉用set之类的方法,

但是一定得在组件内部,否则是用不了的

写过的用法:

因为要对context进行处理且提出来逻辑,所以对context进行重写

其实也就是最外层的逻辑嘛,要么在最外层大的那里写,然后最外层那边处理;要么在provider这一层写。

没毛病。

也是给被context包裹住的全局使用的。

ps: provider 自己也需要有个props,这也和直接在最外层使用还是提供一个provider一样思路

有关refs

这我不会了。不理解。

ref用于不用use state的常量,或者是直接引用到相关的dom元素。

先create ref

再设置current


有关use refucer

  • 状态是一个对象,且需要多种修改方式时
  • 修改逻辑复杂,需要集中管理(比如表单校验、购物车)
  • 状态需要被多个子组件共享时(配合 Context API)

首先,声明一个money reduceer,这里面封装进去具体的操作,比如说什么存钱取钱,通过switch的方式,进行一个集合。

之后, const [state, dispatch] = useReducer(moneyReducer, { money: 0 }); 三个值,state原始数据,dispatch更改,reducer方法。

使用type和具体的参数来搞进变量。 dispatch({ type: '存钱', num: 10 }

那么如果用变量的方式写,就是 —- (初始变量)

const [aaaRecord, dispatchStatus] = useReducer(
      aaaaReducer,
      initialStatus,
    );

而具体redux怎么用,还放在了一个文件

规范了一下每一个reducer应该传递什么文件进来,

对于dispatch就只需要传类型和数据,具体的操作步骤是reducer人去做的。

有关 infinate scroll

不会写,写不来,教学一下,如果懂了可以更新到视频的p2??

 

enum

可以当变量。可参与计算、比较,不会像interface一样擦除!!

shadcn

  • 手动安装后,需要把相关文件粘贴进组件库

    ShadCN 的整体设计可以分为「组件设计」和「CLI 设计」

    它的cli也是添加一个文件

    ui/ 后面的文件,最好可以不用动~

平滑滚动 

子元素还要设置snap-start

也就是父元素:

  scroll-snap-type: x mandatory;(强制

  scroll-snap-type: x proximity;(不强制 x轴)

子元素还要:

        .snap-start {
    scroll-snap-align: start;
  }

  • inline'start' 'center' 'end' 'nearest'控制横向滚动对齐方式(核心参数)
    block 同上 控制纵向滚动对齐方式(设为 nearest 可避免纵向干扰)
    element.scrollIntoView({
      behavior: 'smooth',  // 滚动动画
      block: 'nearest',    // 垂直方向不强制对齐
      inline: 'center'     // 水平方向居中(关键参数)
    });
    

    关键是要通过id获取到元素

  • 简化版新组件 【看这个!】

    import { FC, memo } from 'react';
    const Corner: FC = () => {
      return <></>;
    };
    
    export default memo(Corner);
    

多用语义化 反正原生的标签样式都无了

sectionn

p

h4

ul 后li,作为for的迭代

shadcn 使用casourle

关键代码:一定要写上setApi才能获取,setapi就素在操作数据了。

   	opts={{
          align: 'center',
          startIndex: startIndex,
        }}
        setApi={setApi}

as child属性

控制组件是否将自身渲染为直接子元素(child)的容器

  • asChild={false}(默认):组件渲染为自身默认的 DOM 元素(如 <button>
  • asChild={true}:组件会将第一个子元素作为渲染根节点,同时将自身的属性和样式透传给该子元素

主要是用于透传东西。

就类似

const Slot = React.forwardRef((props, ref) => { const { children, ...rest } = props; return React.isValidElement(children) ? React.cloneElement(children, { ...rest, ref }) : null; });

在shadcn里⬇️

import { Slot } from '@radix-ui/react-slot';

最后,我的代码写出来belike ⬇️,这是极好的,不管你用不用button都行,as child的话,就直接透传,onclick方法和一些context都在casouel内部做完了,外界不用关心。

const Comp = asChild ? Slot : Button;

return (
    <Comp
      ref={ref}
      //   variant={variant}
      size={size}

按钮点按的状态 实际上就是: active 就行。

bootstrap里的sr-only全称是 screen reader only,意为 为无障碍设计的 标签

git常用操作

git checkout xxxxbranch

git branch 查看有什么branch

useSWRMutation

即使是 await里的代码 也能调用 swr里的具体参数

swr返回值

  • data: fetcher 返回的给定键的数据
  • error: fetcher 抛出的错误(或 undefined)
  • trigger(arg, options): 用于触发远程突变的函数
  • reset: 用于重置状态的函数(dataerrorisMutating
  • isMutating: 是否正在进行远程突变

但是data有的时候会有 什么。。。读取不到的可能性,此时可以重新接一下数据

要求不高的话isMutating够用了

Memo

简单来说memo是包裹组件的,而 usememo是给函数用的,不影响

  • React.memo() 是一个高阶组件,我们可以使用它来包装我们不想重新渲染的组件,除非其中的 props 发生变化useMemo() 是一个 React Hook,我们可以使用它在组件中包装函数。 我们可以使用它来确保该函数中的值仅在其依赖项之一发生变化时才重新计算
  • React.memo() 是一个高阶组件,我们可以使用它来包装我们不想重新渲染的组件,除非其中的 props 发生变化
  • useMemo() 是一个 React Hook,我们可以使用它在组件中包装函数。 我们可以使用它来确保该函数中的值仅在其依赖项之一发生变化时才重新计算

 

  1. NonNullable 是ts的,去除了null和undefined

  2. Record ts 构造一个对象类型,其属性key是Keys,属性value是Type。被用于映射一个类型的属性到另一个类型。

    • 如,<1, xxxxx> 前面是id
  3. Partial 可选,都可选,里面,而且可以直接。< >

    1. 下面两个等同
    type Coord = Partial<Record<'x' | 'y', number>>;
    
    // 等同于
    type Coord = {
    	x?: number;
    	y?: number;
    }
    
  4. use callback

    不需要 useCallback 的场景

    • 函数只在当前作用域内使用,不传递、不作为依赖项
    • 避免在函数内部直接修改依赖项,而是使用使用函数式更新
      • setCount(prev => prev + 1);

 

bfc cache:

一些高级浏览器启用了这个功能,前进后退只是fress,并么有给清理掉,

因为没有清理掉。所以return () => 里面的就触发不了,得用swr之类的自动触发或者页面enter之类的,才能捕捉到

 

Pick:

Pick<PostLoginRequest, 'session' | 'smsResp'>是从PostLoginRequest类型中选取了sessionsmsResp这两个属性,创建了一个新的类型,包含这两个属性。然后,通过&操作符,将另一个对象类型{ is_redeem_login?: boolean; }合并进来。这里的&表示交叉类型,即合并两个类型的所有属性。

 

session 刷新后也存在

Session Storage 适合存储临时会话数据(如表单草稿、页面状态),在刷新页面时保留数据,但需注意标签页关闭时的数据清除特性

 

尽量高效休息,高效工作,要摸鱼就狂摸,要么就不摸,高效工作大于无效摸鱼

 

posted @ 2025-04-22 11:37  send/me/a/cat  阅读(48)  评论(0)    收藏  举报