react-问卷星项目(3)

项目实战

React Hooks

缓存,性能优化,提升时间效率,但是不要为了技术而优化,应该是为了业务而进行优化

内置Hooks保证基础功能,灵活配合实现业务功能,抽离公共部分,自定义Hooks或者第三方,即复用代码

React组件公共逻辑的抽离和复用

  • 之前是class组件,现在是函数组件
  • class组件:Mixing HOC render-props 来复用
  • 函数组件:使用Hooks-当前最完美的解决方法,vue3也参考这种实现方式

useState

用普通的js变量无法触发组件的更新,如下代码,方法触发了,但是数值没更新

function App() {
  let count = 0;
  function add() {
    count++;
  }
  // 列表页
  return (
    <>
      {/* <List1></List1> */}
      <div>
        <button onClick={add}>点我增加 {count}</button>
      </div>
    </>
  );
}

下面的写法能触发更新。导入useState函数,设置初始数字为0,返回的是一个数组。数组的第一个值就是当前count的值,第二个是setCount函数,就是设置新值的函数,注意必须是传入新的值,不能通过count++传入

import React, { useState } from "react";
import "./List1.css";
// import List1 from "./List1";

function App() {
  // let count = 0;
  const [count, setCount] = useState(0);
  function add() {
    // count++;
    setCount(count + 1);
  }
  // 列表页
  return (
    <>
      {/* <List1></List1> */}
      <div>
        <button onClick={add}>点我增加 {count}</button>
      </div>
    </>
  );
}

export default App;
state

一个组件的独特记忆

  • props是父组件传递过来的信息
  • state是组件内部的状态信息,不对外
  • state变化触发组件更新,重新渲染rerender
  • 特点:
    1. 异步更新,比如将添加数字抽出为组件,并在每一次点击后打印出来,会发现打印出来的数值是点击前的内容,如图所示。
      1. // stateDemo组件
        import React, { FC, useState } from "react";
        const Demo: FC = () => {
          const [count, setCount] = useState(0);
          function add() {
            // count++;
            // setCount(count + 1);
            // 上下两个写法一致,都是异步更新
            setCount((count) => count + 1);
            console.log(count);
          }
          return (
            <>
              {/* <List1></List1> */}
              <div>
                <button onClick={add}>点我增加 {count}</button>
              </div>
            </>
          );
        };
        export default Demo;
      2.                ​​​​​​
      3. 如果一个变量不用jsx显示,就不需要用state来管理。比如设置一个变量name,页面上并不需要展示这个变量,但是每次方法的时候会调用setState来设置name,而setState只要改变就会触发页面更新,这就导致不需要的变量触发了页面的更新。这种情况下用useRef
    2. 可能会被合并,state异步更新,相同的内容执行的时候每次传入的都是最新的值,无论多少次被更新都是执行的相同步骤,导致结果应该为5的倍数却还是123这样子增加,用下面函数更新的方式可以解决合并问题
      1. // stateDemo组件
        import React, { FC, useState } from "react";
        const Demo: FC = () => {
          const [count, setCount] = useState(0);
          function add() {
            // count++;
            // setCount(count + 1); 这个多次执行会导致合并
            setCount((count) => count + 1);
            setCount((count) => count + 1);
            setCount((count) => count + 1);
            setCount((count) => count + 1);
            console.log(count);
          }
          return (
            <>
              {/* <List1></List1> */}
              <div>
                <button onClick={add}>点我增加 {count}</button>
              </div>
            </>
          );
        };
        export default Demo;
    3. 不可变数据(重要)

      1. 不修改state的值,而是传入一个新的值。下列代码中只修改了age,其他属性使用解构语法获得,即解构这个数据对象,未修改的数据保持不变

      2. import React, { FC, useState } from "react";
        const Demo: FC = () => {
          const [userInfo, setUserInfo] = useState({ name: "双", age: 20 });
        
          // function changeAge() {
          //   setUserInfo({
          //     // 解构语法
          //     ...userInfo,
          //     age: 21,
          //   });
          // }
        
          function addItem() {
            // 不能使用list.push,因为不可变数据,要传入新值而不是改变state
            // concat返回的是一个新数组,push返回的不是
            setList(List.concat("z"));
            setList([...List, "z"]);
          }
          const [List, setList] = useState(["x", "y"]);
        
          return (
            <div>
              <h2>state不可变数据</h2>
              {/* <div>{JSON.stringify(userInfo)}</div>
              <button onClick={changeAge}></button> */}
              <div>{JSON.stringify(List)}</div>
              <button onClick={addItem}>add item</button>
            </div>
          );
        };
        export default Demo;
    4. 实现增删改,因为抽离出了子组件,增删改需要通过父组件触发相应的操作,涉及到一个状态提升的概念,即数据源在父组件中,子组件中只需要执行传递过来的命令,显示数据即可。

      1. 以下是子组件中的代码,基本思想是面向对象,抽离出一个列表类,因为子组件被抽出所以对子组件进行操作的时候需要通知父组件,自己删除自己不合适

      2. // 子组件 uestionCard
        import React, { FC } from "react";
        import "./QuestionCard.css";
        type PropsType = {
          id: string;
          title: string;
          isPublished: boolean;
          // 问号表示这个属性可写可不写,跟flutter语法相似
          deletQuestion?: (id: string) => void;
          pubQuestion?: (id: string) => void;
        };
        
        const QuestionCard: FC<PropsType> = (props) => {
          const { id, title, isPublished, deletQuestion, pubQuestion } = props;
          function pub(id: string) {
            pubQuestion && pubQuestion(id);
          }
          function del(id: string) {
            // 与运算符,前一个为true才去执行后一个判断条件
            deletQuestion && deletQuestion(id);
          }
          return (
            <div key={id} className="list-item">
              <strong>{title}</strong>
              <br />
              {/* {条件判断} */}
              {isPublished ? (
                <span style={{ color: "green" }}>已发布</span>
              ) : (
                <span>未发布</span>
              )}
              <button
                onClick={() => {
                  pub(id);
                }}
              >
                发布问卷
              </button>
              <button
                onClick={() => {
                  del(id);
                }}
              >
                删除问卷
              </button>
            </div>
          );
        };
        
        export default QuestionCard;
        
      3. 以下是父组件的代码,在父组件中定义对列表元素的增删改后将相应的方法传递给子元素,并在子组件中进行调用
      4. import React, { FC, useState } from "react";
        import QuestionCard from "./ListCard/QuestionCard";
        const List2: FC = () => {
          const [questionList, setQuestionList] = useState([
            { id: "q1", title: "问卷1", isPublished: true },
            { id: "q2", title: "问卷2", isPublished: false },
            { id: "q3", title: "问卷3", isPublished: false },
            { id: "q4", title: "问卷4", isPublished: false },
          ]);
        
          // 异步更新所以设置为5
          const [count, setCount] = useState(5);
        
          function deletQuestion(id: string) {
            // 不可变数据
            setQuestionList(
              // 返回true是保存,false就是删除,filter返回的是一个过滤后的新数组
              questionList.filter((que) => {
                if (que.id == id) return false;
                else return true;
              }),
            );
          }
        
          function pubQuestion(id: string) {
            setQuestionList(
              // 返回的同样是新的数组
              questionList.map((que) => {
                if (que.id !== id) return que;
                return {
                  ...que,
                  isPublished: true,
                };
              }),
            );
          }
        
          function add() {
            setCount((count) => count + 1);
            setQuestionList(
              questionList.concat({
                id: "q" + count,
                title: "问卷" + count,
                isPublished: false,
              }),
            );
          }
        
          return (
            <div>
              <h1>问卷列表页2</h1>
              <div>
                {questionList.map((question) => {
                  const { id, title, isPublished } = question;
                  return (
                    <QuestionCard
                      key={id}
                      id={id}
                      title={title}
                      isPublished={isPublished}
                      deletQuestion={deletQuestion}
                      pubQuestion={pubQuestion}
                    />
                  );
                })}
              </div>
              <div>
                <button onClick={add}>新增问卷</button>
              </div>
            </div>
          );
        };
        export default List2;

immer

出现背景,state是不可变数据,并且state操作成本比较高,有很大的不稳定性

  • 执行相应的下载指令

npm install immer

  • vsc上安装相应的识别插件 Code Spell Checker (可选)
  • 以下代码为immer使用,和state做比较
  • // 更换年龄,对象单属性
    import React, { FC, useState } from "react";
    import { produce } from "immer";
    const Demo: FC = () => {
      const [userInfo, setUserInfo] = useState({ name: "双", age: 20 });
    
      function changeAge() {
        // setUserInfo({
        //   // 解构语法
        //   ...userInfo,
        //   age: 21,
        // });
        setUserInfo(
          produce((item) => {
            item.age = 21;
          }),
        );
      }
    
      return (
        <div>
          <h2>immer可变数据</h2>
          <div>{JSON.stringify(userInfo)}</div>
          <button onClick={changeAge}>点击更换年龄</button>
        </div>
      );
    };
    export default Demo;
    
    // 更换列表对象的属性
    import React, { FC, useState } from "react";
    import { produce } from "immer";
    const Demo: FC = () => {
      function addItem() {
        // 不能使用list.push,因为不可变数据,要传入新值而不是改变state
        // concat返回的是一个新数组,push返回的不是
        // setList(List.concat("z"));
        // setList([...List, "z"]);
        setList(
          produce((item) => {
            item.push("z");
          }),
        );
      }
      const [List, setList] = useState(["x", "y"]);
    
      return (
        <div>
          <div>{JSON.stringify(List)}</div>
          <button onClick={addItem}>add item</button>
        </div>
      );
    };
    export default Demo;
  • 使用immer重构问卷列表

  • import React, { FC, useState } from "react";
    import { produce } from "immer";
    import QuestionCard from "./ListCard/QuestionCard";
    const List2: FC = () => {
      const [questionList, setQuestionList] = useState([
        { id: "q1", title: "问卷1", isPublished: true },
        { id: "q2", title: "问卷2", isPublished: false },
        { id: "q3", title: "问卷3", isPublished: false },
        { id: "q4", title: "问卷4", isPublished: false },
      ]);
    
      // 异步更新所以设置为5
      const [count, setCount] = useState(5);
    
      function deletQuestion(id: string) {
        // 不可变数据
        // setQuestionList(
        //   // 返回true是保存,false就是删除,filter返回的是一个过滤后的新数组
        //   questionList.filter((que) => {
        //     if (que.id == id) return false;
        //     else return true;
        //   }),
        // );
        // 更换为immer的方法
        setQuestionList(
          produce((item) => {
            // 找到对应的id在列表中的位置
            const index = item.findIndex((q) => q.id === id);
            // 在原数组上进行修改使用splice即可
            item.splice(index, 1);
          }),
        );
      }
    
      function pubQuestion(id: string) {
        // setQuestionList(
        //   // 返回的同样是新的数组
        //   questionList.map((que) => {
        //     if (que.id !== id) return que;
        //     return {
        //       ...que,
        //       isPublished: true,
        //     };
        //   }),
        // );
        setQuestionList(
          produce((item) => {
            const q = item.find((i) => i.id === id);
            if (q) q.isPublished = !q.isPublished;
          }),
        );
      }
    
      function add() {
        // setCount((count) => count + 1);
        // setQuestionList(
        //   questionList.concat({
        //     id: "q" + count,
        //     title: "问卷" + count,
        //     isPublished: false,
        //   }),
        // );
        // 替换为immer
        setCount(
          produce((item) => {
            // 这里要返回return不然只增加到5就不递增了,暂不清楚原因
            return (item += 1);
          }),
        );
        setQuestionList(
          produce((item) => {
            item.push({
              id: "q" + count,
              title: "问卷" + count,
              isPublished: false,
            });
          }),
        );
      }
    
      return (
        <div>
          <h1>问卷列表页2</h1>
          <div>
            {questionList.map((question) => {
              const { id, title, isPublished } = question;
              return (
                <QuestionCard
                  key={id}
                  id={id}
                  title={title}
                  isPublished={isPublished}
                  deletQuestion={deletQuestion}
                  pubQuestion={pubQuestion}
                />
              );
            })}
          </div>
          <div>
            <button onClick={add}>新增问卷</button>
          </div>
        </div>
      );
    };
    export default List2;

useEffect

当一个组件渲染完成或者当某个state更新时,加载一个Ajax网络请求,使用useEffect可以实现。state实现不了,因为如果在某个组件中写上需要执行的语句,会导致任何state更新都会触发组件的更新(重新执行函数),不满足初次更新或者某个特定条件更新的两个条件

副作用:本来组件只需要执行完函数即可,但是现在却要求在特定的时间或者满足特定的条件下实现函数,即副作用

数组传入的是依赖项,不设置即为无依赖,即在第一次更新后,后续不会触发,有设置则相应的依赖项改变时会触发这个函数。数组中可以添加多个依赖项,只要其中一个被触发就会执行这个函数

import React, { FC, useState, useEffect } from "react";
import { produce } from "immer";
import QuestionCard from "./ListCard/QuestionCard";
const List2: FC = () => {
  // 一传函数,二传数组
  useEffect(() => {
    console.log("加载Ajax网络请求");
  }, []);
}

子组件销毁时的调用,能打印出来销毁,但是不知道为什么视频里打印出来单个,但是我打印的时候有其他几个子组件的销毁状态

// QuestionCard
  
useEffect(() => {
    console.log("组件挂载");
    return () => {
      console.log("组件销毁" + id);
    };
  });

解决打印两次的问题。如图所示,为什么会显示打印两次,是因为组件自销毁了一次。从react18开始,useEffect在开发环境下会执行两次,目的是模拟组件创建,销毁,再创建的流程,方便及早发现问题。发布版本就不会有这个问题

通过下列指令发布

npm run build

执行完毕后在build目录下可以查看到项目的相关目录和内容,再通过以下指令运行服务器查看打包后的项目,生产环境下useEffect只执行一次

http-server

npm install -g serve

serve -s build

其他内置Hooks

useRef
  • 一般用于操作DOM
import React, { FC, useRef } from "react";
const Demo: FC = () => {
  // 初始化传入默认值为null,因为初始化的时候页面还没创建
  // ts泛型
  const inputRef = useRef<HTMLInputElement>(null);
  function selectInput() {
    // 当前指向
    const inputElm = inputRef.current;
    if (inputElm) inputElm.select();
  }
  return (
    <div>
      {/* 通过ref指向DOM节点 */}
      <input ref={inputRef} defaultValue="hello"></input>
      <button onClick={selectInput}>选中input</button>
    </div>
  );
};
export default Demo;
  • 可传入普通的JS变量,但不会触发rerender(渲染),比如下面这个例子,打印出来的数值改变了,但是界面上展示的数值没有改变,state修改会触发rerender,想要显示出来就用state,只是保存结果就是用ref
const Demo: FC = () => {
  const nameRef = useRef("双"); // 不是DOM节点而是普通的JS变量
  function changeName() {
    nameRef.current = "双月亮";
    console.log(nameRef.current);
  }
  return (
    <>
      <p>name{nameRef.current}</p>
      <button onClick={changeName}>change name</button>
    </>
  );
};
  • 要和vue3 ref区分开,vue3的ref是用于响应式监听的 

useMemo

函数组件,每次state更新都会重新执行函数,useMemo可以缓存数据,不用每次执行函数都重新生成,可用于计算量较大的场景,提高缓存性能

import React, { FC, useMemo, useState } from "react";
const Demo: FC = () => {
  console.log("demo");
  const [num1, setNum1] = useState(10);
  const [num2, setNum2] = useState(20);
  const [text, setText] = useState("hello");
  // 跟useEffect相似
  const sum = useMemo(() => {
    console.log("gen sum");
    return num1 + num2;
  }, [num1, num2]);

  return (
    <>
      <p>{sum}</p>
      <div>
        <p>{num1}</p>
        <button
          onClick={() => {
            setNum1(num1 + 1);
          }}
        >
          add num1
        </button>
      </div>
      <div>
        <p>{num2}</p>
        <button
          onClick={() => {
            setNum2(num2 + 1);
          }}
        >
          add num2
        </button>
      </div>
      <div>
        {/* form组件,受控组件 */}
        <input onChange={(e) => setText(e.target.value)} value={text} />
      </div>
    </>
  );
};
export default Demo;

useMemo依赖num1和num2,两个数字变化的时候会触发相应的函数,即重新计算sum,而text不是依赖项,所以text改变的时候不会重新计算sum。

可以把useMemo作为性能优化的手段,但不要把它当成语义上的保证,即不要认为每次使用都会真正的缓存,因为Memo可能会选择性的缓存或者遗忘一个值,然后下次再缓存

useCallback

作用和useMemo一致,也是用于缓存,准们用于缓存函数,可以理解为useMemo的语法糖,下列代码中的两个方法比较类似,fn1是什么时候加载什么时候打印,fn2只有相关依赖改变的时候才会触发

import React, { FC, useState, useCallback } from "react";
const Demo: FC = () => {
  const [text, setText] = useState("hello");
  const fn1 = () => console.log("fn1", text);
  const fn2 = useCallback(() => {
    console.log("fn2", text);
  }, [text]);
  return (
    <>
      <div>
        <button onClick={fn1}>fn1</button> &nbsp;{" "}
        <button onClick={fn2}>fn2</button>
      </div>
      {/* form组件,受控组件,即输入的时候会导致页面数值的变化,类似vue的双向数据绑定 */}
      <input onChange={(e) => setText(e.target.value)} value={text} />
    </>
  );
};
export default Demo;

自定义hooks

抽离出来的这个组件定义为ts组件即可

// ts文件即可,因为没有JSX片段,即div等标签
import { useEffect } from "react";
function useTitle(title: string) {
  useEffect(() => {
    document.title = title;
  }, []);
}
export default useTitle;

监听鼠标事件

import { useState, useEffect } from "react";
// 获取鼠标位置
function useMouse() {
  const [x, setX] = useState(0);
  const [y, setY] = useState(0);
  // "这个组件",即谁引用就指向谁
  useEffect(() => {
    const mouseMoveHandler = (event: MouseEvent) => {
      setX(event.clientX);
      setY(event.clientY);
    };
    // 监听鼠标事件
    window.addEventListener("mousemove", mouseMoveHandler);
    // 组件销毁时一定要解绑DOM事件,不然可能会出现内存泄漏问题
    // 解绑的时候需要和绑定的时候的函数相同
    return () => {
      window.removeEventListener("mousemove", mouseMoveHandler);
    };
  }, []);
  return { x, y };
}
export default useMouse;

模拟异步加载数据

import { useState, useEffect } from "react";
function getInfo(): Promise<string> {
  // 模拟异步信息
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(Date.now().toString());
    }, 1500);
  });
}

const useGetInfo = () => {
  const [loading, setLoading] = useState(true);
  const [info, setInfo] = useState("");
  useEffect(() => {
    getInfo().then((info) => {
      setLoading(false);
      setInfo(info);
    });
  }, []);

  return { loading, info };
};
export default useGetInfo;

第三方Hooks
  • ahooks国内流行 官网
  • react-hooks国外流程

使用下列指令下载ahooks

npm install ahooks --save

下载完后看官网的文档选择调用即可,官网有相关的讲解

使用规则

  • 必须用useXxx格式命名
  • 只能在两个地方调用Hook(组件内,其他Hook内)
  • 必须保证每次调用顺序一致(不能把hooks放在for if内部,只能放在函数第一层,可以在hooks内部加逻辑判断)

闭包陷阱

当异步函数获取state时,可能不是当前最新的state,可使用useRef解决

  • 对闭包问题还有点疑惑,通过文心一言描述一下,下面的代码中,setTimeout 函数在调用时捕获了 count 变量的当前值(在其调用时的值)。由于 setTimeout 是异步执行的,它在 3 秒后执行时,并不会自动获取 count 的最新值。这就是闭包的作用:它保存了函数定义时的环境(在这里是 count 的值),
import React, { FC, useState, useEffect, useRef } from "react";
const Demo: FC = () => {
  const [count, setCount] = useState(0);
  function add() {
    setCount(count + 1);
  }
  function alertFn() {
    setTimeout(() => {
      alert(count);
    }, 3000);
  }
  return (
    <>
      <p>闭包陷阱</p>
      <div>
        <span>{count}</span>
        <button onClick={add}>add</button>
        <button onClick={alertFn}>alert</button>
      </div>
    </>
  );
};

export default Demo;

上述问题就是当异步函数获取state时,可能不是当前最新的state,接下来使用useRef解决,本质是因为count是一个值类型,而ref是引用类型

import React, { FC, useState, useEffect, useRef } from "react";
const Demo: FC = () => {
  const [count, setCount] = useState(0);
  const countRef = useRef(0);
  useEffect(() => {
    countRef.current = count;
  }, [count]);
  function add() {
    setCount(count + 1);
  }
  function alertFn() {
    setTimeout(() => {
      // alert(count);
      alert(countRef.current);
    }, 3000);
  }
  return (
    <>
      <p>闭包陷阱</p>
      <div>
        <span>{count}</span>
        <button onClick={add}>add</button>
        <button onClick={alertFn}>alert</button>
      </div>
    </>
  );
};

export default Demo;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/886449.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Kubernetes】常见面试题汇总(五十四)

目录 120.创建 init C 容器后&#xff0c;其状态不正常&#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题&#xff0c;即 “ 汇总&#xff08;一&#xff09;~&#xff08;二十二&#xff09;” 。 题目 69-113 属于【Kubernetes】的生产…

Swagger配置且添加小锁(asp.net)(笔记)

此博客是基于 asp.net core web api(.net core3.1)框架进行操作的。 一、安装Swagger包 在 NuGet程序包管理中安装下面的两个包&#xff1a; swagger包&#xff1a;Swashbuckle.AspNetCore swagger包过滤器&#xff1a;Swashbuckle.AspNetCore.Filters 二、swagger注册 在…

开源 AI 智能名片 O2O 商城小程序与抖音:品牌传播的新机遇与挑战

摘要&#xff1a;本文探讨了开源 AI 智能名片 O2O 商城小程序在品牌传播中的作用&#xff0c;以及与抖音平台相结合所带来的机遇与挑战。分析了抖音如何利用算法适配品牌调性为门店找到目标消费者&#xff0c;放大品牌势能&#xff0c;同时阐述了新品牌在抖音上进行品牌传播的优…

C++平台跳跃游戏

目录 开头程序Game.cpp源文件Player.h头文件Player.cpp源文件 程序的流程图程序游玩的效果下一篇博客要说的东西 开头 大家好&#xff0c;我叫这是我58。 程序 Game.cpp源文件 #include <iostream> #include "Player.h" using namespace std; void printma…

[数据集][目标检测]电力场景防震锤缺陷检测数据集VOC+YOLO格式705张1类别

重要说明&#xff1a;防震锤缺陷图片太难找&#xff0c;数据集里面存在大量单一场景图片&#xff0c;请仔细查看图片预览谨慎下载&#xff0c;此外数据集均为小目标检测&#xff0c;如果训练map偏低属于正常现象 数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径…

19.第二阶段x86游戏实战2-寻找寻路call

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

C++容器之list基本使用

目录 前言 一、list的介绍&#xff1f; 二、使用 1.list的构造 2.list iterator的使用 3.list capacity &#x1f947; empty &#x1f947;size 4.list element access &#x1f947; front &#x1f947; back 5.list modifiers &#x1f947; push_front &#x1f947; po…

VMware ESXi 8.0U3b macOS Unlocker OEM BIOS 2.7 Dell HPE 定制版 9 月更新发布

VMware ESXi 8.0U3b macOS Unlocker & OEM BIOS 2.7 Dell HPE 定制版 9 月更新发布 VMware ESXi 8.0U3b macOS Unlocker & OEM BIOS 2.7 标准版和厂商定制版 ESXi 8.0U3 标准版&#xff0c;Dell (戴尔)、HPE (慧与)、Lenovo (联想)、IEIT SYSTEMS (浪潮信息)、Cisco …

Xshell7下载及服务器连接

一、Xshell-7.0.0164p、Xftp 7下载 1.1、文件下载 通过网盘分享的文件&#xff1a;xshell 链接: https://pan.baidu.com/s/1qc0CPv4Hkl19hI9tyvYZkQ 提取码: 5snq –来自百度网盘超级会员v2的分享 1.2、ip连接 下shell和xftp操作一样&#xff1a;找到文件—》新建—》名称随…

HTML增加文本复制模块(使用户快速复制内容到剪贴板)

增加复制模块主要是为了方便用户快速复制内容到剪贴板&#xff0c;通常在需要提供文本信息可以便捷复制的网页设计或应用程序中常见。以下是为文本内容添加复制按钮的一个简单实现步骤&#xff1a; HTML结构&#xff1a; 在文本旁边添加一个复制按钮&#xff0c;例如 <butto…

【C++】set容器和map容器的基本使用

一、序列式容器和关联式容器 1、STL中的部分容器如&#xff1a;string、vector、list、deque、array、forward_list等&#xff0c;这些容器统称为序列式容器&#xff0c;因为逻辑结构为线性序列的数据结构&#xff0c;两个位置存储的值之间一般没有紧密的关联关系&#xff0c;…

第L2周:机器学习|线性回归模型 LinearRegression:2. 多元线性回归模型

本文为365天深度学习训练营 中的学习记录博客原作者&#xff1a;K同学啊 任务&#xff1a; ●1. 学习本文的多元线形回归模型。 ●2. 参考文本预测花瓣宽度的方法&#xff0c;选用其他三个变量来预测花瓣长度。 一、多元线性回归 简单线性回归&#xff1a;影响 Y 的因素唯一&…

1、Spring Boot 3.x 集成 Eureka Server/Client

一、前言 基于 Spring Boot 3.x 版本开发&#xff0c;因为 Spring Boot 3.x 暂时没有正式发布&#xff0c;所以很少有 Spring Boot 3.x 开发的项目&#xff0c;自己也很想了踩踩坑&#xff0c;看看 Spring Boot 3.x 与 2.x 有什么区别。自己与记录一下在 Spring Boot 3.x 过程…

Linux ssh 免密登录配置

参考资料 ~/.ssh/configについて~/.ssh/configを使ってSSH接続を楽にする.ssh/configファイルでSSH接続を管理する 目录 一. 密钥生成1.1 生成工具1.1.1 OpenSSH1.1.2 Git 1.2 生成命令1.3 注意事项1.4 解决路径中的用户名乱码 二. 将公钥配置到目标服务&#xff0c;免密登录2…

如何在 Windows 10 上恢复未保存/删除的 Word 文档

您是否整夜都在处理重要的 word 文件&#xff0c;但忘记保存它&#xff1f;这篇文章是给你的。在这里&#xff0c;我们将解释如何恢复未保存的 word 文档。除此之外&#xff0c;您还将学习如何恢复已删除的 word 文档。 从专业人士到高中生&#xff0c;每个人都了解丢失重要 W…

从HarmonyOS Next导出手机照片

1&#xff09;打开DevEco Studio开发工具 2&#xff09;插入USB数据线&#xff0c;连接手机 3&#xff09;在DevEco Studio开发工具&#xff0c;通过View -> Tool Windows -> Device File Browser打开管理工具 4&#xff09;选择storage -> cloud -> 100->fi…

JDBC 概述

JDBC 概述 JDBC的基本概念与功能JDBC的工作原理JDBC的组件与类JDBC的类型与特性JDBC的应用场景 JDBC&#xff08;Java Database Connectivity&#xff09;即Java数据库连接&#xff0c;是Java编程语言用于与数据库进行连接和操作的API&#xff08;应用程序编程接口&#xff09;…

Linux:深入理解冯诺依曼结构与操作系统

目录 1. 冯诺依曼体系结构 1.1 结构分析 1.2 存储结构分布图 2. 操作系统 2.1 概念 2.2 如何管理 2.3 什么是系统调用和库函数 1. 冯诺依曼体系结构 1.1 结构分析 不管是何种计算机&#xff0c;如个人笔记本电脑&#xff0c;服务器&#xff0c;都是遵循冯诺依曼结构。…

注册安全分析报告:科研诚信查询平台无验证方式导致安全隐患

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

【Linux】进程管理:状态与优先级调度的深度分析

✨ 山海自有归期&#xff0c;风雨自有相逢 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;Linux—登神长阶 ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1…