📅 GJ504b 的 React 进阶之路:Day 1

📅 GJ504b 的 React 进阶之路:Day 1

知识清单

1 用 Vite + React 从零构建项目

pnpm create vite@latest 项目名称
pnpm i
pnpm run dev

2 组件化思维:将复杂的页面抽象可复用的 StaticCard 组件

数据向下流动 (Props),行为向上触发 (Callbacks)

alt text
补充:

  1. “子传父”其实是状态提升。 当多个组件需要共享数据时,我们把状态保存在共同的父组件中。

  2. “蓝色都是通过 props”也可以总结为 声明式 UI 渲染。 我们只负责通过props描述数据长什么样,React 负责把它画出来。

  3. StaticCard 就是我设计的的原子组件,具有高度的独立性和可复用性。

3 组件通信和列表渲染

父传子

通过在父组件定义数组对象(json)形式向子组件传递其需要的属性。即:父组件定义子组件需要的属性,子组件通过props的形式接受渲染UI

  const navData = [
    {title:"今日待处理",count:12},
    {title:"本月新增",count:28},
    {title:"待审查成功病历",count:5},
    {title:"需要重新诊断",count:2}
]
 <StaticCard title = {item.title} count = {item.count} key={i} />//父组件定义子组件需要的props
export default function StaticCard(props) {}//子组件接收通过props

子传父

通过在父组件定义函数并传给子组件,实现点击查看详情时,父组件能接收到具体的业务信息。

  const handleChildClick = (name) =>{
    alert("点击: "+name+" 成功")
  }//父组件展示的方式
 <StaticCard onCardClick= {handleChildClick} />//接受子组件具体的业务信息

<a onClick={()=>props.onCardClick(props.title)}>
          <p>查看详情</p>
          <p>→</p>
</a>//点击a标签区域触发给父组件业务

数据驱动渲染

学会使用 .map() 循环渲染数组数据

      {
        navData.map((item,i) =>{//绑定item和i
          return(
            <StaticCard title = {item.title} count = {item.count} key={i} onCardClick= {handleChildClick} />
          )
        })
      }

🧀🧀🧀key在diff算法的重要性

Diff 算法是 React 提升性能的关键。它通过同层对比、组件类型判断以及唯一 Key 标识,把对比的时间复杂度从 O(n³) 降低到了 O(n)。这样当数据变化时,React 能够以最小的代价更新真实 DOM,保证了页面的流畅。

比如当顺序不一样的时候,有了key,diff算法就会聪明的只调组件的位置而不是全部重新渲染

4 状态管理初探 (Hooks)

useState 钩子:告别低级的 alert 弹窗,实现点击卡片后,页面顶部标题实时、异步更新的交互效果。

import { useState } from 'react'
  const [activeTitle, setActiveTitle] = useState("请选择卡片")

  const handleChildClick = (name) =>{
    setActiveTitle(name)
  }

5 解决的“坑”与思考

  1. 箭头函数 vs 立即执行:
    onClick={() => func()} 是绑定
    页面刷新时,这个函数只是被存起来了,并没有执行。只有当你真正点击按钮的那一刻,浏览器才会触发这个箭头函数
    onClick={func()} 是立即执行
    页面一刷新,函数就自动运行了

  2. div、p 与 button 在实际开发中的选择逻辑与用户体验

    1. 追求语义化:如果是为了执行一个动作(如:删除、提交、展开),大厂规范要求使用
    2. 追求无障碍:使用 button 标签,残障人士使用读屏插件时,系统会告诉他“这是一个按钮”,而 p 标签只会被识别为一段文字。
    3. 万能的 div:在很多复杂的自定义卡片里,程序员也经常直接在 div 上绑定 onClick,只要加上 cursor: pointer,用户体验是一样的
  3. 组件命名一致性:解决了子传父时 Prop 名字对不上的 Bug(onCardClick),深刻体会到了代码的严谨性

每日一题--力扣 hot 100

题目描述

alt text

我最初的解法

两次循环,暴力求解,时间复杂度O(n^2)

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    const n = nums.length;
    let res = [-1,-1];
    for(let i = 0;i<n;i++ ){
        for(let j = 1+i;j<n;j++){//🧀🧀🧀 不可以是j = 1,因为必须保证j,i不一致,如果那样写可能出现i,j一致
            if(nums[i] + nums[j] == target){
                res[0] = i;
                res[1] = j; 
                return res;
            }
        }
    }
};

没有必要引入res数组,我们可以直接返回的

var twoSum = function(nums, target) {
    const n = nums.length;
    for(let i = 0;i<n;i++ ){
        for(let j = 1+i;j<n;j++){
            if(nums[i] + nums[j] == target){
                return [i,j];
            }
        }
    }
};

更好的解法

哈希表,以空间换时间,用键值对储存已经运算过的信息,避免重复计算,时间复杂度O(n)

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    const n = nums.length;
    const map = new Map();//构建哈希表
    for(let i=0;i<n;i++){
        const nextNumber = target - nums[i];
        if(map.has(nextNumber)){//has()方法:找哈希表内有无我们的目标值
            return[map.get(nextNumber),i];//get()方法,得到下标,我们的键
        }
        map.set(nums[i],i);//set()方法:每次将值和下标储存入哈希表
    }
};
posted @ 2026-02-01 22:06  GJ504b  阅读(2)  评论(0)    收藏  举报