redux

news2024/9/23 9:29:18

文章目录

  • redux是什么
  • redux使用情况
  • redux工作原理
    • redux安装
    • redux的3个核心概念
      • Action——形成动作
      • Reducers——操作状态
      • store——存储状态
      • API
      • redux的响应式
    • redux实现加减案例
      • 不使用ActionCreators实现
      • 使用ActionCreators实现
    • 异步Action
  • react-redux
    • 使用
      • 容器组件创建
      • 修改App.jsx在渲染容器组件而不是UI组件
      • UI组件接收容器组件传递过来的属性和方法做相应的修改
      • 优化一:容器组件的简写
      • 优化二:优化store传参、优化检测渲染
      • 优化三:容器组件和UI组件的融合_最终版
      • React-redux的使用总结
  • Redux的多组件共享——实现redux的意义
    • 编写personUI组件
    • 配置Person的redux
    • store引入
    • 编写personUI组件的容器化——实现addPerson
    • 实现Person组件读取Count组件使用的store数据
    • 目录结构
      • 注意:reducers中返回结果的形式
      • 注意:纯函数
  • Redux的开发者工具

redux是什么

  • redux是一个用于做状态管理(即数据管理)的JS库。
    注意:它是JS库不是react的插件库,vue和Angular有都可以使用redux(只是redux和react结合使用的情况比较多,vue有自己专门的状态管理库——vuex
  • 作用:集中式管理react应用中多个组件的共享状态(数据)

redux使用情况

  • 共享:当一个组件中的数据其他组件都需要使用的时候可以使用redux。redux将公共数据进行存储,哪个组件需要使用,直接获取即可。
    在这里插入图片描述
  • 通信:一个组件需要改变另一个组件的状态的时候
    在这里插入图片描述

redux工作原理

在这里插入图片描述

redux安装

npm i redux

redux的3个核心概念

Action——形成动作

包含2个属性

  • type:标识属性,值为字符串,唯一,必要属性
  • data:数据属性,值类型任意,可选属性
    例子: { type: 'ADD_STUDENT',data:{name: 'tom',age:18} }

Reducers——操作状态

用于初始化状态、加工状态。

  • 加工时,根据旧的state和action,产生新的state数据
  • 初始化时,旧的state为undefined,action中的type为@@redux/INITk.s.p.9.6.9
    k.s.p.9.6.9是随机值
    (Reducers的初始化是store自动触发的)

注意: Reducers一般放的都是最基础的操作,不带任何逻辑判断的操作。

store——存储状态

将state、action、reducer联系在一起的对象,使整个redux得以运行

API

  • store.getState() 获取redux中存储的数据
  • store.dispatch({type:'increment',data:value}) 更新redux中的数据
  • store.subscribe(()=>{}) 检测redux中存储的状态是否发生改变,只要redux中所保存的任意一个状态发生改变,都会调用该回调

redux的响应式

注意: react的state中的属性如果使用setState()方法进行更新,react就会重新调用render方法进行页面渲染,实现state中的数据一更新页面中的数据就更新的效果。
但是redux只是一个数据存储库,里面的数更新后react不会重新渲染页面,这就需要我们利用store.subscribe(()=>{})this.setState({})手动重新渲染。

componentDidMount(){
    // 检测redux中状态的变化,只要发生改变就调用render(利用setState方法调用render )
        store.subscribe(()=>{
            // 只要redux中所保存的任意一个状态发生改变,都会调用该回调
            this.setState({})
        })
    }

如果组件过多每个组件都需要添加该段代码,可能有些麻烦。可以直接在index.jsx中直接监听,一旦redux中的状态发生变化就进行整个项目的重新渲染:
index.jsx

import React from "react";
import ReactDOM from "react-dom";
import App from "./App"
import store from "./redux/store"

ReactDOM.render(<App/>, document.getElementById("root"))

store.subscribe(()=>{
  ReactDOM.render(<App/>, document.getElementById("root"))
})

redux实现加减案例

效果:
在这里插入图片描述

不使用ActionCreators实现

代码:
在这里插入图片描述
components/Count/index.jsx

import React, { Component } from 'react'
import store from "../../redux/store"

export default class Count extends Component {
    componentDidMount(){
    // 检测redux中状态的变化,只要发生改变就调用render(利用setState方法调用render )
        store.subscribe(()=>{
            // 只要redux中所保存的任意一个状态发生改变,都会调用该回调
            this.setState({})
        })
    }

    increment=()=>{
        const {value} = this.selectNumber
        store.dispatch({type:'increment',data:value*1})
    }
    decrement=()=>{
        const {value} = this.selectNumber
        store.dispatch({type:'decrement',data:value*1})
    }
    oddIncrement=()=>{
        const count = store.getState()
        const {value} = this.selectNumber
        if(count%2 !== 0) {
            store.dispatch({type:'increment',data:value*1})
        }
    }
    asyncIncrement=()=>{
        const {value} = this.selectNumber
        setTimeout(()=>{
            store.dispatch({type:'increment',data:value*1})
        },500)
    }
    
  render() {
    return (
      <div>
        {/* store.getState()获取state值 */}
        <h2>当前求和为:{store.getState()}</h2>
        <select ref={c => this.selectNumber = c}>
            <option value={1}>1</option>
            <option value={2}>2</option>
            <option value={3}>3</option>
        </select>&nbsp;&nbsp;&nbsp;
        <button onClick={this.increment}>+</button>&nbsp;
        <button onClick={this.decrement}>-</button>&nbsp;
        <button onClick={this.oddIncrement}>当前求和为奇数再+</button>&nbsp;
        <button onClick={this.asyncIncrement}>异步加</button>&nbsp;

      </div>
    )
  }
}

redux/count_reducer.js

// reducer的本质就是一个函数
// reducer接收收到两个参数;之前的状态参数(preState),动作对象(action)
export default function countReducer(preState, action) {
    if(preState === undefined) {
        preState = 99
    }

    const {type, data} = action
    // 根据type决定如何加工数据
    switch(type) {
        case 'increment':
            return preState+data
        case 'decrement':
            return preState-data
        default://初始化
            return preState
    }
}

redux/store.js

// 暴露store对象
import {createStore} from "redux"
import countReducer from "./count_reducer"

export default createStore(countReducer)

App.jsx

import React, { Component } from 'react'
import Count from './components/Count'

export default class App extends Component {
  render() {
    return (
      <div>App
        <Count/>
      </div>
    )
  }
}

index.jsx

import React from "react";
import ReactDOM from "react-dom";
import App from "./App"

ReactDOM.render(<App/>, document.getElementById("root"))

使用ActionCreators实现

在上面代码的基础上添加 count_action.js文件, 并对Count/index.jsx文件做相应修改
redux/count_action.js

import {INCREMENT,DECREMENT} from './const'

// 如果箭头函数的函数体只需要返回一个对象时,简写形式对象需要加上一个括号
export const createIncrementAction = data=>({type:'increment', data})
export const createDecrementAction = data=>({type:'decrement', data})

components/Count/index.jsx

import React, { Component } from 'react'
// 引入store用户获取redux中保存的对象
import store from "../../redux/store"
// 引入actionCreator用于创建action对象
import { createIncrementAction, createDecrementAction } from '../../redux/count_action'

export default class Count extends Component {

    increment=()=>{
        const {value} = this.selectNumber
        store.dispatch(createIncrementAction(value*1))
    }
    decrement=()=>{
        const {value} = this.selectNumber
        store.dispatch(createDecrementAction(value*1))
    }
    oddIncrement=()=>{
        const count = store.getState()
        const {value} = this.selectNumber
        if(count%2 !== 0) {
            store.dispatch(createIncrementAction(value*1))
        }
    }
    asyncIncrement=()=>{
        const {value} = this.selectNumber
        setTimeout(()=>{
            store.dispatch(createIncrementAction(value*1))
        },500)
    }
    
    render() {
        return (
        <div>
            {/* store.getState()获取state值 */}
            <h2>当前求和为:{store.getState()}</h2>
            <select ref={c => this.selectNumber = c}>
                <option value={1}>1</option>
                <option value={2}>2</option>
                <option value={3}>3</option>
            </select>&nbsp;&nbsp;&nbsp;
            <button onClick={this.increment}>+</button>&nbsp;
            <button onClick={this.decrement}>-</button>&nbsp;
            <button onClick={this.oddIncrement}>当前求和为奇数再+</button>&nbsp;
            <button onClick={this.asyncIncrement}>异步加</button>&nbsp;
        </div>
        )
    }
}

异步Action

ActionCreators可以创建两种Action对象:

  • 同步action, 即action的值为对象形式
  • 异步action, 即action的值为函数function形式(开启异步任务的function)
    但是使用异步action必须引用一个中间件redux-thunk进行处理.
    安装 : npm i redux-thunk
    在store.js中引用 :
// 暴露store对象
import {createStore} from "redux"
import countReducer from "./count_reducer"
import {applyMiddleware} from "redux"
import thunk from 'redux-thunk'

export default createStore(countReducer, applyMiddleware(thunk))

异步action中一般都会调用同步action:
eg:

import {INCREMENT,DECREMENT} from './const'
import store from './store'

// 如果箭头函数的函数体只需要返回一个对象时,简写形式对象需要加上一个括号
export const createIncrementAction = data=>({type:INCREMENT, data})
export const createDecrementAction = data=>({type:DECREMENT, data})
// 异步action
export const createIncrementAsyncAction = (data, time)=>{
    return ()=>{
        setTimeout(()=>{
            store.dispatch(createIncrementAction(data))
        },time)
    }
}

还可以简写为

import {INCREMENT,DECREMENT} from './const'

// 如果箭头函数的函数体只需要返回一个对象时,简写形式对象需要加上一个括号
export const createIncrementAction = data=>({type:INCREMENT, data})
export const createDecrementAction = data=>({type:DECREMENT, data})
export const createIncrementAsyncAction = (data, time)=>{
    return (dispatch)=>{
        setTimeout(()=>{
          dispatch(createIncrementAction(data))
        },time)
    }
}

react-redux

  1. 所有的UI组件都应该被一个容器组件包裹,他们是父子关系。
  2. 容器组件是真正和redux打交道的,里面可以随意的使用redux的api。 UI组件中不能使用任何redux的api。
  3. 容器组件会传给UI组件:
  • redux中所保存的状态。
  • 用于操作状态的方法。
    并且均通过props属性传递。
    在这里插入图片描述
    容器组件一般写在containers文件夹中,UI组件一般写在components文件夹中。

使用

容器组件创建

  • 创建containers文件夹,创建容器组件文件如containers/Count/index.jsx
  • 下载react-redux: npm i react-redux
  • 在容器组件中,引入并使用react-redux
    containers/Count/index.jsx
// 引入Count的UI组件
import CountUI from "../../components/Count";

// 引入action
import {
    createIncrementAction,
    createDecrementAction,
    createIncrementAsyncAction } from "../../redux/count_action";

// 引入redux中的store,但是不能通过import引入,需要在父组件中通过组件的props传递过来

// 引入connect用于连接UI组件与redux
import {connect} from 'react-redux'

// mapStateToProps函数返回的对象中的key就作为传递给UI组件props的key,vale就作为传递给UI组件props的value——传递状态
function mapStateToProps(state){
    // state参数,就是从store.getState()中获取的,react-redux直接为我们提供好了
    return {count:state}
}

// mapDispatchToProps函数返回的对象中的key就作为传递给UI组件props的key,vale就作为传递给UI组件props的value——传递操作状态的方法
function mapDispatchToProps(dispatch){
    // diapatch参数,就是从store.dispatch()中获取的
    return {
        increment:data=>dispatch(createIncrementAction(data)),
        decrement:data=>dispatch(createDecrementAction(data)),
        incrementAsync:(data,time)=>dispatch(createIncrementAsyncAction(data, time)),
    }
}

// 创建与UI组件建立联系的容器组件
// const CountContainer = connect()(CountUI)
 export default connect(mapStateToProps, mapDispatchToProps)(CountUI)

修改App.jsx在渲染容器组件而不是UI组件

App.jsx
渲染容器组件而不是UI组件,并将渲染容器所需要的store作为参数传递过去。

import React, { Component } from 'react'
import Count from './containers/Count'
import store from './redux/store'

export default class App extends Component {
  render() {
    return (
      <div>App
        <Count store={store}/>
      </div>
    )
  }
}

UI组件接收容器组件传递过来的属性和方法做相应的修改

components/count/index.jsx

import React, { Component } from 'react'

export default class Count extends Component {
    increment=()=>{
        const {value} = this.selectNumber
        this.props.increment(value*1)
    }
    decrement=()=>{
        const {value} = this.selectNumber
        this.props.decrement(value*1)
    }
    oddIncrement=()=>{
        const {value} = this.selectNumber
        if(this.props.count%2===1){
            this.props.increment(value*1)
        }
    }
    asyncIncrement=()=>{
        const {value} = this.selectNumber
        this.props.incrementAsync(value*1, 500)
    }
    
    render() {
        return (
        <div>
            {/* store.getState()获取state值 */}
            <h2>当前求和为:{this.props.count}</h2>
            <select ref={c => this.selectNumber = c}>
                <option value={1}>1</option>
                <option value={2}>2</option>
                <option value={3}>3</option>
            </select>&nbsp;&nbsp;&nbsp;
            <button onClick={this.increment}>+</button>&nbsp;
            <button onClick={this.decrement}>-</button>&nbsp;
            <button onClick={this.oddIncrement}>当前求和为奇数再+</button>&nbsp;
            <button onClick={this.asyncIncrement}>异步加</button>&nbsp;
        </div>
        )
    }
}

优化一:容器组件的简写

containers/Count/index.jsx

// 引入Count的UI组件
import CountUI from "../../components/Count";

// 引入action
import {
    createIncrementAction,
    createDecrementAction,
    createIncrementAsyncAction } from "../../redux/count_action";

// 引入redux中的store,但是不能通过import引入,需要在父组件中通过组件的props传递过来

// 引入connect用于连接UI组件与redux
import {connect} from 'react-redux'

// 映射状态
// const mapStateToProps = state =>({count:state})

// 映射操作状态的方法
// const mapDispatchToProps = (dispatch)=>(
//     {
//         increment:data=>dispatch(createIncrementAction(data)),
//         decrement:data=>dispatch(createDecrementAction(data)),
//         incrementAsync:(data,time)=>dispatch(createIncrementAsyncAction(data, time)),
//     }
// )

// 创建与UI组件建立联系的容器组件
// const CountContainer = connect()(CountUI)
 export default connect(
    state =>({count:state}),
    // mapDispatchToProps一般写法
    // (dispatch)=>(
    //     {
    //         increment:data=>dispatch(createIncrementAction(data)),
    //         decrement:data=>dispatch(createDecrementAction(data)),
    //         incrementAsync:(data,time)=>dispatch(createIncrementAsyncAction(data, time)),
    //     }
    // )

    // mapDispatchToProps的简写(react-redux自动调用dispatch)
    {
        increment:createIncrementAction,
        decrement:createDecrementAction,
        incrementAsync:createIncrementAsyncAction,
    }
    
    )(CountUI)

优化二:优化store传参、优化检测渲染

src/index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App"
import store from "./redux/store"
import {Provider} from "react-redux" 

ReactDOM.render(
  // Provider为<App/>中的所有容器组件提供一个store,那么容器中无需自己传递store
  <Provider store={store}>
    <App/>
  </Provider>,
  document.getElementById("root")
)

// react-redux可以不用手动检测,容器组件的connect可以检测
// store.subscribe(()=>{
//   ReactDOM.render(<App/>, document.getElementById("root"))
// })

优化三:容器组件和UI组件的融合_最终版

删除components/Count/index.jsx文件

修改container/Count/index.jsx:

// 引入action
import {
    createIncrementAction,
    createDecrementAction,
    createIncrementAsyncAction } from "../../redux/count_action";

import {connect} from 'react-redux'
import React, { Component } from 'react'

// UI组件
class Count extends Component {
    increment=()=>{
        const {value} = this.selectNumber
        this.props.increment(value*1)
    }
    decrement=()=>{
        const {value} = this.selectNumber
        this.props.decrement(value*1)
    }
    oddIncrement=()=>{
        const {value} = this.selectNumber
        if(this.props.count%2===1){
            this.props.increment(value*1)
        }
    }
    asyncIncrement=()=>{
        const {value} = this.selectNumber
        this.props.incrementAsync(value*1, 500)
    }
    
    render() {
        return (
        <div>
            {/* store.getState()获取state值 */}
            <h2>当前求和为:{this.props.count}</h2>
            <select ref={c => this.selectNumber = c}>
                <option value={1}>1</option>
                <option value={2}>2</option>
                <option value={3}>3</option>
            </select>&nbsp;&nbsp;&nbsp;
            <button onClick={this.increment}>+</button>&nbsp;
            <button onClick={this.decrement}>-</button>&nbsp;
            <button onClick={this.oddIncrement}>当前求和为奇数再+</button>&nbsp;
            <button onClick={this.asyncIncrement}>异步加</button>&nbsp;
        </div>
        )
    }
}


// 容器组件
export default connect(
    state =>({count:state}),
    {
        increment:createIncrementAction,
        decrement:createDecrementAction,
        incrementAsync:createIncrementAsyncAction,
    }

)(Count)

React-redux的使用总结

新建container/组件名/index.jsx文件,编写如下内容:

  • 定义UI组件,不暴露
    在UI组件中使用this.props.XXXXX来读取状态和方法
  • 定义容器组件,并进行暴露
    利用connect生成一个容器组件
export default connect(
    // 映射状态
    state =>({count:state}),
    // 映射操作状态的方法(从readux/action中引入)
    {
        increment:createIncrementAction,
        decrement:createDecrementAction,
        incrementAsync:createIncrementAsyncAction,
    }

)(Count)

Redux的多组件共享——实现redux的意义

编写personUI组件

container/Person/index.jsx

import React, { Component } from 'react'
import {nanoid} from 'nanoid' 

export default class Person extends Component {

    addPerson=()=>{
        const name = this.nameNode.value
        const age = this.ageNode.value
        const personObj ={
            id:nanoid(),
            name,
            age
        }
    }
  render() {
    return (
      <div>
        <hr/>
        <h2>Person组件</h2>
        <input ref={c=>this.nameNode=c} type="text" placeholder='请输入名字'></input>
        <input ref={c=>this.ageNode=c} type="text" placeholder='请输入年龄'></input>
        <button onClick={this.addPerson}>添加</button>
      </div>
    )
  }
}

配置Person的redux

  • redux/actions/person.js
import { ADD_PERSON } from "../const";

export const createAddPersonAction =(personObj)=>({type:ADD_PERSON, data:personObj})

  • redux/reducers/person.js
import {INCREMENT,DECREMENT} from '../const'

// reducer的本质就是一个函数
// reducer接收收到两个参数;之前的状态参数(preState),动作对象(action)
export default function countReducer(preState, action) {
    if(preState === undefined) {
        preState = 99
    }

    const {type, data} = action
    // 根据type决定如何加工数据
    switch(type) {
        case INCREMENT:
            return preState+data
        case DECREMENT:
            return preState-data
        default://初始化
            return preState
    }
}

store引入

多个组件必须使用combineReducers进行引入。

// 暴露store对象
import {createStore, combineReducers} from "redux"
// 引入CountReducer
import countReducer from "./reducers/count"
// 引入PersonReducer
import personReducer from "./reducers/count"
import {applyMiddleware} from "redux"
import thunk from 'redux-thunk'

// 汇总所有的Reducer
const allReducer = combineReducers({
    count: countReducer,
    person: personReducer
})
export default createStore(allReducer, applyMiddleware(thunk))

编写personUI组件的容器化——实现addPerson

由于是多个组件,所以需要使用 state =>({person: state.person}),形式进行redux数据的引入

containers/Person/index.jsx

import React, { Component } from 'react'
import {nanoid} from 'nanoid' 
import { connect } from 'react-redux'
import {createAddPersonAction} from '../../redux/actions/person'


class Person extends Component {

    addPerson=()=>{
        const name = this.nameNode.value
        const age = this.ageNode.value
        const personObj ={
            id:nanoid(),
            name,
            age
        }
        this.props.addPerson(personObj)

        this.nameNode.value=""
        this.ageNode.value=""
    }
  render() {
    return (
      <div>
        <hr/>
        <h2>Person组件</h2>
        <input ref={c=>this.nameNode=c} type="text" placeholder='请输入名字'></input>
        <input ref={c=>this.ageNode=c} type="text" placeholder='请输入年龄'></input>
        <button onClick={this.addPerson}>添加</button>
        <ul>
           {
            this.props.person.map((person)=>{
                return <li key={person.id}>{person.name}--{person.age}</li>
            })
           }
        </ul>
      </div>
    )
  }
}

export default connect(
    state =>({person: state.person}),
    {addPerson: createAddPersonAction}
)(Person)

实现Person组件读取Count组件使用的store数据

import React, { Component } from 'react'
import {nanoid} from 'nanoid' 
import { connect } from 'react-redux'
import {createAddPersonAction} from '../../redux/actions/person'


class Person extends Component {

    addPerson=()=>{
        const name = this.nameNode.value
        const age = this.ageNode.value
        const personObj ={
            id:nanoid(),
            name,
            age
        }
        this.props.addPerson(personObj)

        this.nameNode.value=""
        this.ageNode.value=""
    }
  render() {
    return (
      <div>
        <hr/>
        <h2>Person组件</h2>
        <input ref={c=>this.nameNode=c} type="text" placeholder='请输入名字'></input>
        <input ref={c=>this.ageNode=c} type="text" placeholder='请输入年龄'></input>
        <button onClick={this.addPerson}>添加</button>
        <ul>
           {
            this.props.person.map((person)=>{
                return <li key={person.id}>{person.name}--{person.age}</li>
            })
           }
        </ul>
        <h2>上方组件的和:{this.props.count}</h2>
      </div>
    )
  }
}

export default connect(
    state =>({person: state.person,
    count: state.count}),
    {addPerson: createAddPersonAction}
)(Person)

效果:
在这里插入图片描述

目录结构

在这里插入图片描述

注意:reducers中返回结果的形式

reducers中返回的结果:redux会对返回值进行浅比较,如果返回结果和之前的一样就不会更新页面

reducers/person.js

import { ADD_PERSON } from "../const"

const initState=[{id:'001', name:"Tom", age:18}]
export default function personReducer(preState=initState, action){
    const {type, data}= action
    switch(type){
        case ADD_PERSON:
            // preState.unshift(data)
            // return preState
            // 不能使用上述这种方式,因为redux会对返回值进行浅比较,如果返回结果和之前的一样就不会更新页面
            return [data, ...preState]
        default:
            return preState 
    }
    
}

注意:纯函数

定义: 只要同样的输入必定得到同样的输出的函数叫做纯函数。
纯函数必须遵守如下约束:

  • 不得改写参数数据
  • 不会产生任何副作用:不可以发送网络请求、不可以使用输入输出设备
  • 不能调用Data.now()、Math.random()等不纯的方法
    redux的reducer必须是纯函数。

Redux的开发者工具

在这里插入图片描述
配置使用:

  • 安装库:npm i redux-devtools-extension
  • 引入:
    store.js:
// 暴露store对象
import {createStore, combineReducers} from "redux"
// 引入CountReducer
import countReducer from "./reducers/count"
// 引入PersonReducer
import personReducer from "./reducers/person"
import {applyMiddleware} from "redux"
import thunk from 'redux-thunk'

// 引入devtools
import {composeWithDevTools} from "redux-devtools-extension"

// 汇总所有的Reducer
const allReducer = combineReducers({
    count: countReducer,
    person: personReducer
})
export default createStore(allReducer, composeWithDevTools(applyMiddleware(thunk)))

在这里插入图片描述
功能解释:
在这里插入图片描述

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

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

相关文章

干电池升压IC3.3V的电源芯片fs2111/FS2112

干电池升压3.3V的电源芯片FS2111/FS2112 FS2111/FS2112适用于一节干电池升压到3.3V&#xff0c;两节干电池升压3.3V的升压电路&#xff0c;FS2111/FS2112干电池升压IC。 FS2111/FS2112 干电池1.5V和两节干电池3V升压到3.3V的测试数据 两节干电池输出500MA测试&#xff1a; F…

CubeMax添加Rtthread操作系统 组件STM32F103

CubeMax添加Rtthread操作系统 组件STM32F103 本篇主要介绍&#xff0c;怎么使用STM32CubeMx工具&#xff0c;添加RT-Thread操作系统组件&#xff0c;码代码的IDE是keil。快速移植RT-Thread实时操作系统&#xff0c;所用的IDE可自行官网下载最新版。 CubeMax官网下载链接 RTthre…

Ajax(六)

1. XMLHttpRequest的基本使用——URL编码与解码 1.1 什么是URL编码 1.2 如何对URL进行编码与解码 <body><script>var str 黑马程序员//对str编码var str2 encodeURI(str)console.log(str2)//一个汉字对应三个百分号&#xff0c;反解码从console里头复制console.…

js解决单线程之路 - worker的使用分析

写在前面 今天写一个关于实现多线程的东西&#xff0c;都知道js是一个单线程的语言&#xff0c;所谓的单线程就是一次只能做一件事&#xff0c;多线程就是一次可以做很多件事&#xff0c;当然目前我们的电脑等设备很少会有单线程了&#xff0c;比如我们的电脑一般都是标的6核12…

stm32f103zet6的GPIO基础知识

IO数量 16*7112个&#xff0c;GPIOA~GPIOG7组,共144个引脚 IO模式 很多IO口既可以做为输入&#xff0c;也可以做为输出 输入模式 VSS指的是地&#xff0c;VDD是高电平&#xff0c; MOS英文全称为Metal-Oxide-Semiconductor。 意思为金属-氧化物-半导体&#xff0c;而拥有这…

Python画一棵茂盛的分形树

文章目录前情回顾添加分岔茂盛的分形树前情回顾 上次画了一棵分形树&#xff1a;用Python画一棵分形树&#xff0c;得到的图如下 发现看的人还是挺多的&#xff0c;但没什么人点赞&#xff0c;这说明我能给大家画分形树&#xff0c;大家很高兴&#xff0c;但这棵树太秃了&…

[附源码]Python计算机毕业设计调查问卷及调查数据统计系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

在Ubuntu上搭建Nexus服务

介绍 Nexus&#xff1a;Nexus 是一个强大的 Maven 仓库管理器&#xff0c;它极大地简化了自己内部仓库的维护和外部仓库的访问。如Android远程仓库依赖&#xff0c;Java服务端应用程序依赖等&#xff0c;都很方便。 Docker方式 准备 ubuntu上已经安装docker&#xff0c;docker安…

20221218解决在Ubuntu18.04下编译Firefly的Core-3588J出现lz4的问题

20221218解决在Ubuntu18.04下编译Firefly的Core-3588J出现lz4的问题 2022/12/18 15:37 解决方法&#xff1a;编译最新的lz4的dev分支&#xff01; https://wiki.t-firefly.com/zh_CN/Core-3588J/android_compile_android12.0_firmware.html Core-3588J产品规格书 3. 编译 Andro…

Bootstrap5 小工具

Bootstrap 5 提供了很多有用的类来帮组我们快速实现效果&#xff0c;不需要重复写一些 CSS 代码。 背景颜色 设置不同元素的背景颜色时&#xff0c;需要通过 .text-* 类来设置匹配的文本颜色&#xff1a; 实例 <div class"p-3 mb-2 bg-primary text-white">.…

跟老韩学JAVA——IDEA基本使用和快捷键

1. IDEA介绍 2.IDEA下载和安装 这个博主的下载安装介绍的很详细了&#xff0c;我就不过多介绍了 3.IDEA的基本使用 1&#xff09;修改字体大小 File -> Settings -> Editor -> Font -> Size 2)修改字体变粗 3)修改背景颜色 4) 修改菜单栏字体大小 5&#xff…

滑动窗口思想练习题

文章目录1. 找到字符串中所有字母异位词做法一&#xff1a;采用两个数组分别记录字符出现频次做法二&#xff1a;采用diff记录s和p字符串中字符的频次差2. 串联所有单词的子串个人理解&#xff0c;如有异议&#xff0c;欢迎指正&#xff01;1. 找到字符串中所有字母异位词 题目…

XiaoMi手机MIX 2S线刷固件和刷入Recovery

mix 2s 固件下载地址 https://web.vip.miui.com/page/info/mio/mio/detail?postId4865868&app_versiondev.20051 miflash线刷工具下载地址 https://miuiver.com/miflash/ 安装miflash线刷工具 点击安装驱动 打开miflash 手机关机按音量下加开机键进入bootloader&#xf…

Spring boot整合rocketmq(windows)

目录 1.环境搭建 2.命名服务器和业务服务器的启动 3.名词说明 4.执行步骤 5.示例 1.导入依赖 2.配置(至少指定下面两个) 3.代码 6.常见问题 1.环境搭建 下载地址&#xff1a;https://rocketmq.apache.org/解压缩进行安装&#xff0c;默认服务端口&#xff1a;9876 环…

执行 select ... for update 语句,如果查询条件没有索引字段的话,是加行锁还是加表锁?

大家好&#xff0c;我是小林。 昨天在群里看到大家在讨论一个 MySQL 锁的问题&#xff0c;就是执行 select … for update 语句&#xff0c;如果查询条件没有索引字段的话&#xff0c;是加「行锁」还是加「表锁」&#xff1f; 如果你做过这个实验的话&#xff0c;你会发现执行…

数据结构刷题训练营1

开启蓝桥杯备战计划&#xff0c;每日练习算法一题&#xff01;&#xff01;坚持下去&#xff0c;想必下一年的蓝桥杯将会有你&#xff01;&#xff01; 笔者是在力扣上面进行的刷题&#xff01;&#xff01;由于是第一次刷题&#xff01;找到的题目也不咋样&#xff01;所以&a…

SPRING-了解3-注解

IOC容器操作Bean 注解格式&#xff1a;注解名称(属性名称属性值,属性名称属性值) 放在类&#xff0c;方法&#xff0c;属性都可以 目的&#xff1a;简化XML配置 对象创建四大注解 1&#xff09;用的位置不是强制的 Component 最普通 Service 用在service层 Controlle…

接口测试(十)—— telnet和python代码测试dubbo接口

目录 一、传智健康项目介绍 1、项目描述 2、目标用户群体 3、项目模块 4、系统框架 二、Dubbo接口测试 1、RPC 2、Dubbo 3、查阅API文档 三、Telnet工具远程调用 1、启用telnet 2、telnet远程连接服务 3、telnet调用服务接口 四、python借助dubbo远程调用 1、安…

MySQL~JDBC

10、JDBC&#xff08;重点&#xff09; 10.1、数据库驱动 驱动&#xff1a;声卡、显卡、数据库 我们的程序会通过 数据库 驱动&#xff0c;和数据库打交道&#xff01; 10.2、JDBC SUN公司为了简化 开发人员的&#xff08;对数据库的统一&#xff09;操作&#xff0c;提供了…

剑指offer常见题 - 链表问题(一)

二叉树相关算法 链表相关知识点&#xff1a; 链表是一种物理存储单元上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 知识点一&#xff1a;链表由一系列结点&#xff08;链表中每一个元素称为结点&#xff09;组成&#xff0c;…