03-React事件处理 生命周期 Diffing算法

news2024/11/28 23:52:49

React事件处理

背景

1.通过onXxx属性指定事件处理函数(注意大小写)

  • React使用的是自定义(合成)事件, 而不是使用的原生DOM事件
比如原生onclick的事件在React中变成了onClick,这么搞是为了更好的兼容性
  • React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)
比如,div标签中有input,button等标签,这里面的事件最终都会被委托给最外层的div上

事件委托的原理是事件冒泡,这么做的原因是高效

2.通过event.target得到发生事件的DOM元素对象 ~~~ 不要过度使用ref

受控组件与非受控组件

功能:需求: 定义一个包含表单的组件
输入用户名密码后, 点击登录显示输入的信息
在这里插入图片描述

非受控组件(不推荐)

非受控组件主要是用ref来做管理,而ref获取的是DOM,React官方建议少用ref

比如一个表单,点击button进行提交的这个动作,作为H5的默认动作,默认是不阻止提交的,这个就叫非受控组件

在这里插入图片描述

<script type="text/babel">
    class Login extends React.Component{
        handleSubmit=()=>{
            //阻止默认的表单提交
            event.preventDefault()
            // 解构对象,拿到ref设置的DOM
            // 其实这是一种现用现取的逻辑,所以是非受控组件
           const {username,password} =this
           alert(`${username.value},${password.value}`)
        }
        render(){
            return (
                <div>
                    <form action="www.atguigu.com" onSubmit={this.handleSubmit}>
                        {/*将属性通过ref设置到对象身上,以便使用时获取*/}
                        用户名<input ref={(c)=>this.username=c} type="text" name="username"></input>
                        密码<input ref={(c)=>this.password=c} type="password" name="password"></input>
                        <button>登陆</button>
                    </form>
                </div>
            )
        }
    }
    ReactDOM.render(<Login/>,document.getElementById("test"))
</script>

受控组件(推荐)

页面中所有输入的DOM(input,radio…等等),输入的时候,就把输入的内容,set到state里面,等需要用的时候,再取出来
而不是像非受控组件一样,等到需要用的时候,再去现获取。而且非受控组件写了大量的ref属性,在React看来也是不推荐的写法(类似vue双向绑定)

例子:
在这里插入图片描述
在这里插入图片描述

稍加修改,我们把数据暂存到state里面,用state来暂存可以达到同样的效果
在这里插入图片描述
如果是多个的属性,用ref获得到大量的DOM元素就会很乱,不如统一扔进state更方便

最后代码:

<script type="text/babel">
    class Login extends React.Component{
        //初始化一下state,如果不写也可以
        state={
            username:"",
            password:""
        }

        // 管理表单中的n多个属性
        saveUsername=(event)=>{
            //set的时候用this.setState({key:value})
            this.setState({username:event.target.value})
        }
        savePassword=(event)=>{
            // 注意要用setState的API,如果是this.state就会被认为是更新操作
            this.setState({password:event.target.value})
        }
        showValue=(event)=>{
            //阻止提交后发生跳转
            event.preventDefault()
            // 解构,这时就得到的属性,而不是之前的DOM了
            const {username,password}=this.state
            //所以就不再需要再像ref一样去DOM.value,因为直接获取到的就是属性,而不是DOM
            console.log(username,password)
        }
        render(){
            return (
                <div>
                    <form onSubmit={this.showValue}>
                        {/*每次change的时候都会实时同步到state里面*/}
                        用户名<input onChange={this.saveUsername} type="text" name="username"></input>
                        密码<input onChange={this.savePassword} type="password" name="password"></input>
                        <button>登陆</button>
                    </form>
                </div>
            )
        }
    }
    ReactDOM.render(<Login/>,document.getElementById("test"))
</script>

在这里插入图片描述

着重注意一下这里,其实就是ref 解构出来DOMstate 解构出来属性上的区别
在这里插入图片描述

柯里化概念

只有函数才有柯里化

高阶函数: 如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。

  • 若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。
  • 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
    常见的高阶函数有: Promise、setTimeout、arr.map()等等

函数的柯里化: 通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式

高阶函数——函数柯里化

上面的内容其实不难发现,有很大优化空间

比如:
如果有大量的属性,那么复用性很差,有大量冗余,所以不建议这么搞

   // 管理表单中的n多个属性
   saveUsername=(event)=>{
       //set的时候用this.setState({key:value})
       this.setState({username:event.target.value})
   }
   savePassword=(event)=>{
       // 注意要用setState的API,如果是this.state就会被认为是更新操作
       this.setState({password:event.target.value})
   }
<input onChange={this.saveUsername} type="text" name="username"></input>

理所当然的就想着抽共同调用,抽共通的话就需要把当前的key的名字传进去

重点来了

从这样

<input onChange={this.saveUsername} type="text" name="username"></input>

到这样

<input onChange={this.saveUsername("username")} type="text" name="username"></input>

会有一个问题,就是this.saveUsername是一个属性this.saveUsername("username")是一个函数,而这个函数是没有返回值的!
这样就会导致onChange得到的函数return一个undefined。这里的undefined是因为没有标记return

所以怎么办呢,就是把函数的return用箭头函数改造一下!我让return有返回值,但是返回一个空的箭头处理,即有了返回值,又有了处理。

 // 管理表单中的n多个属性
 saveValue = (value) => {
   //这个event是React自动传入,我们无法手动set,所以不能在方法里传入
   return (event) => {
     this.setState({ [value]: event.target.value });
   };
 };
 //调用时传入key
<input onChange={this.saveUsername("username")} type="text" name="username"/>

这里为什么value要用[ ]套一下?

this.setState({ [value]: event.target.value });
这里的value用[]套一下是因为它是当前对象的一个变量,而不是一个字符串。在JavaScript中,当你使用方括号([])来访问对象的属性时,如果属性名是一个变量,那么你需要将变量放在方括号内。这样,你就可以动态地访问和设置对象的属性值。
换句话说,这个方括号([]),直接把value从字符串转换成对象的一个属性了

在这里插入图片描述

贴上完整代码:

<!--JSX转换成JS用的依赖,因为浏览器不认识JSX,只认识JS-->
<script type="text/babel">
  class Login extends React.Component {
    //初始化一下state,如果不写也可以
    state = {
      username: "",
      password: "",
    };

    // 管理表单中的n多个属性
    saveValue = (value) => {
      //这个event是React自动传入,我们直接取值即可
      return (event) => {
        this.setState({ [value]: event.target.value });
      };
    };

    render() {
      return (
        <div>
          <form>
            用户名
            <input
              onChange={this.saveValue("username")}
              type="text"
              name="username"
            ></input>
            密码
            <input
              onChange={this.saveValue("password")}
              type="password"
              name="password"
            ></input>
            <button>登陆</button>
          </form>
        </div>
      );
    }
  }
  ReactDOM.render(<Login />, document.getElementById("test"));
</script>

不用柯里化的写法

不用柯里化对其进行改造,也就是不再采用上面的return箭头函数

关键在于在标签里就把event传进去
改造一下,此时event就直接传入方法了:

<input onChange={(event) => {this.saveValue("username", event)} type="text" name="username" ></input>

saveValue = (value, event) => {
  this.setState({ [value]: event.target.value });
};

测试效果是一样的,好用

全部代码:

<script type="text/babel">
 class Login extends React.Component {
    //初始化一下state,如果不写也可以
    state = {
      username: "",
      password: "",
    };

    // 管理表单中的n多个属性
    saveValue = (value, event) => {
      this.setState({ [value]: event.target.value });
    };

    render() {
      return (
        <div>
          <form>
            用户名
            <input
              onChange={(event) => {
                this.saveValue("username", event);
              }}
              type="text"
              name="username"
            ></input>
            密码
            <input
              onChange={(event) => {
                this.saveValue("password", event);
              }}
              type="password"
              name="password"
            ></input>
            <button>登陆</button>
          </form>
        </div>
      );
    }
  }
  ReactDOM.render(<Login />, document.getElementById("test"));
</script>

React生命周期

React生命周期可以分为旧版和新版,这里旧版生命周期并非弃用,新版只是在旧版生命周期的上面,废弃了三个API,新增了两个API,所以还是有学习旧版生命周期的必要性。

旧版生命周期

可以看到,可以分为两大部分,分别为挂载初始化时组件更新时

render函数贯穿两大部分,因为无论是初始化,还是组件更新,都需要重新渲染,diffing差分等等。

每个部分都有对应的函数供我们使用。

在这里插入图片描述

初始化阶段API(由ReactDOM.render()触发—初次渲染)

主要集中于这四个API,无论代码的顺序如何,都会按照这个生命周期的顺序进行执行。
在这里插入图片描述

  • 1、constructor()
    完成了React数据的初始化,state设值等等。

  • 2、componentWillMount()
    组件已经完成初始化数据,但是还未渲染DOM时执行的逻辑,主要用于服务端渲染,网络请求等。

  • 3、render()
    组件开始渲染真实DOM。

  • 4、componentDidMount()
    组件第一次渲染完成时执行的逻辑,此时DOM节点已经生成了。

代码:

<script type="text/babel">
  class Login extends React.Component {
    constructor(Props) {
      super(Props);
      console.log("constructor 执行");
    }

    componentWillMount() {
      console.log("componentWillMount 执行");
    }

    componentDidMount() {
      console.log("componentDidMount 执行");
    }

    render() {
      console.log("render 执行");
      return <div>123</div>;
    }
  }
  ReactDOM.render(<Login />, document.getElementById("test"));
</script>

执行可以发现,按照生命周期的顺序输出
在这里插入图片描述

更新阶段API(由组件内部this.setSate()或父组件重新render触发)

一般来说,更新阶段API都是在属性变更时触发,比如state属性变化,页面上组件变化,就会触发更新阶段的API
在这里插入图片描述

  • 1、componentWillReceiveProps(nextProps)
    接收父组件新的props时,重新渲染组件执行的逻辑,括号里的参数可以选择接收之后打印一下。注意,这个API在初次接收的时候是不会更新的,只有第二次接收之前才会触发

  • 2、shouldComponentUpdate(nextProps, nextState)
    在setState以后,state发生变化,组件会进入重新渲染的流程时执行的逻辑。在这个生命周期中return false可以阻止组件的更新,主要用于性能优化。

  • 3、componentWillUpdate(nextProps, nextState)
    shouldComponentUpdate返回true以后,组件进入重新渲染的流程时执行的逻辑。

  • 4、render()
    页面渲染执行的逻辑,render函数把jsx编译为函数并生成虚拟dom,然后通过其diff算法比较更新前后的新旧DOM树,并渲染更改后的节点。

  • 5、componentDidUpdate(prevProps, prevState)
    重新渲染后执行的逻辑。

父子组件传值例子:

定义了两个类组件(A组件 , B组件),B组件在A组件内使用,A组件向B组件传值,每次只要值更新,就会触发更新生命周期函数

<script type="text/babel">
  class A extends React.Component {
    // 给state默认值
    state = {
      car: "宝马",
    };
    // 更新传入值
    changeCar = () => {
      this.setState({ car: "奥迪" });
    };

    render() {
      return (
        <div>
          <div>A组件</div>
          <button onClick={this.changeCar}>更新组件,给B传值触发更新</button>
          {"B组件传入A的state属性"}
          <B car={this.state.car} />
        </div>
      );
    }
  }

  class B extends React.Component {
    render() {
      return <div>{this.props.car}</div>;
    }
  }

  ReactDOM.render(<A />, document.getElementById("test"));
引出API

在这个传值的过程中会触发很多生命周期API,挨个试验一下

  • 1、componentWillReceiveProps(nextProps)
    接收父组件新的props时,重新渲染组件执行的逻辑,括号里的参数可以选择接收之后打印一下。注意,这个API在初次接收的时候是不会更新的,只有第二次接收之前才会触发

在这里插入图片描述


  • 2、shouldComponentUpdate(nextProps, nextState) 参数不传也完全可以
    setState操作就会触发这个钩子,,state发生变化,组件会进入重新渲染的流程时执行的逻辑。在这个生命周期中return false或不指定返回内容(默认undefined) 可以阻止组件的更新相当于更新组件的阀门

在这里插入图片描述
稍微修改一下代码,手动return true,就可以继续更新组件了

 shouldComponentUpdate() {
   console.log("shouldComponentUpdate 执行了!");
   return true;
 }

在这里插入图片描述


  • 3、componentWillUpdate(nextProps, nextState)参数不传也完全可以
    shouldComponentUpdate返回true以后,组件进入重新渲染的流程时执行的逻辑。通俗讲就是渲染前的钩子
  • 4、render()
    页面渲染执行的逻辑,render函数把jsx编译为函数并生成虚拟dom,然后通过其diff算法比较更新前后的新旧DOM树,并渲染更改后的节点。
  • 5、componentDidUpdate(prevProps, prevState)参数不传也完全可以
    重新渲染后执行的逻辑。通俗讲就是渲染完毕后的钩子
    在这里插入图片描述

代码(这里只有更新阶段钩子)

<script type="text/babel">
    class A extends React.Component {
      // 给state默认值
      state = {
        car: "宝马",
      };
      // 更新传入值
      changeCar = () => {
        this.setState({ car: "奥迪" });
      };

      shouldComponentUpdate() {
        console.log("A标签的 shouldComponentUpdate 执行了!");
        return true;
      }

      componentWillUpdate() {
        console.log("A标签的 componentWillUpdate 执行了!(组件渲染前)");
        return false;
      }

      componentDidUpdate() {
        console.log("A标签的 componentDidUpdate 执行了!(组件渲染完毕)");
        return false;
      }

      render() {
        console.log("A标签的 render 执行了!");
        return (
          <div>
            <div>A组件{this.state.car}</div>
            <button onClick={this.changeCar}>更新A组件</button>
          </div>
        );
      }
    }
    ReactDOM.render(<A />, document.getElementById("test"));
  </script>
组件卸载(由ReactDOM.unmountComponentAtNode()触发)

最后一个API,在组件卸载之前触发

  • componentWillUnmount()

组件卸载方法:ReactDOM.unmountComponentAtNode()

组件的卸载前执行的逻辑,比如进行“清除组件中所有的setTimeout、setInterval等计时器”或“移除所有组件中的监听器removeEventListener”等操作。

旧版生命周期总结

在这里插入图片描述

1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
		1.	constructor()
		2.	componentWillMount()
		3.	render()
		4.	componentDidMount() =====> 常用
			一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
2. 更新阶段: 由组件内部this.setSate()或父组件render触发
		1.	shouldComponentUpdate()
		2.	componentWillUpdate()
		3.	render() =====> 必须使用的一个,不渲染没法显示
		4.	componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
		1.	componentWillUnmount()  =====> 常用
			一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

新旧生命周期对比

新版本生命周期相对于旧版本,废弃了三个带will的API(componentWillMount(),componentWillReceiveProps(),componentWillUpdate())
新增了两个API static getDerivedStateFromProps(),getSnapshotBeforeUpdate()

在这里插入图片描述
注意:对于已经过时的API不会马上废弃,而是在控制台进行Warning提醒,并且在后续的React版本中,如果非要使用过时的API,就必须在API的前缀上加入UNSAFE_前缀,作为提醒。
比如,从React17版本开始就得加入前缀:
在这里插入图片描述

注意,这里的API UNSAFE并不是说这个API就会有安全问题,而是说在未来的预计更新中有概率出现问题。
比如现在切换到React 17版本,再使用过期API就会有提示
在17版本下,使用过时的componentWillMount,PS:这里选的是不需要条件就可以触发的API,另外两个过时的API触发都需要条件

 componentWillMount() {
   console.log("componentWillMount执行");
 }

在这里插入图片描述

这几个UNSAFE_ 的API本身用的频率就很低,所以了解一下即可

新版生命周期

初始化阶段API

在这里插入图片描述


  • 1、constructor()

完成了React数据的初始化,state设值等等。之前写过就不赘述了


  • 2、static getDerivedStateFromProps()

首先这个组件是静态的,如果不用static,就会报错。看控制台报错,说明这个方法不属于对象,需要用static来进行声明
在这里插入图片描述

组件挂载阶段render前的最后一次调用,并且在初始挂载及后续更新时都会被调用。适用于第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子)。返回一个state就更新state,返回一个null就不做更新动作

可以传入props和state

static getDerivedStateFromProps(props,state){
	console.log('getDerivedStateFromProps',props,state);
	return null
}

在这里插入图片描述

如果这个位置返回一个固定的state的对象,那么这个return的值就会一直影响state,导致其无法更新,因为其return的值是一个固定的state。那肯定就更新不了state了。

 static getDerivedStateFromProps(props, state) {
   console.log("getDerivedStateFromProps", props, state);
   return {"key":"value"};
 }

举一个props影响state的例子,用react的官方例子:
在这里插入图片描述
在这里插入图片描述


  • 3.render()

组件挂载依靠这个api,不render就不会重新渲染,之前说过,这里不赘述了


  • 4.componentDidMount()

组件挂载完毕之后触发的,也就是render之后

//组件挂载完毕的钩子
componentDidMount(){
	console.log('Count---componentDidMount');
}

在这里插入图片描述

更新阶段API

主要集中在这5个钩子
在这里插入图片描述


  • 1.getDerivedStateFromProps()
    贯穿于组件挂载阶段和更新阶段的API,React 会在初始挂载和后续更新时调用 render 之前调用它。它应该返回一个对象来更新 state,或者返回 null 就不更新任何内容。

比如我想做一个点击按钮就+1的,更新state就会触发组件更新,就会触发这个API
在这里插入图片描述

<script type="text/babel">
	//创建组件
	class Count extends React.Component{
		//构造器
		constructor(props){
			console.log('Count---constructor');
			super(props)
			//初始化状态
			this.state = {count:0}
		}

		//加1按钮的回调
		add = ()=>{
			//获取原状态
			const {count} = this.state
			//更新状态
			this.setState({count:count+1})
		}
		
		//若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromProps
		static getDerivedStateFromProps(props,state){
			console.log('getDerivedStateFromProps',props,state);
			return null
		}

		render(){
			console.log('Count---render');
			const {count} = this.state
			return(
				<div>
					<h2>当前求和为:{count}</h2>
					<button onClick={this.add}>点我+1</button>
				</div>
			)
		}
	}
	
	//渲染组件
	ReactDOM.render(<Count count={199}/>,document.getElementById('test'))
</script>

  • 2.shouldComponentUpdate(nextProps, nextState)

和老版本的那个一样,当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。默认返回为true,返回false则阻止更新

控制组件自身或者子组件是否需要更新,尤其在子组件非常多的情况下
在之前的触发state更新的基础上加入API,查看更新时效果

shouldComponentUpdate(props, state) {
  console.log("shouldComponentUpdate 执行", props, state);
  // return false阻止更新
  return false;
}

在这里插入图片描述

如果改为return true,那么就会没有问题,继续让state更新

shouldComponentUpdate(props, state) {
  console.log("shouldComponentUpdate 执行", props, state);
  // return true继续更新
  return true;
}

在这里插入图片描述


  • 3.render()

这个没啥好说的, 前面的"阀门API"如果调用了,并且都return true了 render就会重新执行,如果不调用那就无所谓了,不会影响render()。
如果反过来, 前面的"阀门API"如果调用了,并且return false了,render后续就无法执行。


  • 4.getSnapshotBeforeUpdate()

在最后一次渲染(提交到dom节点)之前调用,getSnapshotBeforeUpdate(prevProps,prevState,),这两个参数就是DOM更新前的参数。
在更新之前获取快照,返回值传递给componentDidUpdate(prevProps,prevState,?snapshotValue)的snapshotValue上面。这个"快照"指的是在组件更新之前捕获的某个状态state或数据props的瞬时影像,可以取这个快照里对象的某一个属性,也可以return一个任意的数值。

如果单用这个getSnapshotBeforeUpdate(),是不行的,要搭配componentDidUpdate()使用,要接收参数的

如果单用getSnapshotBeforeUpdate()的话,控制台就会报警
在这里插入图片描述
两个搭配在一起使用

//在更新之前,render之后获取快照
getSnapshotBeforeUpdate(prevProps,prevState){
	console.log('getSnapshotBeforeUpdate');
	return 'atguigu'
}

//组件挂载完毕的钩子
componentDidUpdate(prevProps,precState,snapshot){
	console.log('componentDidUpdate 执行!',"getSnapshotBeforeUpdate传入的参数",snapshot);
}

在这里插入图片描述


  • 5.componentDidUpdate()

组件更新后触发的函数,和旧版本一样,这里先讨论单独使用componentDidUpdate()的场景
触发一下组件更新操作,触发API
在这里插入图片描述

如果是和getSnapshotBeforeUpdate()配合使用的话,我们将获取到其返回值

 // // 在更新之前,render之后获取快照
 getSnapshotBeforeUpdate(prevProps, prevState) {
   console.log("getSnapshotBeforeUpdate");
   return "atguigu";
 }

 // //组件挂载完毕的钩子
 componentDidUpdate(prevProps, precState, snapshot) {
   console.log("componentDidUpdate 执行 组件更新完毕", snapshot);
 }

点击更新操作
在这里插入图片描述


最后验证一下新版本生命周期钩子的执行顺序
在这里插入图片描述

组件卸载(由ReactDOM.unmountComponentAtNode()触发)
  • componentWillUnmount()

在组件卸载之前触发

组件卸载方法:ReactDOM.unmountComponentAtNode(),但是已经在18版本被取代
在这里插入图片描述
例子:

<script type="text/babel">
  class Count extends React.Component {
    componentWillUnmount() {
      console.log("componentWillUnmount 执行,组件即将卸载");
    }

    unMount=()=>{
      ReactDOM.unmountComponentAtNode(document.getElementById("test"))
    }

    render() {
      return <div><button onClick={this.unMount}>卸载组件</button></div>;
    }
  }

  //渲染组件
  ReactDOM.render(<Count />, document.getElementById("test"));
</script>

在这里插入图片描述

单击button,组件就会卸载,在真正卸载之前就会触发componentWillUnmount()执行
在这里插入图片描述

虚拟DOM与DOM Diffing算法

颗粒度:DOM Diffing算法对比的最小粒度是标签,且逐层对比
在这里插入图片描述

  • diffing算法应用在 react / vue 中,用于比较虚拟DOM和真实DOM。
  • 虚拟DOM中采用的算法,把树形结构按照层级分解,只比较同级元素,不同层级的节点只有创建和删除操作。
  • diffing算法会从根节点开始,一层层的向下比较,如果在某一层的某个节点发现不同了,他就会直接替换这个节点下面的所有子树。
  • 渲染真实DOM所消耗的性能是很大的,很多操作都会导致页面重新渲染。 通过diff算法对比新旧vdom之间的差异,可以最小化的执行dom操作,从而提高代码性能。

Diffing算法简单解析

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

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

相关文章

MUYUCMS v2.1:一款开源、轻量级的内容管理系统基于Thinkphp开发

MuYuCMS&#xff1a;一款基于Thinkphp开发的轻量级开源内容管理系统&#xff0c;为企业、个人站长提供快速建站解决方案。它具有以下的环境要求&#xff1a; 支持系统&#xff1a;Windows/Linux/Mac WEB服务器&#xff1a;Apache/Nginx/ISS PHP版本&#xff1a;php > 5.6 (…

超级简单的springboot整合springsecurity oauth2第三方登录

前言 springboot整合springsecurity oauth2进行第三方登录&#xff0c;例如qq、微信、微博。网上一堆教程&#xff0c;并且很多都是旧版本的&#xff0c;篇幅又长&#xff0c;哔哩吧啦一大堆&#xff0c;就算你搞下来了&#xff0c;等下次版本升级或变更一下&#xff0c;你又不…

5分频【FPGA】

所以数据对齐晶振。 从第一个晶振开始&#xff1a; 5分频&#xff1a; 2.5晶振高电平&#xff0c;2.5晶振低电平 clk1是 32 clk2是23 需要 clk2下降沿【拉低】clk1上升沿【拉高】 clk_out clk1 & clk2; 推荐5分频&#xff1a;

一文带你速通Seata的XA模式

目录 XA规范协议 基本介绍 分布式事务处理模型角色 两阶段提交 Seata的XA的模式 基本介绍 具体使用 小结 XA规范协议 基本介绍 在讲解Seate中的XA模式之前我们先来了解了解什么是XA规范。XA 规范 是 X/Open 组织定义的分布式事务处理&#xff08;DTP&#xff0c;Distr…

计算机毕业设计项目选题推荐(免费领源码)java+Springboot+Mysql邻家优选超市线上线下购物系统小程序92713

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

运维那些事儿|2023年,运维还有出路吗?

作为一名运维&#xff0c;不知道你有没有这样的感受。 觉得自己的工作没什么成长空间。每天装个系统、跑个机房、跑个脚本&#xff0c;忙来忙去也没忙出来什么名堂&#xff0c;含金量低不说&#xff0c;薪资也一直没见涨&#xff0c;所以你开始陷入迷茫&#xff0c;会疑惑&…

第二证券:机构策略:大盘有望继续走出震荡攀升走势

3053点上方途径压力较为明显&#xff0c;短期内打破3053点上方途径需求量能的不断释放&#xff0c;周三两市成交量再度打破万亿&#xff0c;这为后市向上打破奠定了基础&#xff0c;短线大盘打破前期3053点上方途径难以一蹴即至&#xff0c;但先行目标科创100、国证2000现已光复…

【Linux C IO多路复用】多用户聊天系统

目录 Server-Client mutiplexingServer mutiplexingClient mutiplexing Server-Client 在Linux系统中&#xff0c;IO多路复用是一种机制&#xff0c;它允许一个进程能够监视多个文件描述符&#xff08;sockets、pipes等&#xff09;的可读、可写和异常等事件。这样&#xf…

基于RTLS的资产追踪

第1章 什么是资产追踪&#xff1f; 资产跟踪使最终用户能够监控和管理物理对象&#xff0c;无论是在配送中心、制造工厂、仓库还是医疗保健环境中&#xff0c;仅举几个可能的场景。 资产跟踪通常由硬件和软件组成&#xff0c;旨在报告物理对象的状态&#xff0c;特别强调位置…

目标检测标注的时代已经过去了?

在快速发展的机器学习领域&#xff0c;有一个方面一直保持不变&#xff1a;繁琐和耗时的数据标注任务。无论是用于图像分类、目标检测还是语义分割&#xff0c;长期以来人工标记的数据集一直是监督学习的基础。 然而&#xff0c;由于一个创新性的工具 AutoDistill&#xff0c;这…

Kakao账号注册全流程,如何Kakao多开?

Kakao是目前韩国地区最流行的通讯生活服务软件&#xff0c;相当于我们国内的微信&#xff0c;如果您的业务正准备或者正在进军这个区域&#xff0c;那么少不了需要注册并使用这个平台&#xff0c;甚至需要Kakao多开&#xff08;多账号同时管理与使用&#xff09;&#xff0c;本…

C# OpenCvSharp 通过特征点匹配图片

SIFT匹配 SURF匹配 项目 代码 using OpenCvSharp; using OpenCvSharp.Extensions; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text.RegularExpressions; using System.Windows.Forms; using static System.Net…

Presentation Prompter 5.4.2(mac屏幕提词器)

Presentation Prompter是一款演讲辅助屏幕提词器软件&#xff0c;旨在帮助演讲者在公共演讲、主持活动或录制视频时更加流畅地进行演讲。以下是Presentation Prompter的一些特色功能&#xff1a; 提供滚动或分页显示&#xff1a;可以将演讲稿以滚动或分页的形式显示在屏幕上&a…

奇安信360天擎getsimilarlist存在SQL注入漏洞

奇安信360天擎getsimilarlist存在SQL注入漏洞 一、产品描述二、漏洞描述三、漏洞复现1.手动复现2.自动化复现①nulei扫描yaml ②小龙POC检测工具下载地址 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的…

Studio One6最新中文特别版下载安装教程

PreSonus Studio One是PreSonus出品的一款功能强大的音乐创作软件。主要为用户提供音乐创作、录音、编辑、制作等功能。它可以让你创造音乐&#xff0c;无限的轨道&#xff0c;无限的MIDI和乐器轨道&#xff0c;虚拟乐器和效果通道&#xff0c;这些都是强大和完美的。在Studio …

sprinboot使用自定义注解切面 aop aspectj

sprinboot使用自定义注解切面 主要依赖定义注解接口定义切面使用注解打印切面获取参数 主要依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--切面依赖…

时间序列预测:深度学习、机器学习、融合模型、创新模型实战案例(附代码+数据集+原理介绍)

本文介绍->给大家推荐一下我的时间序列预测实战专栏&#xff0c;本专栏平均质量分98分&#xff0c;而且本专栏目前免费阅读。其中涉及机器学习、深度学习、融合模型、个人创新模型、数据分析等一系列有关时间序列的内容&#xff0c;其中的实战案例不仅有简单的模型类似于机器…

STM32F407-Discovery的硬件FPU

本文基于STM32 HAL 库版本&#xff1a;STM32Cube_FW_F4_V1.27.0 1. STM32F407的FPU简介 FPU&#xff1a;Float Point Unit&#xff0c;也就是浮点运算单元。如果是定点 CPU&#xff08;没有 FPU 的 CPU&#xff09;计算浮点数&#xff0c;则按照 IEEE-754 标准&#xff0c;完…

UltraEdit v22.0.0.19(高级文本编辑器)

UltraEdit是一款多功能文本编辑器&#xff0c;该软件功能强大&#xff0c;界面友好&#xff0c;使用方便&#xff0c;支持语法高亮、代码折叠、宏等高级功能&#xff0c;适用于编辑文本、十六进制、ASCII码等多种类型的文件。 UltraEdit v22.0.0.19(高级文本编辑器) UltraEd…