React基础知识大汇总

news2024/11/25 0:10:04

函数组件和类组件

函数组件与类组件有什么区别呢?

function getName(params:{name:string}){
	const count = 0;
	return params.name +'-'+count;
}
getName({name:"test"})
getName({name:"哈哈哈"})

getName是一个纯函数,不产生任何副作用,执行结束后,它的执行上下文和活动对象会被销毁,前后两次调用互不影响。对于不使用任何Hooks的函数组件而言,它也是纯函数,那么对于函数组件前后两次渲染,你能得出与调用getName函数类似的结论吗?

下面用类组件和函数组件实现相同的功能来对比二者的区别。在浏览器上显示一个按钮,单击按钮调用props中的方法来更新父组件的状态,隔1s之后打印this.props.count的值。类组件的代码如下:

import { Button } from 'antd'
import React, { Component } from 'react'

class ClassCom extends Component {

    onClick = () => {
        this.props.updateCount()
        setTimeout(() => {
            console.log("类组件",this.props.count)
        }, 1000)
    }

    render() {
        return (
            <Button onClick={this.onClick}>
                这是类组件
            </Button>
        )
    }
}

function FunCom(props) {

    const onClick = () => {
        props.updateCount()
        setTimeout(() => {
            console.log("函数组件",props.count)
        }, 1000)
    }

    return (
        <Button onClick={onClick}>
            这是函数组件
        </Button>
    )
}

export default class FunComVsClassCom extends Component {

    constructor(props) {
        super(props)
        this.state = {
            count: 0
        }
    }

    updateCount = () => {
        this.setState({
            count:this.state.count+1
        })
    }

    render() {
        return (
            <div>
                <FunCom
                    count={this.state.count}
                    updateCount={this.updateCount}
                />
                <ClassCom
                    count={this.state.count}
                    updateCount={this.updateCount}
                />
            </div>
        )
    }
}

在这里插入图片描述
单击FuncCom和ClassCom组件中的按钮都会使得父级重新刷新,从而导致FuncCom和ClassCom重新渲染。ClassCom是类组件,重新渲染不会创建新的组件实例,在setTimeout的回调函数中this.props拿到了最新的值。FuncCom是函数组件,重新渲染会创建新的执行环境和活动变量,所以访问props,无论何时拿到的都是调用FunCom时传递给它的参数,该参数不可变。

React Ref API

Ref的功能强大,它能够让组件与DOM元素,或类组件与其父级之间建立直接联系。总体而言,使用Ref出于以下3个目的。

  • 访问DOM元素。
  • 访问组件的实例。
  • 将Ref作为mutable数据的存储中心
  1. 创建Ref
    创建Ref有两种方式,分别为useRef和React.createRef。useRef是一种Hooks,只能在函数组件中使用。React.createRef的使用位置不限制,但不要在函数组件中使用它,如果在函数组件中使用它创建Ref,那么函数组件每次重新渲染都会创建新的Ref。

  2. 访问DOM元素或组件实例
    要想通过Ref访问DOM元素,必须将Ref绑定到浏览器内置的组件上。等组件装载了之后使用ref.current字段访问DOM元素。

    export default function App() {
    const inputRef = useRef(null)
    const onClick=()=>{
      if(inputRef.current){
        inputRef.current.focus()
      }
    }
     return (
        <input ref={inputRef}/>
      )
    }
    
  3. 将Ref作为mutable数据的存储中心
    将Ref作为mutable数据的存储中心,使用场景主要是函数组件,在类组件中大可不必如此。这是因为函数组件每一次重新渲染都会执行函数体,使函数体的各个变量都被重新创建。如果函数体中声明了一些只用于缓存的数据,即不会导致组件重新渲染的变量,那么将这些数据放在ref中能避免它们被反复创建。
    将Ref作为mutbale数据的存储中心,不需要将其绑定到React element上,创建之后就能直接使用,修改mutableRef.current的值,组件不会重新刷新。

React Hooks

React Hooks在React16.8时正式发布。它使函数组件拥有自己的状态。对类组件没有影响。一般函数组件相比起类组件存在如下3个优点:

  • 类组件必须时刻关注this关键字的指向。
  • 相同的生命周期在类组件中最多定义一个,这导致彼此无关的逻辑代码被糅杂在同一个函数中。
  • 不同的生命周期函数可能包含相同的代码。最常见的便是componentDidMount和componentDidUpdate。
useState

useState是一个与状态管理相关的Hooks,能让函数组件拥有状态,是最常用的Hooks之一,useState的基本用法。

  1. useState的参数不是函数
    此时,useState的参数将作为状态的初始值,如果没有传参数,那么状态的初始值为undefined。

    const [name,setName] = useState("test")
    const [age,setAge] = useState()
    
  2. useState的参数是函数
    此时,函数的返回值是状态的初始值。某些时候,状态的初始值要经过计算才能得到。此时推荐将函数作为useState的参数,该函数只在组件初始渲染时执行一次。

    const [count,setCount] = useState(()=>{
        //这个函数只在初始渲染时执行,后续的重新渲染不再执行
        return 0
    })
    
  3. 修改状态的值
    修改状态有两种方式:

    //用法一
    setCount((count)=>{
      return count+1
    })
    //用法二
    setCount(0)
    

如果setCount的参数时函数,那么count现在的值将以参数的形式传递给函数,函数的返回值用于更新状态。如果setCount的参数不是函数,那么该参数将用于更新状态。状态值发生变化将导致组件重新渲染,重新渲染时,useState返回的第一个值始终是状态最新的值,不会重置为初始值。

useRef

使用useState能让函数组将拥有状态,状态拥有不变性,它在组件前后两次渲染中相互独立。使用useRef能为组件创建一个可变的数据,该数据在组件的所有渲染中保持唯一的引用,所以对它取值始终会得到最新的值。

useEffect

函数组件可以多次调用useEffect,每使用一次就定义一个effect,这些effect的执行顺序与它们被定义的顺序一致,建议将不同职责的代码放在不同的effect中。接下来从effect的清理工作和依赖这两个方面介绍useEffect。

  1. effect的清理工作
    effect没有清理工作就意味着它没有返回值。effect的清理工作由effect返回的函数完成,该函数在组件重新渲染后和组件卸载时调用。

    useEffect(()=>{
       document.body.addEventListener('click',()=>{})
        //在返回的函数中定义与该effect相关的清理工作
        return()=>{
            document.body.removeEventListener('click',()=>{})
        } 
    })
    

    该effect在组件首次渲染和之后的每次重新渲染时都会执行,如果组件的状态更新频繁,那么组件重新渲染也会很频繁,这将导致body频繁绑定click事件又解绑click事件/是否有办法使组件只在首次渲染时给body绑定事件呢?那就是依赖。

  2. effect的依赖
    前面示例定义的effect没有指明依赖,因此组件的每一轮渲染都会执行它们。

    useEffect(()=>{
       document.body.addEventListener('click',()=>{})
        //在返回的函数中定义与该effect相关的清理工作
        return()=>{
            document.body.removeEventListener('click',()=>{})
        } 
    },[])//传空意味着该effect只在组件初始渲染时执行,它的清理工作在组件卸载时执行。
    
    useEffect(()=>{
       document.body.addEventListener('click',()=>{})
        //在返回的函数中定义与该effect相关的清理工作
        return()=>{
            document.body.removeEventListener('click',()=>{})
        } 
    },[name])//在组件初始渲染时会执行,当name发生变化导致组件重新渲染也会执行,相应的,组件卸载时和由name变化导致组件重新渲染之后将清理上一个effect
    

    注意:给effect传递依赖项,React会将本次渲染时依赖项的值与上一次渲染时依赖项的值进行浅对比,如果它们当中的一个有变化,那么该effect会被执行,否则不会执行。为了让effect拿到他所需状态和props的最新值,effect中所有要访问的外部变量都应该作为依赖项。函数组件每次渲染时,effect都是一个不同的函数,在函数组件内的每一个位置(包括事件处理函数、effects、定时器等)只能拿到定义他们的那次渲染的状态和props。

useReducer

useReducer是除useState之外另一个与状态管理相关的Hooks。这个Hooks笔者用得比较少,需要的同学可以参考下官方文档。
https://zh-hans.react.dev/reference/react/useReducer

用法如下:

import { useReducer } from 'react';

function reducer(state, action) {
  if (action.type === 'incremented_age') {
    return {
      age: state.age + 1
    };
  }
  throw Error('Unknown action.');
}

export default function Counter() {
  const [state, dispatch] = useReducer(reducer, { age: 42 });

  return (
    <>
      <button onClick={() => {
        dispatch({ type: 'incremented_age' })
      }}>
        Increment age
      </button>
      <p>Hello! You are {state.age}.</p>
    </>
  );
}

自定义Hooks

如果在多个组件中使用了相同的useEffect或useState逻辑,推荐将这些相同的逻辑封装到函数中,这些函数被称为自定义的Hooks。下面举例3个自定义的Hooks的示例。

  1. useForceUpdate:返回一个让组件重新渲染的函数。

     function useForceUpdate(){
        const [,setTick]=useState(0)
        return ()=>setTick(t=>t+1)
     }
     const forceUpdate = useForceUpdate();
      const handleClick = () => {
           // 调用 forceUpdate 函数来强制组件重新渲染
          forceUpdate();
     };
    
    
  2. usePrevVal:获取状态的上一次的值,它利用了Ref的可变性,以及effect在DOM被绘制到屏幕上才执行的特性

    function usePrevVal(status){
       const ref = useRef()
       const [prevVal,setPrevVal] = useState()
       useEffect(()=>{
          setPrevVal(ref.current)
          ref.current = status
       },[status])
       return prevVal
    }
    
  3. useVisible:检测dom元素是否在浏览器视口内,它在effect中创建observer来异步观察目标元素是否与顶级文档视口相交。

    function useVisible(root:React.RefObject<HTMLElement>,rootMargin?:string) {
      const [isVisible, setIsVisible] = useState(false);
    
      useEffect(() => {
        const observer = new IntersectionObserver((entries) => {
          entries.forEach(entry => {
            setIsVisible(entry.isIntersecting);
          });
        }, {rootMargin});
    
        if (root.current) {
          observer.observe(root.current);
        }
    
        return () => {
          observer.disconnect() 
        };
      }, [root,rootMargin]);
    
      return isVisible;
    }
    
React Context API

在React应用中,为了让数据在组件间共享,常见的方式是让它们以props的形式自顶向下传递。如果数据在组件树的不同层级共享,那么这些数据必须传递到目的地,这种情况称为prop-drilling。Context如同管道,他将数据从入口直接传递到出口,使用Context可以避免出现prop-drilling。
总体而言,使用Context分为以下三步:

  1. 创建Context对象

    const MyContext = React.createContext({
       lang:"zh_CN",
       changeLang:()=>{throw Error('xxxx')}
    })
    
  2. 用Context.Provider包裹组件树
    用Context.Provider圈选Context的作用域,只有作用域内的组件才能消费Context中的数据,此处是管道的入口,在这里放入想要传递的数据。

    class ContextDemo extends React.Component{
        render(){
           <MyContext.Provider
             value={someValue}
           >
            //children
           </MyContext.Provider>
        }
    }
    
  3. 订阅Context
    订阅Context的位置是管道的出口,对于Context对象而言,管道入口只有一个,但出口可以有多个。订阅Context有3种方式。

    • 类组件的静态属性contextType。
      在类组件中使用contextType去订阅Context。用法如下。

      class MyNestedClass extends React.Component{
         static contextType = MyContext
      }
      

      contextType订阅了Context之后,除了不能在构造函数中使用this.context访问到contextvalue之外,在类组件的其他位置都能使用this.context访问到数据。React组件的shouldComponentUpdate的第三个参数是组件即将接收的context。

    • useContext。
      在函数组件中通过useContext订阅Context时,useContext的使用次数不限。用法如下。

      function MyNestedFunc(){
         const myContext = useContext(MyContext)
      }
      
    • Context.Consumer。
      Context.Consumer是react组件,在Context作用域的任何位置都能使用它,它只接收一个名为children的props,children必须是一个返回React.ReactNode的函数,该函数以context作为参数。用法如下:

      <MyContext.Consumer>
         {(context)=><MyNestedCom lang={context.lang}/>}
      </MyContext.Consumer>
      

无论如何订阅Context,只要context的值被更新,那么订阅该Context的组件一定会重新渲染,而不管context更新的那部分值是否被自己使用,也不管祖先组件是否跳过重新渲染。所以推荐将不同职责的数据保存到不同的context中,以减少不必要的重新渲染。
如果给Context.Provider的value属性传递一个对象字面量,那么Context.Provider的父组件每次重新刷新都会使得context的值发生变化,进而导致订阅该context的组件重新渲染,应当避免。

深入理解React的渲染流程
  • 类组件的生命周期流程图如下(18版本之后)。父组件重新渲染、调用this.setState()、调用this.forceUpdate()以及订阅Context的value发生变更都会导致类组件更新。
    在这里插入图片描述
    函数组件的生命周期流程如下所示:
    在这里插入图片描述
    装载是运行的惰性初始化程序指传递给useState和useReducer的函数。父组件重新渲染、状态发生变更以及订阅的Context的value发生变更都会导致函数组件更新。有图可知,上一次的effect会在组件更新后被清理,清理effect和运行effect都不会阻塞浏览器绘制。

  • 渲染流程
    渲染是React让组件根据当前的props和状态描述它要展示的内容;重新渲染是React让组件重新描述它要展示的内容。渲染和更新DOM不是同一件事情,组件经过了渲染,DOM不一定会更新。React渲染一个组件,如果组件返回的输出与上次的相同,那么它的DOM节点不需要有任何更新。
    将组件显示到屏幕上,React的工作分为如下两个阶段:

    • Render阶段(渲染阶段):计算组件的输出并收集所有需要应用到DOM上的变更。
    • Commit阶段(提交阶段):将Render阶段计算出的变更应用到DOM上。

    在Commit阶段React会更新DOM节点和组件实例的Ref。如果是类组件,React会同步运行componentDidMount或componentDidUpdate生命周期方法;如果是函数组件,React会同步运行useLayoutEffect Hooks,当浏览器绘制DOM之后,再运行所有的useEffect Hooks。

    初始化渲染之后,下面的方式会让React重新渲染组件。

    • 类组件—— 调用this.setState方法或调用this.forceUpdate方法
    • 函数组件—— 调用useState返回的setState或调用useReducer返回的dispatch
    • 其他——组件订阅的Context的value发生变更或重新调用ReactDOM.render(<AppRoot>)
  • 提高渲染性能
    要将组件显示在界面上,组件必须经过渲染流程,但是渲染有时候会被认为是浪费时间。如果渲染的输出结果没有改变,它对应的DOM节点也不需要更新,该组件的渲染工作就真的是在浪费时间。React组件的输出结果始终基于当前props和状态的值,因此,如果我们知道组件的propss和状态没有改变,那么便能让组件跳过重新渲染。

    1. shouldComponentUpdate:返回false,react将跳过重新渲染该组件的过程。使用它最常见的场景是检测组件的props和状态是否自上次以来发生变更,如果没有变更则返回false。
    2. PureComponent:它在Component的基础上添加了默认的 shouldComponentUpdate去比较组件的props和状态自上次渲染以来是否变更。
    3. React.memo:这是一个高阶组件,接收自定义组件作为参数,返回一个被包裹的组件。被包裹的组件的默认行为是检测props是否有更改,如果没有,则跳过重新渲染的过程。
    4. 如果组件在渲染过程中返回的元素的引用与上一次渲染时的引用完全相同,那么React不会重新渲染该组件。
function ShowChildren(props:{children}){
  const [count,setCount] = useState(0)
  return(
     <div>
       {count}<button onClick={()=>setCount(c=>c+1)}>click</button>
       {props.children} //点击按钮不会使其重新渲染
       <Children/> //点击按钮会使其重新渲染
     </div>
  )
}

默认情况下,只要组件重新渲染,React就会重新渲染所有被它嵌套的后代组件,即便组件的props没有变更。如果试图通过meo和PureComponent优化组件的渲染性能,那么要注意每个props的引用是否变更。

const MemoizedChildren = React.memo(Children)
function Parent(){
  const onClick=()=>{}
  return <MemoizedChildren onClick={onClick}/>
}

Parent被重新渲染会创建新的onClick函数,所以对MemoizedChildren 而言,props.onClick的引用发生变化,因此Children组件会重新渲染,如果必须让组件跳过重新渲染,可以使用useCallback。

const MemoizedChildren = React.memo(Children)
function Parent(){
    // 使用useCallback优化回调函数
  const handleClick = useCallback(() => {
    console.log('Button clicked! Count:', count);
  }, []);
  return <MemoizedChildren onClick={handleClick }/>
}
  • useCallback和useMome
  1. 功能不同:useCallback用于记忆化回调函数,而useMemo用于记忆化计算结果。

  2. 参数不同:useCallback接受一个回调函数和一个依赖项数组作为参数,只有当依赖项发生变化时,才会返回一个新的记忆化的回调函数。useMemo接受一个计算函数和一个依赖项数组作为参数,只有当依赖项发生变化时,才会重新计算并返回一个新的记忆化的计算结果。

  3. 返回值类型不同:useCallback返回一个记忆化的回调函数,而useMemo返回一个记忆化的计算结果。

  4. 使用场景不同:useCallback主要用于优化传递给子组件的回调函数,避免不必要的重新创建和渲染。useMemo主要用于优化计算操作,避免不必要的重复计算。

import React, { useState, useCallback, useMemo } from 'react';
 
function MyComponent() {
  const [count, setCount] = useState(0);
 
  // 使用useCallback优化回调函数
  const handleClick = useCallback(() => {
    console.log('Button clicked! Count:', count);
  }, [count]);
 
  // 使用useMemo优化计算结果
  const doubledCount = useMemo(() => {
    console.log('Calculating doubled count...');
    return count * 2;
  }, [count]);
 
  return (
    <div>
      <button onClick={handleClick}>Click Me</button>
      <p>Count: {count}</p>
      <p>Doubled Count: {doubledCount}</p>
    </div>
  );
}

可以看到,在上面的例子中,handleClick回调函数通过useCallback进行记忆化,只有当count发生变化时才会重新创建。而doubledCount则通过useMemo进行记忆化,只有当count发生变化时才会重新计算。这样可以避免在每次组件渲染时不必要地重新创建回调函数和重复计算结果。

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

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

相关文章

算法竞赛相关问题总结记录

前言 日常在校生或者是工作之余的同学或多或少都会参加一些竞赛,参加竞赛一方面可以锻炼自己的理解与实践能力&#xff0c;也能够增加自己的生活费&#xff0c;竞赛中的一些方案也可以后续作为自己论文的base,甚至是横向课题的框架。在算法竞赛中算法的差别个人感觉差距都不大&…

区块链钱包开发指南: 探究区块链钱包开发涉及

区块链钱包是连接用户与区块链网络的重要工具&#xff0c;它们不仅提供了安全的存储和管理数字资产的功能&#xff0c;还允许用户进行交易和与区块链上的智能合约进行互动。本文将探究区块链钱包开发涉及的关键方面和技术要点。 1. 区块链钱包类型 区块链钱包可以分为以下几种…

Android Studio查看viewtree

前言&#xff1a;之前开发过程一直看的是手机上开发者选项中的显示布局边界&#xff0c;开关状态需要手动来回切换&#xff0c;今天偶然在Android Studio中弄出了布局树觉得挺方便的。

汽车纵染压制专用液压机比例阀放大器

汽车纵染压制专用液压机比例阀放大器是一种专门用于汽车纵梁拉伸工艺的设备&#xff0c;它也可以用于其他金属薄板的压制成型及校正工艺。该类型的液压机通常具备独立的动力机构和电气系统&#xff0c;采用PLC技术进行控制&#xff0c;以确保操作的准确性和稳定性。除了纵梁拉伸…

文心一言 VS 讯飞星火 VS chatgpt (243)-- 算法导论18.1 1题

一、B树中为什么不允许最小度数 t1&#xff1f;如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 在B树中不允许最小度数 t1 的主要原因在于这样会导致树的结构退化为链表&#xff0c;失去了B树作为平衡多路搜索树的优势。当 t1 时&#xff0c;每个非根节点将只能…

openGauss学习笔记-269 openGauss性能调优-TPCC性能调优测试指导-数据库服务端及客户端绑核

文章目录 openGauss学习笔记-269 openGauss性能调优-TPCC性能调优测试指导-数据库服务端及客户端绑核269.1 安装openGauss数据库269.2 停止数据库269.3 使用gs_guc工具修改数据库端口、IP等269.4 使用gs_guc工具设置如下参数269.5 执行如下命令以绑核方式启动服务端数据库269.6…

在线教程丨刘强东数字人首秀交易额破5千万!用GeneFace++ 生成实时说话数字人

近日&#xff0c;京东创始人刘强东化身「采销东哥 AI 数字人」&#xff0c;在京东家电家居和超市的采销直播间开启了自己的直播首秀。此次直播活动观看人次超 2 千万&#xff0c;交易总额超 5 千万&#xff0c;充分彰显了AI 数字人在电商直播领域的巨大潜力。 「采销东哥」亮相…

SwiftUI 5.0(iOS 17.0)触摸反馈“震荡波”与触发器模式趣谈

概览 要想创作出一款精彩绝伦的 App&#xff0c;绚丽的界面和灵动的动画并不是唯一吸引用户的要素。有时我们还希望让用户真切的感受到操作引发的触觉反馈&#xff0c;直击使用者的灵魂。 所幸的是新版 SwiftUI 原生提供了实现触觉震动反馈的机制。在介绍它之后我们还将进一步…

prompt提示词:小红书爆款标题提示词,让AI 帮你生成吸睛的标题

目录 小红书爆款标题提示词效果展示&#xff1a;提示词&#xff1a; 小红书爆款标题提示词 一篇文章若缺少了吸引人的标题&#xff0c;就如同失去了灵魂的躯壳&#xff0c;失去了与读者心灵相通的桥梁&#xff0c;上次发表了一篇小红书爆款文案生成助手 提示词&#xff0c;大家…

Linux之安装Nginx

目录 传送门前言一、快速安装二、反向代理语法1、基本语法2、location语法1. 基本语法2. 匹配规则3. 修饰符4. 权重5. 嵌套location6. 其他指令7.案例 三、配置反向代理 传送门 SpringMVC的源码解析&#xff08;精品&#xff09; Spring6的源码解析&#xff08;精品&#xff0…

食用油5G智能工厂数字孪生可视化平台,推进食品制造业数字化转型

食用油5G智能工厂数字孪生可视化平台&#xff0c;推进食品制造业数字化转型。在食用油产业中&#xff0c;数字化转型已成为提升生产效率、优化供应链管理、确保产品质量和满足消费者需求的关键。食用油5G智能工厂数字孪生可视化平台作为这一转型的重要工具&#xff0c;正在推动…

【来自理工科的独有浪漫-给crush一朵夏天的雪花】--对于有限差分法的理解

目录 有限差分法相关参考资料先上手看代码&#xff0c;然后理解数理概念有限差分法的理解Q: 什么是有限差分法&#xff1f; 代码中涉及的知识点1. 划分网格对于求解二维偏微分方程的作用2. 临近点对于求解偏微分方程的作用3. 有限差分方法中的中心差分公式 总结 写在前面&#…

喜报 | 一致认可!擎创科技连续6年获“鑫智奖”专家推荐TOP10优秀解决方案

为展示金融企业数据管理和数据平台智能化转型成果&#xff0c;分享大数据和人工智能在风控、营销、产品、运营等场景的落地实践&#xff0c;探讨“金融科技数据智能”的创新应用和未来发展&#xff0c;在全球金融专业人士协会的支持下&#xff0c;金科创新社主办了“鑫智奖第六…

Apple II首席设计师为中国家庭设计,鹿客指脉锁S6 Max引领科技美学

智能门锁设计正在步入一个科技与艺术交织的美学时代。鹿客科技认为&#xff0c;智能门锁的设计理念是将锁视为人类与仿生形状之间的接口&#xff0c;将门视为几何建筑的一部分&#xff0c;产品设计应该通过提供诱人且用户友好的“触摸和感觉”来传达这种转变。 鹿客近日发布的最…

(C语言入门)数组

目录 什么是数组&#xff1f; 数组&#xff1a; 数组的使用&#xff1a; 数组的初始化&#xff1a; 数组名&#xff1a; 数组案例&#xff1a; 一维数组的最大值&#xff1a; 一维数组的逆置&#xff1a; 数组和指针&#xff1a; 通过指针操作数组元素&#xff1a; …

springCloud集成activiti5.22.0流程引擎

springCloud集成activiti5.22.0流程引擎 点关注不迷路&#xff0c;欢迎再访&#xff01; 精简博客内容&#xff0c;尽量已行业术语来分享。 努力做到对每一位认可自己的读者负责。 帮助别人的同时更是丰富自己的良机。 小编最近工作需要涉及到流程&#xff0c;由于网络上5.22版…

AD--SSL卸载--单向认证和双向认证

一.SSL卸载单向认证 1.添加SSL证书 2.添加SSL卸载策略 由于是测试模拟环境&#xff0c;有些效果表现不出来&#xff0c;配置不了卸载策略 3.起虚拟服务&#xff0c;服务类型选择https或者ssl ,选择SSL卸载策略 实验效果&#xff1a;打开网页进入AD抓包发现&#xff0c;客户端和…

MySQL及SQL语句

SQL语句 数据库相关概念数据查询语言&#xff08;DQL&#xff09;基本查询数据类型条件查询多表查询子查询 数据操作语言&#xff08;DML&#xff09;数据定义语言&#xff08;DDL&#xff09;数据控制语言&#xff08;DCL&#xff09;MySQL数据库约束视图练习题 数据库相关概念…

8【PS作图】画一个“像素云朵”

选择64*128像素大小&#xff0c;横向画布 选择“油漆桶”工具&#xff0c;“容差”调整为0&#xff0c;取消“锯齿”&#xff0c;勾选“连续的”&#xff0c;这样方便后续上色&#xff0c;并且边缘都是像素风格的锯齿状 点击画布&#xff0c;变成蓝色天空 画云朵&#xff0c;首…