(失业学习)个人手写题练习

211 阅读10分钟

代码题

寄生组合式继承

//父类构造函数
function Father(name){
    this.name = name
}
//寄生函数 创建父类原型副本
Father.prototype.eating = function(){}

function inheritPrototype(subType,superType){
    var prototype = Object.create(superType.prototype)
    prototype.constructor = subType
    subType.prototype = prototype
}
//子类构造函数
function Son(name,age){
    Father.call(this,name)
    this.age= age
}

inheritPrototype(Son,Father)

深拷贝

//方法一
JSON.parse(JSON.stringify(obj))
//方法二
function deepClone(value, map = new WeakMap()){
    if(typeof value !== 'object' || value === null ) return value;
    
    if(value instanceof Date || value instanceof RegExp) return value;
    
    if(value instanceof Map){
        return value.forEach((item,index)=>{obj.set(index,deepClone(item,map))})
    }
    if(map.has(value)) return map.get(value)
    
    let res = new value.constructor()
    
    map.set(value,res)
    
    for(let key in value){
        if(Object.hasOwn(value,key)){
            res[key] = deepClone(value[key],map)
        }
    }
    return res
}

树结构查找

// 数据如下: const tree = [ 
    { name: "数据1", id: 1, children: 
        [ { name: "数据2", id: 2, children:
            [ { name: "数据3", id: 3, children:
                [{ name: "数据4", id: 4, children: 
                    [], 
                        }, ], }, ], }, ], }, ];
                    
 //实现
 
 function findNodeById(tree, id) { 
     if(tree.length) return null
     
     const search =(node)=>{
         if(node.id === id){
         return node
         }else if(node.children){
             for(let child of node.children){
                 const res = search(child)
                 if(res){
                    return res
                 }
             }
         }
         return null
     }
     
     for(let root of tree){
         const res = search(root)
         return res
     }
     
 }
//

function findNodeById(tree,id){
    if(!tree.length) return null
    let res 
    
    function search(node){
        if(node.id === id) return node
        
        const res = node.children?.length>0 && node.children.find(child => search(child)) || null
    }
    for(let node of tree){
    res = search(node)
    if(res !== null) return res
    }
    
    return null
    }

数组转树

function arrToTree(arr, parentId){
    return arr.fifter((val)=>{ val.id === parentId})
              .map((val)=>({
              ...val,children:arrToTree(arr,val.id)
              }))
}

树转数组

function treeToArr(tree){
    return tree.reduce((pre,next)=>{
       return pre.concat(next.children?treeToArr(next.children):next)
    },[])
}
//方法二
function treeToArr(tree){
    return tree.reduce((prev,cur){
        if(!tree.children){
            prev.push(cur)
        }else{
            const list = treeToArr(arr.children)
            delete cur.children
            prev.push(cur,...list)
        }
       return prev 
    },[])
    
}

数组扁平化

function flatten(arr){
    return arr.reduce((pre,next)=>{
       return pre.concat(Array.isArray(next)? flatten(next):next)
    },[])
}


function flatten(arr) {
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr);
    }
    return arr;
}

数组去重

[...new Set(arr)]

function unique(arr){
    return arr.filter((item,index,readonly)=>{
            return readonly.indexOf(item,0) === index
        })
}

防抖

function useDebounceFn(fn, delay) {
  const timeout = useRef(null);

  const debounceFn = (...args) => {
    if (timeout.current) {
      clearTimeout(timeout.current);
    }
    timeout.current = setTimeout(() => {
      fn(...args);
    }, delay);
  };

  useEffect(() => {
    if (timeout.current) {
      clearTimeout(timeout.current);
    }
  }, []);

  return debounceFn;
}

节流

function useThrottleFn(fn,delay){
   const lastTime = useRef(0)
   
   const throttleFn = (..args) => {
    const now = Date.now()
    
    if(now - lastTime.current >= wait){
        fn(...args)
        lastTime.current = now
    }
       }
       
       return throttleFn
}

instanceof原理

function myInstanceof(left,right){
    if(typeof left !== 'object' || left =null) return false
    let proto = Object.getPrototypeoOf(left)
    while(proto){
    if(proto === right.prototype){
        return true
    }
    proto = Object.getProtypeOf(proto)
    }
    return false
}

new

function myNew(fn){
    let newObj = Object.create(fn.prototype)
    let res = fn.call(newObj,...args)
    return typeof res === 'object' ? res : newObj
}

call ,apply,bind

//call
Function.prototype.myCall = function (thisArg, ...args) {
  var fn = this;

  thisArg = thisArg ? Object(thisArg) : window;
  thisArg.fn = fn;
  var res = thisArg.fn(...args);

  delete thisArg.fn;

  return res;
};

//apply

Function.prototype.myApply = function(thisArg,argsArr){
    var fn = this
    
    thisArg = thisArg ? Object(thisArg) : window
    thisArg.fn = fn
    
    var res = thisArg.fn(...argsArr)
    
    delete thisArg.fn
    
    return delete
}
//bind

Function.prototype.myBind = function(thisArg,...args){
    var fn = this
    
    thisArg = thisArg ? Object(thisArg) : window
    
    var newFn = function(...arg){
        thisArg.fn =fn
        var newArgs = [...args,...arg]
        var res = thisArg.fn(...newArgs)
        
        delete thisArg.fn
        
        return res
    }
    
    return newFn
} 

实现数字千分符

let num = 12345678910.22;

function parseToMoney(num) {
  let [int, decimal] = String.prototype.split.call(num, ".");
  let parse = int.replace(/\d(?=(\d{3})+$)/g, function (n) {
    return n + ",";
  });
let res = decimal ? parse + "." + decimal :parse
  return res;
}

let res = parseToMoney(num);
console.log(res);
//方法二
num.toLocalString()

解析 URL Params 为对象


let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled';

function(url){
    const paramsStr= url.split('?')[1]
    const paramsArr = paramsStr.split('&')
    let obj = {}
    paramsArr.forEach(params =>{
        if(/=/.text(params)){
            let [key,value] = params.split('=')
            val = docodeURIComponent(val)
            val = /^\d+$/.test(val) ? parseFloat(val) : val
            if(obj.hasOwnProperty(key)){
                obj[key] = [].concat(obj[key],value)
            }else{
                obj[key] = value
            }
        }else{
            obj[key] = null
        }
    })
    return obj
}

function URLParamsObj(url) {
  const _url = new URL(url);
  const params = {};
  for (let [key, value] of _url.searchParams) {
    if (params[key]) {
      params[key] = [].concat(params[key], value);
    } else {
      params[key] = value;
    }
  }
  return params;
}

转化为驼峰命名

function tf(str){
    return str.replace(/-\w/g,function(s)){
        return s.slice(1).toUpperCase()
    }
}

函数柯里化

function keli(fn,params){
    if(fn.length === 0) return fn
    params = params || []
    
    return function curried(...args){
        let newArgs = params.concat(args)
        if(newArgs >= fn.length){
            return fn.apply(this,newArgs)
        }else{
            return curry.call(this, fn, newArgs)
        }
    }
}

字符串反转

//方法一
function reveser1(str){
    return str.split('').reveser().join('')
}
//方法二
function strReverse(str){

return Array.from(str).reduce((pre,cur)=> return `${cur}${pre}`,'')
}

promise.all

function myAll(proms){
    return new Promise((resolve,reject)=>{
        res = []
        count = 0
        proms.forEach((item,index)=>{
            count++
            Promise.resolve(item).then(data=>{
                res[index] = data
                if(count === proms.length){
                    resolve(res)
                }
            },reject)
        })
    })
}

promise.race

    function myRace(proms){
        return new Promise((resolve,reject)=>{
            proms.forEach(item=>{
                Promise.resolve(item).then(data=>resolve(data),reject)
            })
        })
    }

promise并发控制


async function promisePool(tasks, limit) {
    const resArr = new Array(tasks.length); // 初始化结果数组
    const queue = []; // 存储当前正在运行的任务

    for (let i = 0; i < tasks.length; i++) {
        const task = tasks[i]()
            .then((res) => {
                resArr[i] = res; // 任务成功时,存储结果
            })
            .catch((err) => {
                resArr[i] = err; // 任务失败时,存储错误
            })
            .finally(() => {
                queue.splice(queue.indexOf(task), 1); // 任务完成后,从队列中移除
            });

        queue.push(task); // 将任务添加到队列中

        if (queue.length >= limit) {
            // 如果队列已满,等待任意一个任务完成
            await Promise.race(queue);
        }
    }

    // 等待所有任务完成
    await Promise.allSettled(queue);

    // 返回结果数组
    return resArr;
}


单例模式

//ES5
let Model = (function(){
                let instance
                function User(name,age){
                    this.name = name
                    this.age = age
                }
                return function(name){
                    if(!instance){
                        
                        return instance = new User()
                    }
                    return instance
                }
})()

//ES6
class Singleton{
    construtor(name,age){
        this.name = name
        this.age = age
        if(!Singleton.instance){
            return Singleton.instance
        }
        return Singleton.instance
    }
}

装饰器模式

//js
Function.prototype.before=function(beforeFn){
    let _this = this
    return function(){
        beforeFn.call(this,...args)
        return _this.call(this,...args)
    }
}

//ts
//类装饰器 ClassDecorator
//属性装饰器 ProtertyDecorator
//参数装饰器 ParameterDecorator
//方法装饰器 MethodDecorator

const Base = (name:string) => {
  return  const Fn:ClassDecorator(target){
          console.log(target,返回的是构造函数)
          target.prototype.name = name
          }
}
@Base(name)
class Person{
    //...
    }

观察者模式

class Suject{
    constructor(){
        this.observers = []
    }
    add(observer){
        this.observers.push(observer)
    }
    remove(obsever){
        this.observers = this.observers.filter(item =>return item !== observer)
    }
    notify(){
        this.observers.forEach(item=> item.update())
    }
}
class Observer{
    constructor(name){
        this.name = name
    }
    update(){
    //...
    }
}

const sub = new Subject()
const obs1 = new Observer(obs1)
//订阅
sub.add(obs1)
//发布
sub.notify()
//ts
const List:Set<Function> = new Set()
const autorun = (cb:Function) => {
 if(!List.has(cb)){
     List.add(cb)
 }
}
const observer = <T extends obj>(params:T) =>{
    return new Proxy(params,{
        set(target,key,value,receiver){
        const res = Refect.set(target,key,value,receiver)
        List.forEach(fn => fn())
        return res
        }
    })
}
//创建被观察者实例
const obsProxy = observable({ name: "cn" });
//创建观察者并订阅
autorun(() => {
  console.log("1");
});

obsProxy.name = "ln";

发布订阅模式

//ts
interface I {
    on:(name:string,callback:Function)=>void
    once:(name:string,callback:Function)=>void
    emit:(name:string,...args:Array<any>)=>void
    off:(name:string,callback:Function)=>void
}
class Emitter implements I {
    event:Map<string,Function[]>
    constructor(){
        this.event = new Map()
    }
    on(name:string,callback:Function){
        if(this.event.has(name)){
           const callbacks = this.event.get(name)
           callback && callbacks.push(callback)
        }else{
            this.event.set(name,[callback])
        }
    }
    once(name:string,callback:Function){
        const cb = (...args:any[])=>{
            callback(...args)
            this.off(cb)
        }
        this.on(name,cb)
    }
    emit(name:string,...args:any[]){ 
        const callbacks = this.event.get(name)
         if(callbacks){         
           callbacks.forEach(Fn => Fn(...args))
           }
    }
    off(name:string,callback:Function){
        const callbacks = this.event.get(name)
        if(callbacks){
            callbacks.splice(callbacks.indexOf(callback),1)
        }
    }
}

ts泛型工具

将传入的属性变为可选项
type Partial<T> = { 
    [P in keyof T]?: T[P];
};
将传入的属性变为必填
type Required<T> = { 
    [P in keyof T]-?: T[P]; 
};
将传入的属性变为只读
type Readonly<T> = { 
    readonly [P in keyof T]: T[P]; 
};
定义keey value
type Record<K extends keyof any, T> = { 
    [P in K]: T; 
};
在 T 中,过滤掉非 S 的类型
type Pick<T, K extends keyof T> = { 
[key in K]: T[key]
}
从类型T中剔除所有可以赋值给类型U的类型
type Exclude<T, U> = T extends U ? never : T;

算法

字符串压缩

function compressString(str) {
    let compressed = '';
    let count = 1;

    for (let i = 0; i < str.length; i++) {
        if (str[i] === str[i + 1]) {
            count++;
        } else {
            compressed += str[i] + (count > 1 ? count : '');
            count = 1;
        }
    }

    return compressed.length < str.length ? compressed : str;
}

LRU算法

class LRUCache { 
constructor(lenght) { 
this.length = lenght; // 存储长度 
this.data = new Map(); // 存储数据 } 
// 存储数据,通过键值对的方式 
set(key, value) { 
const data = this.data;
if (data.has(key)) { 
data.delete(key) 
}
data.set(key, value); 
// 如果超出了容量,则需要删除最久的数据 
if (data.size > this.length) { 
const delKey = data.keys().next().value; data.delete(delKey);
} 
} 
// 获取数据 
get(key) { const data = this.data;
// 未找到 
if (!data.has(key)) { return null; } 
const value = data.get(key);
// 获取元素 
data.delete(key); 
// 删除元素
data.set(key, value); 
// 重新插入元素
} }

JavaScript 实现钟表上分针与时针夹角

  1. 计算时针的角度

    • 每小时时针转动 30 度(360 度 / 12 小时)。
    • 每分钟时针额外转动 0.5 度(30 度 / 60 分钟)。
    • 公式:时针角度 = (小时 % 12) * 30 + 分钟 * 0.5
  2. 计算分针的角度

    • 每分钟分针转动 6 度(360 度 / 60 分钟)。
    • 公式:分针角度 = 分钟 * 6
  3. 计算夹角

    • 夹角 = Math.abs(时针角度 - 分针角度)
    • 如果夹角大于 180 度,取 360 - 夹角(因为钟表的最大角度是 180 度)。
function calculateClockAngle(hour, minute) {
  // 计算时针角度
  const hourAngle = (hour % 12) * 30 + minute * 0.5;
  // 计算分针角度
  const minuteAngle = minute * 6;
  // 计算夹角
  let angleDiff = Math.abs(hourAngle - minuteAngle);
  // 如果夹角大于 180 度,取 360 - 夹角
  if (angleDiff > 180) {
    angleDiff = 360 - angleDiff;
  }
  return angleDiff;
}

有效的括号

给定一个只包括 `'('``')'``'{'``'}'``'['``']'` 的字符串 `s` ,判断字符串是否有效。

有效字符串需满足:

1.  左括号必须用相同类型的右括号闭合。
1.  左括号必须以正确的顺序闭合。
1.  每个右括号都有一个对应的相同类型的左括号。

function isValid(s){
    const stack = []
    const map = {
        '(' : () => stack.push(')'),
        '{' : () => stack.push('}'),
        '[' : () => stack.push(']')
    }
    for(let i in s){
        fn = map[s[i]]
        top = stack[stack.length-1]
        if(fn){
            fn()
        }else if(top === s[i]){
            stack.pop()
        }else{
            return false
        }
        
    }
    return true
}

无重复字符的最长子串

function lengthOfLongestSubstring(s){
    const set = new Set()
    let max = 0
    let i=0, j=0
    for(i;i<s.length;i++){
        if(set.has(s[i])){
            set.add(s[i])
            max = Math.max(max,set.size)
        }else{
            while(set.has[i]){
                set.delete[j]
                j++
            }
            set.add(s[i])
        }
       return max
    }
}

最长公共前戳

function longestCommonPrefix(strs:Array<string>):string{
    const str = strs[0]
    while(!strs.every(i => i.startWith(str))){
        str= str.slice(0,str.length)
    }
     return str === ''?'':str
}

最长连续序列

function longestConsecutive(nums:Array<number>):number{
    const arr = Array.from(new Set(nums)).sort((a,b)=>a-b)
    let ans=1, len=0
    for(let i=1;i<arr.length;i++){
    if(arr[i] - arr[i-1] === 1){
        ans = Math.max(ans,i+1-len)
    }else{
        len = i
    }
    }
    return ans
}

版本号比较


function compareVersions(version1, version2) {
    const v1Parts = version1.split('.')
    const v2Parts = version2.split('.')
    const maxLength = Math.max(v1Parts.length, v2Parts.length);

    for (let i = 0; i < maxLength; i++) {
        const num1 = v1Parts[i] || 0;
        const num2 = v2Parts[i] || 0;

        if (num1 > num2) {
            return 1;
        } else if (num1 < num2) {
            return -1;
        }
    }

    return 0;
}

实现斐波那契数列

function fn (n){
    if(n==0) return 0  
    if(n==1) return 1 
    return fn(n-2)+fn(n-1) 
    }

回文数


function isPalindrome(num){
        if(num <0 || (num !== 0 && num%10 = 0)) return false
        
        let res = 0
        
        while(num > res){
            res = res*10 + num%10
          num =  Math.floor(num/10)
        }
        
        if(num === res || num === Math.floor(res/10)){
            return true
        }
        return false
}

排序

冒泡排序

原理:利用数组的前一项与相邻的后一项相比较,判断大/小,交换位置


const bubbleSort = function(ary){
    for(let i = 0; i < ary.length - 1; i++){
        for(let j = 0; j < ary.length - 1 - i; j++){
            if(ary[j] > ary[j+1]){
                [ary[j], ary[j+1]] = [ary[j+1], ary[j]]
            }
        }
    }

    return ary

}

选择排序

原理:利用数组的某项与后面所有的值相比较,判断大/小,交换位置


const bubbleSort = function(ary){
    for(let i = 0; i < ary.length - 1; i++){
        for(let j = i + 1; j < ary.length; j++){
            if(ary[i] > ary[j]){
                [ary[i], ary[j]] = [ary[j], ary[i]]
            }
        }
    }
    return ary
}

原生排序


Array.sort((a, b)=>a-b)

快速排序

原理:取数组的中间值作为基准,判断左右两边的值大或小,添加到相应数组,递归调用,然后将所有的值拼接在一起。


const quick_sort = function(ary){
    if(ary.length < 1){
        return ary
    }


    let centerIndex = Math.floor(ary.length/2)
    let centerVal = ary.splice(centerIndex, 1)[0]


    let left = []
    let right = []
    ary.forEach(item => {
        item > centerVal ? right.push(item) : left.push(item)
    })

    return [...quick_sort(left), ...[centerVal], ...quick_sort(right)]
}

插入排序

原理:先将数组中的一项添加到新数组中,循环数组每一项与新数组中比较,比较大的值放在后面小的放到新数组的前面。


 const insertion_sort = function(ary){
    let newAry = ary.splice(0, 1)
    for(let i = 0; i < ary.length; i++){
        let cur = ary[i]
        for(let j = newAry.length - 1; j >= 0;){
            if(cur < newAry[j]){
                j--
                j === -1 && newAry.unshift(cur)
            } else {
                newAry.splice(j + 1, 0, cur)
                j = -1
            }
        }
    }
    return [...newAry]
}

react hooks相关练习

实现一个定时器hook 要求每一秒执行一个回调函数

import { useEffect, useRef } from "react";

export default function useInterval(cb: () => void, delay: number) {
  const saveCb = useRef<() => void>(null);
//更新最新的回调函数
  useEffect(() => {
    saveCb.current = cb;
  }, [cb]);
//依赖delay设置定时器
  useEffect(() => {
    function task() {
      if (saveCb.current) {
        saveCb.current();
      }
    }

    if (delay !== null) {
      const id = setInterval(task, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

监听dom大小的hook

const useResize = (callback: (width: number, height: number) => void) => {
  const ref = useRef(null);

  useEffect(() => {
    const element = ref.current;
    if (element) {
      const resizeObserver = new ResizeObserver((entries) => {
        for (const entry of entries) {
          callback(entry.contentRect.width, entry.contentRect.height);
        }
      });
      resizeObserver.observe(element);

      return () => {
        resizeObserver.disconnect();
      };
    }
  }, [callback]);

  return ref;
};

react hooks实现select模糊匹配(简单版)

import { ReactNode, useEffect, useState } from "react";

interface FuzzySelectProps {
  options: Array<string>;
}

type optionsType = FuzzySelectProps["options"];
const higlightMatch: any = (text: string, search?: string) => {
  if (!search) return text;

  const regex = new RegExp(`(${search})`, "gi");
  return text.split(regex).map((item, index) => {
    console.log(item);
    return regex.test(item) ? (
      <span key={index} style={{ color: "red" }}>
        {item}
      </span>
    ) : (
      item
    );
  });
  console.log(text.split(regex));
};
export default function FuzzySelect({ options }: FuzzySelectProps) {
  const [inputValue, setValue] = useState<string>("");

  const [newOptions, setnewOptions] = useState<optionsType>(options);

  useEffect(() => {
    if (inputValue) {
      const filtered = options.filter((option) =>
        option.toLowerCase().includes(inputValue.toLowerCase())
      );
      setnewOptions(filtered);
    } else {
      setnewOptions(options);
    }
  }, [inputValue, options]);
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setValue(e.target.value);
  };
  return (
    <div>
      <input type="text" value={inputValue} onChange={handleChange} />
      <ul>
        {newOptions.map((option, index) => {
          return <li key={index}>{higlightMatch(option, inputValue)}</li>;
        })}
      </ul>
    </div>
  );
}

时分秒倒计时


const Countdown = ({ initialSeconds }) => {
  // 使用 useState 来管理剩余秒数
  const [seconds, setSeconds] = useState(initialSeconds);

  useEffect(() => {
    if (seconds > 0) {
      // 设置一个定时器,每秒减少一秒
      const interval = setInterval(() => {
        setSeconds((prevSeconds) => prevSeconds - 1);
      }, 1000);

      // 在组件卸载或者 seconds 变为 0 时清除定时器
      return () => clearInterval(interval);
    }
  }, [seconds]);

  // 将剩余秒数转换为时分秒格式
  const formatTime = (time) => {
    const hours = Math.floor(time / 3600);
    const minutes = Math.floor((time % 3600) / 60);
    const secs = time % 60;

    const pad = (num) => num.toString().padStart(2, "0");

    return `${pad(hours)}:${pad(minutes)}:${pad(secs)}`;
  };

  return (
    <div>
      {seconds > 0 ? <p>倒计时: {formatTime(seconds)}</p> : <p>倒计时结束</p>}
    </div>
  );
};

useAsyncCache

const { useEffect } = require("react");
const { useState } = require("react");

const useAsyncCache = (fn, cache) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const localCache = localStorage.getItem(key);
    if (localCache) {
      const [value, time] = JSON.parse(localCache);

      if (new Date() - time < cache.minutes * 60 * 1000) {
        setData(value);
        setLoading(false);
        return
      }
    }
    const fetch = async () => {
      try {
        setLoading(true);
        const res = await fn();
        const localCache = {
          value: res,
          time: Date.now(),
        };

        localStorage.setItem(key, JSON.stringify(localCache));
        setData(res);
      } catch (err) {
      } finally {
        setLoading(false);
      }
    };

    fetch();
  });


  return [loading,data]
};

const fetchData = async (time) =>
  new Promise((resolve) => {
    setTimeout(() => {
      console.log("fetchData");
      resolve("这是结果");
    }, time);
  });

// 使用示例
const App = () => {
  const { loading, data } = useAsyncCache(fetchData, { key: "", minutes: 1 });

  if (loading) {
    return <div>Loading</div>;
  }

  return <div>{data}</div>;
};

loadsh 参数查找


function get(obj, path, defaultValue) {
    const keys = path.replace(/[(\d+)]/g, '.$1').split('.');
    let current = obj;
    for (let key of keys) {
        if (current === null || current === undefined) {
            return defaultValue;
        }
        current = current[key];
    }
    return current === undefined ? defaultValue : current;
}

// 示例使用
let obj = {a: [{b: {c3}}]};
console.log(get(obj, "a[0].b.c")); // => 3
console.log(get(obj, "a.0.b.c")); // => 3
console.log(get(obj, "a.b.c""default")); // => "

登录组件

import { Button, Form, Input, Space } from "antd";
import "./index.css";
import { useForm } from "antd/es/form/Form";
import { use, useState } from "react";
function register(options: any) {
  return new Promise<void>((resolve, reject) => {
    setTimeout(() => {
      localStorage.setItem("login", JSON.stringify(options));
      resolve();
    }, 2000);
  });
}

function login() {
  return new Promise((resolve) => {
    setTimeout(() => {
      const res = JSON.parse(localStorage.getItem("login")!);
      console.log(res);
      resolve(res);
    }, 2000);
  });
}

export default function Authing() {
  const [form] = useForm();
  const [active, setActive] = useState("login");
  const handleFinish = async () => {
    const value = form.getFieldsValue();
    if (active === "login") {
      try {
        const loginData: any = await login();
        if (
          loginData.user === value.user &&
          loginData.password === value.password
        ) {
          console.log("登录成功");
        } else {
          console.log("登录失败");
        }
      } catch (error) {
        console.log(error);
      }
    } else {
      await register(value);
      console.log("注册成功");
    }
  };
  const activeClick = () => {
    setActive((value) => {
      return value === "login" ? "register" : "login";
    });
    form.resetFields();
  };
  return (
    <>
      <div className="form">
        <Form
          name="login"
          form={form}
          labelCol={{ span: 8 }}
          wrapperCol={{ span: 16 }}
          onFinish={handleFinish}
        >
          <Form.Item
            name="user"
            label="user"
            rules={[{ required: true, message: "请输入用户名" }]}
          >
            <Input />
          </Form.Item>
          <Form.Item
            name="password"
            label="password"
            rules={[{ required: true, message: "请输入密码" }]}
          >
            <Input.Password />
          </Form.Item>
          {active === "register" ? (
            <Form.Item
              name="confirm"
              label="Confirm Password"
              rules={[
                { required: true, message: "请输入" },
                ({ getFieldValue }) => ({
                  validator(_, value) {
                    if (!value || getFieldValue("password") === value) {
                      return Promise.resolve();
                    } else {
                      return Promise.reject(new Error("密码不一致"));
                    }
                  },
                }),
              ]}
            >
              <Input />
            </Form.Item>
          ) : null}
          <Form.Item wrapperCol={{ offset: 6, span: 16 }}>
            <Space>
              <Button type="primary" htmlType="submit">
                {active === "login" ? "登录" : "注册"}
              </Button>
              <Button type="link" onClick={activeClick}>
                是否{active === "login" ? "注册" : "登录"}
              </Button>
            </Space>
          </Form.Item>
        </Form>
      </div>
    </>
  );
}

实现简单todolist


import React, { useState } from 'react';

const TodoList = () => {
    const [tasks, setTasks] = useState([]);
    const [inputValue, setInputValue] = useState('');

    const handleInputChange = (e) => {
        setInputValue(e.target.value);
    };

    const handleAddTask = () => {
        if (inputValue.trim() !== '') {
            setTasks([...tasks, inputValue]);
            setInputValue('');
        }
    };

    const handleDeleteTask = (index) => {
        const newTasks = [...tasks];
        newTasks.splice(index, 1);
        setTasks(newTasks);
    };

    return (
        <div className="p-4">
            <h1 className="text-2xl font-bold mb-4">ToDo List</h1>
            <div className="flex mb-4">
                <input
                    type="text"
                    value={inputValue}
                    onChange={handleInputChange}
                    className="border border-gray-300 rounded-l-md p-2 w-full"
                    placeholder="Add a new task"
                />
                <button
                    onClick={handleAddTask}
                    className="bg-blue-500 text-white rounded-r-md p-2"
                >
                    Add
                </button>
            </div>
            <ul>
                {tasks.map((task, index) => (
                    <li key={index} className="flex items-center mb-2">
                        <span className="mr-2">{task}</span>
                        <button
                            onClick={() => handleDeleteTask(index)}
                            className="text-red-500"
                        >
                            Delete
                        </button>
                    </li>
                ))}
            </ul>
        </div>
    );
};

export default TodoList;