React开发必知必会的Hooks

news2024/12/25 12:37:56

文章目录

  • 前言
    • 1、React的组件创建方式
    • 2、什么是Hook?
    • 3、Hook总的使用规则
  • 一、useState
  • 二、useRef
  • 三、useEffect
  • 四、useLayoutEffect
  • 五、useReducer
  • 六、useContext
  • 七、memo与useMemo、useCallback
    • 1、memo
    • 2、useMemo
    • 3、useCallback
    • 4、三者区别
  • 八、useImperativeHandle


前言

Hooks是 React 16.8 版本引入的一项特性,它允许在函数式组件中使用状态和其他 React 特性,而不需要使用类组件。

1、React的组件创建方式

1)类式组件

能够对状态的管理与切换进行操控,但是在简单的页面中使用类式组件会使代码显得很重,并且状态逻辑难以复用。

虽然可以使用 render props (渲染属性)和高阶组件进行优化,但这两种方式都会将原来的组件用一个容器包裹起来,形成层级嵌套,代码冗余。而且在类式组件中,this的指向经常容易引起问题。

2)函数式组件

没有了类式组件中的状态,没有生命周期,更不存在this,转而代之的则是一系列的hook。

2、什么是Hook?

Hook就是钩子,作用是把某个目标结果钩到某个可能会变化的数据源或者事件源上,那么当被钩到的数据或事件发生变化时,产生这个目标结果的代码会重新执行,产生更新后的结果。

React中文官网:https://react.docschina.org/reference/react/hooks

3、Hook总的使用规则

  • 只能在函数最外层调用 hook,即:不要在循环、条件判断或者子函数中调用。这是为了确保 Hook在每一次渲染中都按照同样的顺序被调用。

  • 只能在React函数组件或自定义 hook中使用。这是为了确保组件的状态逻辑在代码中清晰可见。

PS: 本文React的版本:
在这里插入图片描述

一、useState

1、作用: 允许我们在函数组件内部声明并管理状态(state),即useState 相当于我们在原生 JS 中定义变量。

2、语法:const [initialState, setInitialState] = useState(initialState);

  • useState(initialState)有一个初始化值作为参数,initialState可以是任意值。

  • 返回包含两个值数组,第一个是值,第二个是set方法。

3、注意事项:

  • useState只能用于函数组件,可以有多个;类组件是用setState,且一个类只能有一个setState。

  • useState不能在循环、条件或嵌套函数中调用。

  • 当useState里面的状态为一个对象时,useState是不会进行局部更新的,而是将修改后的内容将之前的内容进行覆盖。

  • useState 是一个异步操作,它并不会立即更新状态。

也就是说,在函数组件中调用 useState 更新状态时,React 会将新的状态安排进下一次渲染,并在之后的某个时候才会执行更新,这就导致在更新状态后立即访问该状态可能会得到之前的值,而不是最新的值。

【比如在下面示例中setCount后,直接获取count,count的值是不变的】

5、解决数据更新办法:先使用useRef进行存储数据,再使用useEffect监听数据变化,并进行更新。

import { useState, useRef, useEffect } from 'react';

const App = () => {
  // 初始化状态和对应的更新函数
  const [count, setCount] = useState(1);
  
  const countRef = useRef();
  
  // 当需要更新stateValue时,setCount可以直接传递新的状态值
  const handleUpdate = (newCount: number) => {
    setCount(newCount);
  };
  
  // 监听count值实时更新
  useEffect(() => {
    countRef.current = info;
  }, [count]);
  
  // 渲染count值
  return <div>{count}</div>
}

6、自定义模拟源码实现useState方法

// 每次更新时,函数组件会被重新调用,为了新值被记录而不是一直被重新赋上initialState,需要将其提到外部作用域声明
// _state定义为数组是为了解决多次调用的问题,react为了保证useState的执行顺序,还规定了不能在循环、条件或嵌套函数中调用
let _state = [], _index = 0;

function useState(initialState) {
  let curIndex = _index; // 记录当前操作的索引
  
  if (typeof initialState === "function") {
    initialState = initialState();
  }
  
   // 用hasOwnProperty判断当前索引是否被创建,如果有,说明已经对这个state赋初始值了,如果没有,则说明是新创建的,需要使用initialState赋初始值。
  _state[curIndex] = !_state.hasOwnProperty(curIndex) ? initialState : _state[curIndex]; 
 
  // 定义回调函数
  const setState = newState => {
    if (typeof newState === "function") {
      newState = newState(_state[curIndex]);
    }
    // 使用Object.is来比较_state[curIndex]是否变化,若无,则跳过更新
    if (Object.is(_state[curIndex], newState)) return; 
    _state[curIndex] = newState;
    // 简单的更新根视图
    ReactDOM.render(<App />, rootElement);
    _index = 0; // 每更新一次都需要将_index归零,才不会不断重复增加_state
  };
  
  _index += 1; // 下一个操作的索引
  
  return [_state[curIndex], setState];
}

对比react源码中:_state 其实对应 React 的 memoizedState ,而 _index 实际上是利用了链表。

二、useRef

1、作用:用于获取真的DOM节点,返回一个对象,对象里面有current属性存放着获取到的原生DOM对象。

2、语法:const inputRef = useRef(null);

3、使用示例:

import React, { useRef } from 'react'

function App() {
    const inputRef = useRef(null)
    const handleClick = () => {
        console.log(inputRef.current)
    }
    return (
        <div className="App">
            <input ref={inputRef} type="text" />
            <button onClick={handleClick}>获取DOM节点</button>
        </div>
    )
}

export default App

4、注意事项:

  • useRef虽然可以获取到DOM对象,但是建议轻易不要这么做,如果必须要获取,也尽量是读取而不要修改,如果必需要修改也要尽量减少修改的次数,总之能不用就不用。
  • 自己创建的对象组件每次渲染时都会重新创建一个新的对象,而通过useRef()创建的对象可以确保组件每次的重渲染获取到的都是相同的对象。

三、useEffect

1、作用:可以检测数据的更新,主要用于处理副作用操作,比如:订阅数据、手动更改 DOM、设置定时器、添加事件监听器等,并且可以指定在什么条件下进行清理。

2、副作用

  • 含义:指一段和当前执行结果无关的代码,比如说要修改函数外部的某个变量,要发起一个请求有两个参数。

  • 副作用操作:数据获取,设置订阅以及手动更改 React 组件中的 DOM。

3、语法:useEffect(() => {}, [param]);

参数说明:

  • 第一个参数为要进行的异步操作;

  • 第二个参数为一个数组,里面为要检测的依赖项,只要数组里面的依赖项发生了变化,useEffect就会执行。
    当第二个参数不传时,在每次组件渲染时useEffect都会执行,类似于 componentDidUpdate 生命周期钩子。第一个参数返回的函数就相当于componentWillUnmont

4、特别说明:

  • 默认情况下,React 会在每次渲染后调用useEffect,包括第一次渲染:DOM渲染》调用副作用函数》页面展示最新数据信息。
  • useEffect 可以通过返回一个函数来指定如何清除相关的副作用操作,便于将添加和移除订阅的逻辑放在一起。
  • 重新渲染:默认都会生成新的effect,替换掉之前的。
  • 清除阶段:在每次重新渲染时都会执行,而不是只在卸载组件的时候执行一次。

5、使用示例:

import { useEffect } from 'react';

function App() {
  // 1、无依赖项,会一值执行
  useEffect(() => {
  	// 操作
  });
  
  // 2、依赖项为空,组件初始化会执行一次
  useEffect(() => {
  	// 操作
  },[]);
  
  // 3、依赖于某个变量或函数,在依赖项发生变化后触发
  useEffect(() => {
    // 在组件渲染后执行副作用操作

    // 返回一个清理函数(可选)
    return () => { 
     // 在组件卸载或重新渲染之前执行清理操作, 该清理函数将在组件卸载或重新渲染之前执行
    };
    
  }, [/* 依赖项数组 */]);

  return (<div></div>);
}

6、注意事项:

  • 数据获取和订阅:可以在 useEffect 中进行异步操作,如:发起网络请求获取数据或订阅事件,但要确保在清理函数中取消订阅或中断请求,以避免内存泄漏。

  • 清理函数的使用:如果副作用函数需要进行清理操作,如:取消订阅或清除定时器,要在副作用函数中返回一个清理函数,该清理函数将在组件卸载或重新渲染之前执行。

  • 异步操作和更新状态:在副作用函数中进行异步操作时,要确保正确处理状态的更新。可以使用函数式更新或通过依赖项数组传入更新的状态。

  • 在开发的时候发现,当 useEffect 第二个参数为空数组时,明明是在组件挂载之后执行一次,但是会发现在里面打印内容时,会有两次输出。官方文档给出了相应的解释,这种情况只在开发环境中才如此,是 react 方便使用者在开发环境调试。
    对应的解决办法: 根据实际业务场景去解决,有清除函数时要加上,它的依赖项也很重要,有些没有必要监听的依赖,要从Effect中独立出来,变为非响应式的值。

四、useLayoutEffect

1、作用:与 useEffect 类似,但它是在 DOM 变更之后同步执行,不是在浏览器绘制之后执行。它会在浏览器布局和绘制之前同步执行回调函数。

2、使用场景:使用 useLayoutEffect 可以在浏览器布局完成后立即执行一些操作,以确保获取到最新的 DOM 布局信息,并在下一次渲染之前同步地更新 UI。如:准确地测量 DOM 元素的尺寸、位置或进行 DOM 操作。

3、示例:

import React, { useRef, useLayoutEffect } from 'react';

function MeasureElement() {
  const ref = useRef();

  useLayoutEffect(() => {
    const element = ref.current; // 在浏览器布局完成后立即执行操作
    const { width, height } = element.getBoundingClientRect(); // 获取被测量元素的宽度和高度
    console.log('Element size:', width, height); // 使用测量结果进行操作
  }, []);

  return <div ref={ref}>Measure me!</div>;
}

function App() {
  return (
    <div>
      <MeasureElement />
  	</div>
  );
}

4、注意事项:
由于 useLayoutEffect 在浏览器布局之后同步执行,因此它的执行会阻塞浏览器的渲染过程。所以,一般只有在需要同步更新 UI 或测量 DOM 元素时才使用 useLayoutEffect,避免造成性能问题。

五、useReducer

1、作用:通常用于管理具有复杂状态和行为的组件,尤其是涉及到多个状态转换的情况。类似于 Redux 中的 reducer,接收一个状态和操作函数,并返回新的状态和派发操作的函数。

2、语法:const [state, dispatch] = useReducer(reducer, initialState);

参数说明:

  • 第一个是包含状态转换逻辑的函数(reducer);
  • 第二个是初始状态。

返回值:一个包含当前状态和 dispatch 函数的数组。

3、使用示例
先定义一个reducer函数:

function reducer(state, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

然后使用reducer:

import React, { useReducer } from 'react';

// 设置初始值
const initialState = { count: 0 };

function Counter() {
  // 定义状态state和派发操作的函数dispatch
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      Count: {state.count}
			// 根据操作的类型通过调用dispatch派发操作,并由reducer函数来更新状态
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>增加</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>减少</button>
    </div>
  );
}

4、常用场景

1)计数器:可以使用 useReducer 来管理计数器的状态和操作,如:增加、减少计数等。

2)表单处理:使用 useReducer 可以更好地管理表单的状态和用户输入的操作,以及进行表单验证等复杂逻辑。

3)数据列表:当处理复杂的数据列表时,使用 useReducer 可以更好地管理数据的加载、筛选、排序等操作,以及处理分页等功能。

4、总结
useReducer 适用于需要管理复杂状态逻辑的组件,并且可以帮助组织和更新状态,以及处理相关的操作。甚至可以代替使用 useState 的方式,特别适合管理具有多个操作类型和相关状态的组件。

六、useContext

1、作用:用于在组件树中传递数据,通过组件之间的数据状态共享,避免了逐级传递props的缺陷。

2、使用说明:通过 createContext 来创建 context 对象,然后使用 context 对象上的 Procider 来提供数据,在后代组件中通过 useContext 来接收数据。

3、示例

import React, { createContext } from 'react';

const MyContext = createContext(); // 创建上下文对象

function MyContextProvider({ children }) {
  const sharedData = 'Shared Data';
  
  return (
    // 通过 MyContext.Provider提供器将共享数据sharedData传递给子组件
    <MyContext.Provider value={sharedData}>
      {children}
    </MyContext.Provider>
  );
}

在需要访问上下文数据的组件中使用 useContext

import React, { useContext } from 'react';

function App() {
  const sharedData = useContext(MyContext);

  return (
    <div> Shared Data: {sharedData} </div>
	);
}

4、注意事项

  • 使用 useContext 前,要确保已在组件树中的某个地方提供了上下文。

  • 数据更新问题:当上下文数据发生变化时,使用 useContext 的组件会自动重新渲染。即:当共享数据发生更改时,使用该上下文的所有组件都会更新。

  • 嵌套问题:React 允许上下文进行嵌套。在嵌套的情况下,使用 useContext 会获取最接近的上层提供器的值。

  • 性能问题:useContext 的默认行为是每次组件渲染时都重新计算上下文的值。这可能会导致性能问题,尤其是当上下文的值频繁变化时。为了避免不必要的重新渲染,可以使用 memo 结合 useContext 进行优化。

  • 代码耦合问题:上下文是用于共享数据的有用工具,过度使用可能导致组件之间的耦合性增加。建议在需要共享数据的组件之间仔细考虑使用上下文的合适程度。

七、memo与useMemo、useCallback

在 React 中,每当函数组件重新渲染时,函数组件的所有局部变量都会重新初始化。

如果将一个新的函数作为 prop 传递给子组件,即使这个函数具有相同的逻辑,由于它是一个新的引用,子组件可能会被重新渲染,从而可能引起性能问题。

在使用useMemo、useCallback时经常会遇到被缓存的值/函数并不是最新值,换句话说就是,useMemo、useCallback中的值并不是最新值。

因为带有缓存的作用,所以对应的内存占用会随着使用数量的增加而增加。

1、memo

memo 是一个用于优化性能的 React 高阶组件。
语法: const Test = memo(C, cb?)

参数说明:

  • 第一个参数是要被记忆的组件memo并不会对此组件进行任何更改)。C组件就是要被记忆的组件,而memo函数则可以理解成它是C组件的shouldComponentUpdate生命周期方法。

  • 第二个参数cb则是渲染C组件时所调用的回调函数,这个函数会收到当前组件的新旧state以决定本次是否重新渲染。

2、useMemo

1)、作用:用于在组件渲染过程中进行性能优化,避免不必要的计算和重复渲染。类似于useCallback但其主要用于缓存计算结果,而不是缓存回调函数。

2)、语法:useMemo(fn, dependencies);

3)、使用示例

import React, { useMemo, useState } from 'react';

function ExpensiveComponent() {
  // 假设calcExpensiveValue是一个计算非常耗时且复杂的函数
  function calcExpensiveValue() {
    // ...包含一些复杂的计算逻辑
    return Math.random();
  }

  // 使用useMemo缓存计算结果,将空数组作为依赖项传递给useMemo,确保只在组件首次渲染时执行一次计算,避免了每次渲染时都重新计算
  const expensiveValue = useMemo(() => calcExpensiveValue(), []);

  return (
    <div> Expensive Value: {expensiveValue} </div>
  );
}

function App() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <ExpensiveComponent />
    </div>
  );
}

4)、特别说明:

  • 若没有提供依赖项,useMemo 在每次渲染时都会计算新的值,若提供依赖项数组,当某个依赖项改变时才会重新计算。
  • 不要在fn函数内部执行与渲染无关的操作,如:副操作等,适合使用在其它hook中的逻辑。

5)、常见使用场景:

  • 缓存计算结果:当需要根据某些输入计算结果时,可以使用 useMemo 缓存计算结果,避免重复计算,特别适合计算量大的场景。

  • 避免不必要的重复渲染:当一个组件依赖于某个状态或属性,但这些状态或属性的变化并不会影响到组件的渲染结果,可以使用 useMemo 来缓存渲染结果,避免不必要的重复渲染。

  • 优化子组件的渲染:当将一个计算结果作为属性传递给子组件时,可以使用 useMemo 缓存计算结果,以避免在每次父组件渲染时都重新计算并传递给子组件。

  • 性能敏感的比较操作:当需要进行一些性能敏感的比较操作,如:深度比较对象或数组时,可以使用 useMemo 缓存比较结果,以避免在每次渲染时重新执行比较操作。

3、useCallback

1)作用:主要目的是性能优化用于缓存回调函数,以便在依赖项变化时避免不必要的函数重新创建。

2)语法:useCallback(fn, dependencies);

参数说明:

  • 第一个参数fn是要缓存的函数useCallback会在其依赖项发生变化时调用此函数。
  • 第二个参数 dependencies则是依赖项列表,只有依赖发生变化时,才会重新调用所传入的回调函数。

3)注意:在使用useCallback时可能会造成由于闭包问题而无法在useCallback中获取新值的问题。

// 自定义hooks:解决使用useCallback时造成的闭包问题而拿不到新值
const useEventCallback = <T extends (...args: any[]) => any>(fn: T) => {
    const ref = useRef(fn)
    useLayoutEffect(() => {
        ref.current = fn
    })
    return useCallback(((...args) => ref.current.call(window, ...args)) as T, [])
}

4、三者区别

  • memo 用于避免在父组件重新渲染时重新渲染子组件,只有在属性发生变化时重新渲染组件。

  • useMemo 用于避免在组件重新渲染时执行昂贵的计算,只有在依赖发生变化时重新计算值。

  • useCallback 用于避免在组件重新渲染时创建新的函数实例,只有在依赖发生变化时返回新的函数实例。

八、useImperativeHandle

1、作用:允许我们将特定方法向下传递到子组件。简单来说,就是可以让我们控制父组件直接调用子组件中暴露出来的方法或属性。

但其需要与 forwardRef 一起使用,forwardRef 可以将父组件传递给子组件。

2、语法:useImperativeHandle(ref, cb);

参数说明:两个参数,一个 ref 和一个提供给该 ref 的回调函数,在回调函数中定义子组件向父组件暴露出的方法或属性,并返回一个值或函数,该值或函数可以从 ref 中访问。

3、示例:

import React, { forwardRef, useImperativeHandle } from 'react';

// 子组件
const Child = forwardRef((props, ref) => {
  
  // 创建一个childRef对象,以便可以在回调函数中使用
  const childRef = useRef(); 
  
  // 定义focusChild方法和someValue属性,并将其返回给父组件
  useImperativeHandle(ref, () => ({
    focusChild: () => {
      childRef.current.focus();
    },
    someValue: '子组件暴露出来的属性',
  }));
  
  return <input type="text" ref={childRef} />;
});

const Parent = () => {
  const childRef = useRef();
  
  const handleClick = () => {
    childRef.current.focusChild && childRef.current.focusChild();
  };
  
  return (
    <div>
      <Child ref={childRef} />
      <button onClick={handleClick}>点击获取焦点</button>
    </div>
  );
};
export default Parent;

学无止境!关于React的Hooks就暂时介绍这么多啦,更多的建议看看 官网 哦~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++重新入门-C++数据类型

目录 1.基本的内置类型 2.typedef 声明 3.枚举类型 4.类型转换 使用编程语言进行编程时&#xff0c;需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着&#xff0c;当您创建一个变量时&#xff0c;就会在内存中保留一些空间。 您可能需要存储…

网站为什么要用CND?

CDN对于网站来说至关重要&#xff0c;CDN对网站的重要性主要体现在可以提升用户体验、提高网站安全性、减轻服务器负担、提高SEO排名等&#xff0c;还可以为网站节省带宽成本。因此&#xff0c;选择一个性能好、速度快的CDN是很有必要的。 CDN对于现代网站来说是不可或缺的&am…

【算法分析与设计】无重复的最长子串

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 示例 1: 输入: s "abcabcbb" 输…

redis下载与安装教程(centos下)

文章目录 一&#xff0c;redis下载1.1上传到linux服务器上 二&#xff0c;redis安装2.1 安装依赖2.2 解压包2.3 编译并安装2.4 指定配置启动2.5 设置redis开机自启 一&#xff0c;redis下载 官网&#xff1a; https://redis.io1.1上传到linux服务器上 我用filezila上传到/us…

【前端web入门第四天】02 CSS三大特性+背景图

文章目录: 1. CSS三大特性 1.1继承性 1.2 层叠性 1.3 优先级 1.3.1 优先级1.3.2 优先级-叠加计算规则 2. 背景图 2.1 背景属性2.2 背景图2.3 背景图的平铺方式2.4 背景图位置2.5 背景图缩放2.6 背景图固定2.7 背景复合属性 1. CSS三大特性 1.1继承性 什么是继承性? 子级默…

华大基因PMseq病原微生物高通量基因检测产品耐药数据库持续

23年肺炎支原体感染的患者数量持续上升&#xff0c;与此同时&#xff0c;由肺炎支原体感染引发的住院患者数量也在迅速增加。这就导致近期儿科和发热门诊都处于床位爆满状态。而在疑难危重的肺炎患者中&#xff0c;肺炎支原体的检出率也在不断提高。华大基因PM Online线上数据管…

Python程序设计 函数

简单函数 函数&#xff1a;就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。 函数的使用包含两个步骤&#xff1a; 定义函数 —— 封装 独立的功能 调用函数 —— 享受 封装 的成果 函数的作用&#xff0c;在开发程序时&#xff0c;使用…

.NET Core Web API使用HttpClient提交文件的二进制流(multipart/form-data内容类型)

需求背景&#xff1a; 在需要通过服务端请求传递文件二进制文件流数据到相关的服务端保存时&#xff0c;如对接第三方接口很多情况下都会提供一个上传文件的接口&#xff0c;但是当你直接通过前端Ajax的方式将文件流上传到对方提供的接口的时候往往都会存在跨域的情况&#xff…

第97讲:MHA高可用集群模拟主库故障以及修复过程

文章目录 1.分析主库故障后哪一个从库会切换为主库2.模拟主库故障观察剩余从库的状态2.1.模拟主库故障2.3.当前主从架构 3.修复故障的主库3.1.修复主库3.2.当前主从架构3.3.恢复MHA 1.分析主库故障后哪一个从库会切换为主库 在模拟MHA高可用集群主库故障之前&#xff0c;我们先…

jenkins 发布远程服务器并部署项目

安装参考另一个文章 配置maven 和 jdk 和 git 注意jdk的安装目录&#xff0c;是jenkins 安装所在服务器的jdk目录 注意maven的目录 是jenkins 安装所在服务器的maven目录 注意git的目录 是jenkins 安装所在服务器的 git 目录 安装 Publish Over SSH 插件 配置远程服务器 创…

C++之函数重载,默认参数,bool类型,inline函数,异常安全

函数重载 在实际开发中&#xff0c;有时候需要实现几个功能类似的函数&#xff0c;只是细节有所不同。如交换两个变量的值&#xff0c;但这两种变量可以有多种类型&#xff0c;short, int, float等。在C语言中&#xff0c;必须要设计出不同名的函数&#xff0c;其原型类似于&am…

DockerUI如何部署结合内网穿透实现公网环境管理本地docker容器

文章目录 前言1. 安装部署DockerUI2. 安装cpolar内网穿透3. 配置DockerUI公网访问地址4. 公网远程访问DockerUI5. 固定DockerUI公网地址 前言 DockerUI是一个docker容器镜像的可视化图形化管理工具。DockerUI可以用来轻松构建、管理和维护docker环境。它是完全开源且免费的。基…

如何部署Linux AMH服务器管理面板并结合内网穿透远程访问

文章目录 1. Linux 安装AMH 面板2. 本地访问AMH 面板3. Linux安装Cpolar4. 配置AMH面板公网地址5. 远程访问AMH面板6. 固定AMH面板公网地址 AMH 是一款基于 Linux 系统的服务器管理面板&#xff0c;它提供了一系列的功能&#xff0c;包括网站管理、FTP 管理、数据库管理、DNS 管…

容器和镜像

容器和镜像是现代软件开发和部署中重要的概念&#xff0c;它们通常与容器化技术&#xff08;如Docker&#xff09;相关联。以下是它们的基本定义和关系&#xff1a; 容器(Container): 容器是一种轻量级、可移植的运行环境&#xff0c;其中包含了应用程序及其依赖项&#xff08;…

leet code141. 环形链表(投机取巧法)只要9行代码!!不看后悔!

今天在力扣上做到这个题 当我看到了10000时我突然想到一种很投机取巧的方法&#xff0c;我们直接链表循环&#xff0c;然后当它循环到10001次的时候我们就直接能说明它是循环链表了&#xff01; 代码实现(小学生都能看懂) bool hasCycle(struct ListNode *head) { int add…

【HarmonyOS应用开发】APP应用的通知(十五)

相关介绍 通知旨在让用户以合适的方式及时获得有用的新消息&#xff0c;帮助用户高效地处理任务。应用可以通过通知接口发送通知消息&#xff0c;用户可以通过通知栏查看通知内容&#xff0c;也可以点击通知来打开应用&#xff0c;通知主要有以下使用场景&#xff1a; 显示接收…

黑豹程序员-ElementPlus支持树型组件带图标以及icon避坑

效果 vue代码 参数说明&#xff1a;node当前节点&#xff0c;data当前节点后台传入数据。 el-tree自身不支持图标&#xff0c;需要自己去利于实现&#xff0c;并有个坑&#xff0c;和elementui写法不同。 <el-col :span"12"><el-form-item label"绑定…

Spring Web Header 解析常见错误

在上一章&#xff0c;我们梳理了 URL 相关错误。实际上&#xff0c;对于一个 HTTP 请求而言&#xff0c;URL 固然重要&#xff0c;但是为了便于用户使用&#xff0c;URL 的长度有限&#xff0c;所能携带的信息也因此受到了制约。 如果想提供更多的信息&#xff0c;Header 往往…

对多面体数据进行裁剪和加盖的功能

开发环境&#xff1a; Windows 11 家庭中文版Microsoft Visual Studio Community 2019VTK-9.3.0.rc0vtk-example demo解决问题&#xff1a;对多面体数据进行裁剪和加盖的功能。 关键点&#xff1a; 创建了一个平面&#xff0c;并将其定位在输入多面体数据的中心位置&#xff…

Python 数据分析(PYDA)第三版(六)

原文&#xff1a;wesmckinney.com/book/ 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 十二、Python 建模库介绍 原文&#xff1a;wesmckinney.com/book/modeling 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 此开放访问网络版本的《Python 数据分析第三版…