react笔记-04redux篇

redux和react-redux笔记,以及项目中如何使用,对redux的封装,让其使用类似于vuex一样方便。

一、redux

1. redux工作流程

在这里插入图片描述

流程:创建action => dispatch分发action => 交给store => reducer加工数据返回给store

2. redux的三个核心概念

2.1 action

动作对象,包含两个属性:

  • type:标识属性,值为string,唯一,必要属性
  • data:数据属性,值类型任意,可选属性
{ type: 'userInfo', data: { name: 'xiaotian', age: 20 } }

2.2 reducer

用于初始化状态、加工状态。加工时,根据旧的stateaction,产生新的state的纯函数。redux的reducer函数必须是一个纯函数。

纯函数:同样的输入,同样的输出

遵循:

  1. 不得改写参数数据
  2. 不会产生任何副作用,例如:网络请求,输入输出设备
  3. 不能调用Date.now()或者Math.random()等不纯的方法

例如:下面这个函数就不是纯函数

// 传入同样的参数num,每次返回的结果都不相同,所以不是纯函数。
function fn(num) {return Math.random() + num
}

错误写法:

let personList = []
export default function personReducer(preState = personList, action) {const { type, data } = actionswitch (type) {case 'AddPerson':// 不能这样写,会导致personList被改写了,personReducer就不是一个纯函数了,会导致reducx不能识别到数据的改变。personList.unshift(data)return personListdefault:return preState}
}

正确写法:

let personList = []
export default function countReducer(preState = personList, action) {const { type, data } = actionswitch (type) {case 'AddPerson':return [data, ...personList]default:return preState}
}

2.3 store

用于存储数据,有如下方法:

  • getState(): 获取当前的state对象。

  • dispatch(action): 分发action,这是改变state的唯一途径。每个action是一个描述“发生了什么”的普通JavaScript对象。

  • subscribe(() => {}): 注册一个监听器,当state发生改变时,会调用该回调。

3. redux使用

3.1 安装redux

npm install redux

3.2 基本使用

  1. 新建redux目录,在redux目录下新建store.jsxxx.js
  2. store.js
// 引入legacy_createStore,专门用于创建redux中最核心的store对象
import { legacy_createStore } from 'redux'
// 引入为xxx组件服务的reducer
import countReducer from './count_reducer'// 用于暴露一个store对象,整个应用只有一个store
export default legacy_createStore(countReducer)
  1. xxx.js(这里是count_reducer.js

创建一个为xxx组件服务的reducer,reducer的本质就是一个函数

countReducer有两个参数:preState(之前的状态)、action(动作对象)

reducer第一次调用时,是store自动触发的,传递的preState是undefined,action是@@REDUX/INITxxx

export default function countReducer(preState = 0, action) {// 从action对象中获取:type、dataconst { type, data } = action// 根据type决定如何加工数据switch (type) {case 'increment':return preState + data case 'decrement':return preState - datadefault:return preState}
}
  1. getState:获取store中的state数据
store.getState()
  1. dispatchstore派发数据(更新数据)
store.dispatch({ type: 'increment', data: xxx })
  1. subscribe:监听store中的数据变化
store.subscribe(() => {// 调用render,渲染页面
})

组件中使用:

componentDidMount() {store.subscribe(() => {this.setState({})})
}

全局index.js中使用:

import store from './redux/store'const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<React.StrictMode><BrowserRouter><App /></BrowserRouter></React.StrictMode>
)store.subscribe(() => {root.render(<React.StrictMode><BrowserRouter><App /></BrowserRouter></React.StrictMode>)
})

3.3 异步action

  1. action分类:
  • 同步action:一般对象类型,{type: string, data: any}
  • 异步action:函数类型
  1. 异步action的使用:

组件中:

import React, { Component } from 'react'
import store from '../redux/store'
import { createIncrementAction, createAsyncIncrementAction } from '../redux/count_action'export default class count extends Component {handleAsyncIncrement = () => {const { value } = this.selectNumberstore.dispatch(createAsyncIncrementAction(value))}render() {return (<div><h1>当前求和为: {store.getState()}</h1><select ref={c => this.selectNumber = c}><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button onClick={this.handleAsyncIncrement}>异步加</button></div>)}
}

count_action.js中(用于创建action对象):

// 异步action:指action的值是函数,异步action中都会调用同步action去真正的操作数据
export const createAsyncIncrementAction = (data) => {return (dispatch) => {// 由redux调用,传递参数dispatchsetTimeout(() => {dispatch({ type: 'increment', data: data * 1 })}, 1000)}
}

⚠️注意:redux的action默认是不支持函数类型的,需要使用中间件redux-thunk

安装:

npm install redux-thunk

store.js中:

import { legacy_createStore, applyMiddleware } from 'redux'
// 引入redux-thunk,用于支持异步action
import { thunk } from 'redux-thunk'
import countReducer from './count_reducer'export default legacy_createStore(countReducer, applyMiddleware(thunk))

这样就可以使用异步action了。

二、react-redux(类式组件中使用)

在这里插入图片描述

react-redux搭配redux使用步骤:

1. 目录结构

在这里插入图片描述

  • components: 存放UI组件
  • containers: 存放容器组件
  • redux: 存放redux仓库

2. react-redux的基本使用

2.1 redux

store.js: 创建store

import { legacy_createStore, applyMiddleware } from 'redux'
import count_reducer from './count_reducer'
import { thunk } from 'redux-thunk'export default legacy_createStore(count_reducer, applyMiddleware(thunk))

count_reducer.js

export default function countReducer(preState = 0, action) {const { type, data } = actionswitch (type) {case 'ADD':return preState + datadefault:return preState}
}

2.2 containers(容器组件): containers/count.jsx

容器组件的store是靠父组件的props传递进去的(2.3的App.jsx),而不是自己import引入的

// 引入cont的ui组件
import CountUI from '../components/count'
// 引入connect用于连接ui组件和redux
import { connect } from 'react-redux'// 1. mapStateToProps函数的返回的是一个对象
// 2. 返回对象中的key就作为传递给ui组件的props的key,value就作为传递给ui组件props的value
// 3. mapStateToProps函数的本质:传递状态,把状态传递给props
function mapStateToProps(state) {return {count: state}
}// 1. mapDispatchToProps函数的返回的是一个对象
// 2. 返回对象中的key就作为传递给ui组件的props的key,value就作为传递给ui组件props的value
// 3. mapDispatchToProps函数的本质:传递操作状态的方法
function mapDispatchToProps(dispatch) {return {add: () => {console.log('add')dispatch({ type: 'ADD', data: 1 })}}
}// 使用connect()()创建并暴露一CountUI的容器组件
export default connect(mapStateToProps, mapDispatchToProps)(CountUI)

2.3 App.jsx

⚠️注意:这里引入的Count组件是容器组件(2.2 创建的),而不是UI组件

通过props的方式,将store传入给容器组件,在mapStateToProps中就可以获取到statemapDispatchToProps中可获取到dispatch

import React, { Component } from 'react'
import Count from './containers/count'
import store from './redux/store'export default class App extends Component {render() {return <><div><h1>App</h1><Count store={store} /></div></>}
}

2.4 components(UI组件): components/count.jsx

这个时候通过this.props即可获取redux的store仓库中数据和方法(在2.2容器组件定义的数据和方法)

import React, { Component } from 'react'export default class count extends Component {handleAdd = () => {this.props.add()}render() {// console.log('ui组件props', this.props)return (<div><p>num为: {this.props.count}</p><button onClick={this.handleAdd}>+1</button></div>)}
}

3. 优化

3.1 优化1:容器组件mapDispatchToProps的简写

mapDispatchToProps可以是函数,也可以是对象

value只要返回action,react-redux自动dispatch分发action

// 引入cont的ui组件
import CountUI from '../components/count'
// 引入connect用于连接ui组件和redux
import { connect } from 'react-redux'export default connect(state => ({count: state}),// mapDispatchToProps的简写{add: () => ({ type: 'ADD', data: 1 })}
)(CountUI)

3.2 优化2:不用再手动监测redux数据的变化,react-redux自动监测

3.3 优化3:Provider使用

如果有多个容器组件,需要每个容器组件都传入store,就类似这样:

<Count store={store} />
<Demo store={store} />
<Text store={store} />

优化:可以通过Provider向每个容器组件都传入store,在入口文件中如下使用:

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import { Provider } from 'react-redux'
import store from './redux/store.js'ReactDOM.createRoot(document.getElementById('root')).render(<React.StrictMode><Provider store={store}><App /></Provider></React.StrictMode>,
)

需要组件的地方直接使用即可:

<Count />

3.4 整合:UI组件+容器组件

import React, { Component } from 'react'
import { connect } from 'react-redux'// ui组件
class count extends Component {handleAdd = () => {this.props.add()}render() {return (<div><p>num为: {this.props.count}</p><button onClick={this.handleAdd}>+1</button></div>)}
}// 容器组件
export default connect(state => ({count: state}),{add: () => ({ type: 'ADD', data: 1 })}
)(count)

4. 多个reducer的使用

store.js中:

import { legacy_createStore, applyMiddleware, combineReducers } from 'redux'
import count_reducer from './reducers/count'
import person_redercer from './reducers/person'
import { thunk } from 'redux-thunk'// 汇总所有的reducer变成一个总的reducer
const allReducer = combineReducers({count: count_reducer,personList: person_redercer
})export default legacy_createStore(allReducer, applyMiddleware(thunk))

容器组件中:

import React, { Component } from 'react'
import { connect } from 'react-redux'class count extends Component {handleAdd = () => {// 操作状态的方法不需要区分this.props.add()}render() {return (<div><p>num为: {this.props.count}</p><button onClick={this.handleAdd}>+1</button><div>{this.props.personList.length}</div></div>)}
}export default connect(state => ({// state.xxx:xxx是根据store.js中的allReducer中的key值决定的count: state.count,personList: state.personList}),{add: () => ({ type: 'ADD', data: 1 })}
)(count)

5. redux开发者工具的使用

5.1 下载浏览器插件

下载地址:https://chrome.zzzmh.cn/info/lmhkpmbekcpmknklioeibfkpmmfibljd

5.2 项目中安装

npm i redux-devtools-extension

5.3 在store.js中配置

import { legacy_createStore, applyMiddleware } from 'redux'
import count_reducer from './reducers/count'
import { thunk } from 'redux-thunk'
// 引入开发者工具
import { composeWithDevTools } from 'redux-devtools-extension'export default legacy_createStore(count_reducer, composeWithDevTools(applyMiddleware(thunk)))

这样浏览器插件就会亮了。

三、react-redux(函数式组件使用)

1. 可以通过UI组件和容器组件结合的写法:

import { connect } from 'react-redux'const CountUI = (props) => {return (<div><h1>当前求和为:{props.count}</h1><button onClick={props.add}>+1</button></div>)
}function mapStateToProps(state) {return {count: state}
}function mapDispatchToProps(dispatch) {return {add: () => {console.log('add')dispatch({ type: 'ADD', data: 1 })}}
}export default connect(mapStateToProps, mapDispatchToProps)(CountUI)

2. Hooks写法(推荐)

2.1 创建仓库

import { legacy_createStore } from 'redux'
import reducer from './reducer'// window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() 配置redux-devtools
const store = legacy_createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
export default store

2.2 创建reducer(初始化仓库数据,和修改仓库数据)

// 仓库数据
const defaultState = {num: 0
}// 当调用dispatch的时候会触发函数
let reducer = (state = defaultState, action) => {// action:dispatch传递过来的对象//  对数据进行深拷贝let newState = JSON.parse(JSON.stringify(state))switch (action.type) {case 'ADD1':newState.num += 1break;case 'ADD2':newState.num -= action.numbreak;default:break;}return newState
}export default reducer

2.3 在main.js中将store与项目关联

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import { Provider } from 'react-redux'
import store from './store/index.js'ReactDOM.createRoot(document.getElementById('root')).render(<Provider store={store}><App /></Provider>
)

2.4 在组件中获取仓库数据修改仓库数据(2.2关联)

  • 获取仓库数据:通过useSelector获取
  • 修改仓库数据:通过useDispatch获取
import { useSelector, useDispatch } from "react-redux"export default () => {// 通过useSelector获取仓库数据,回调返回一个对象或数组const { num } = useSelector((state) => {return {num: state.num}})// 修改仓库数据const dispatch = useDispatch()const changeNum = () => {// dispatch({type: '字符串', val: 'val可以自定义,也可以不传'})dispatch({type: 'ADD1'})}const changeNum2 = () => {dispatch({type: 'ADD2', val: 2})}return (<div><p>{num}</p><button onClick={changeNum}>num1</button><button onClick={changeNum2}>num2</button></div>)
}

3. 对react-redux的优化

3.1 将state数据抽离

  1. 新建index.js用于存放数据和方法
// index.js 用于存放数据
// src/store/index.js 用于存放num模块数据
export default {state: {num: 0},actions: {ADD1(newState, action) {newState.num += 1},ADD2(newState, action) {newState.num += action.val}},// 名字统一管理actionsName: {add1: 'ADD1',add2: 'ADD2'}
}
  1. reducer.js
// 仓库数据
import handleStore from './index'
const defaultState = {// num: handleStore.state.num 多个属性这么写会很麻烦...handleStore.state
}// 当调用dispatch的时候会触发函数
let reducer = (state = defaultState, action) => {// action:dispatch传递过来的对象//  对数据进行深拷贝let newState = JSON.parse(JSON.stringify(state))switch (action.type) {case handleStore.actionsName.add1:// handleStore.actions.ADD1(newState, action)// 将add1抽离handleStore.actions[handleStore.actionsName.add1](newState, action)break;case handleStore.actionsName.add2:handleStore.actions[handleStore.actionsName.add2](newState, action)break;default:break;}return newState
}export default reducer

页面的使用参考2.4

3.2 仓库模块化

仓库目录结构:

在这里插入图片描述

  • modules:用于对模块进行划分
    • 不同模块目录:
    • index.js:用于存放仓库数据和方法
    • reducer.js:创建不同模块的reducer
  • index.js:redux仓库

拆分优化过程:

  1. index.js进行reducer合并
import { legacy_createStore, combineReducers,  } from 'redux'
import num_reducer from './modules/num/reducer'
import arr_reducer from './modules/arr/reducer'const reducers = combineReducers({num_module: num_reducer,arr_module: arr_reducer
})const store = legacy_createStore(reducers, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
export default store

页面上展示使用:

import { useSelector, useDispatch } from "react-redux"export default () => {const { num } = useSelector((state) => {return {// 需要加上模块名称使用num: state.num_module.num}})const dispatch = useDispatch()const changeNum = () => {dispatch({ type: 'ADD1' })}const changeNum2 = () => {dispatch({ type: 'ADD2', val: 2 })}const { arr } = useSelector((state) => {return {// 需要加上模块名称使用arr: state.arr_module.arr}})const arrPush = () => {dispatch({ type: 'ARRPUSH', val: 40 })}return (<div><p>{num}</p><button onClick={changeNum}>num1</button><button onClick={changeNum2}>num2</button><hr /><p>{arr}</p><button onClick={arrPush}>push</button></div>)
}
  1. 对每个模块的reducer.js中的switch语句进行优化
// 仓库数据
import handleStore from './index'
const defaultState = {// num: handleStore.state.num 多个属性这么写会很麻烦...handleStore.state
}// 当调用dispatch的时候会触发函数
let reducer = (state = defaultState, action) => {// action:dispatch传递过来的对象let newState = JSON.parse(JSON.stringify(state))// 优化前:// switch (action.type) {//     case handleStore.actionsName.add1://         // handleStore.actions.ADD1(newState, action)//         // 将add1抽离//         handleStore.actions[handleStore.actionsName.add1](newState, action)//         break;//     case handleStore.actionsName.add2://         handleStore.actions[handleStore.actionsName.add2](newState, action)//         break;//     default://         break;// }// 优化后for (const key in handleStore.actionsName) {if (action.type === handleStore.actionsName[key]) {handleStore.actions[action.type](newState, action)break}}return newState
}export default reducer
  1. 根据每个模块的index.js中的actions的名字自动生成actionsName,也可以将actionsName进行提取到单独文件统管理
const store = {state: {num: 0},actions: {ADD1(newState, action) {newState.num += 1},ADD2(newState, action) {newState.num += action.val}},// 名字统一管理(最好将key=value=actions的方法名)// actionsName: {// ADD1: 'ADD1',// ADD2: 'ADD2'// }
}let actionsName = {}
for (const key in store.actions) {actionsName[key] = key
}
Object.assign(store, { actionsName })export default store

效果及其如何使用:

  • 效果:做到了只有修改每个模块的index.js中的数据和方法,不去动reducer.js文件,使用起来跟``vuex`一样
  • 复制index.jsreducer.js,在index.jsstate中添加数据,actions添加方法即可;在store/index.js中引入不同模块的reducer

4. 异步action

4.1 跟之前的一样,需要安装redux-thunk

4.2 在store/index.js中配置

import { legacy_createStore, combineReducers, compose, applyMiddleware } from 'redux'
import { thunk } from 'redux-thunk'
import num_reducer from './modules/num/reducer'
import arr_reducer from './modules/arr/reducer'const reducers = combineReducers({num_module: num_reducer,arr_module: arr_reducer
})// 判断是否有__REDUX_DEVTOOLS_EXTENSION__COMPOSE__这个开发者工具模块
let composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION__COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION__COMPOSE__() : composeconst store = legacy_createStore(reducers, composeEnhancers(applyMiddleware(thunk)))
export default store

4.3 组件中使用

import { useSelector, useDispatch } from "react-redux"export default () => {const { num } = useSelector((state) => {return {num: state.num_module.num}})const dispatch = useDispatch()const asyncChangeNum = () => {// 异步用法:dispatch中传入回调dispatch((disp) => {setTimeout(() => {disp({ type: 'add1', val: 1 })}, 1000)})}return (<div><p>{num}</p><button onClick={asyncChangeNum}>num异步+1</button></div>)
}

4.4 优化:将组件内的方法抽取到每个模块的index.js

index.js

const store = {state: {num: 0},actions: {add1(newState, action) {newState.num += action.val}},// 异步方法asyncActions: {asyncAdd1(dispathch) {setTimeout(() => {dispathch({ type: 'add1', val: 1 })}, 1000)}}
}let actionsName = {}
for (const key in store.actions) {actionsName[key] = key
}
Object.assign(store, { actionsName })export default store

组件内:

import { useSelector, useDispatch } from "react-redux"export default () => {const { num } = useSelector((state) => {return {num: state.num_module.num}})const dispatch = useDispatch()const asyncChangeNum = () => {// 异步用法:dispatch中传入回调dispatch(调用asyncAdd1方法即可)}return (<div><p>{num}</p><button onClick={asyncChangeNum}>num异步+1</button></div>)
}

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

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

相关文章

LabVIEW在核磁共振实验室的应用

​核磁共振&#xff08;NMR&#xff09;实验室在进行复杂的核磁共振实验时&#xff0c;需要一个高效、灵活且易于操作的实验控制和数据采集系统。传统的NMR实验系统往往使用专门的硬件和软件&#xff0c;存在系统封闭、扩展性差、维护成本高等问题。为了解决这些问题&#xff0…

揭秘Redis中的高级数据结构:跳跃表Skiplist

Redis数据结构-跳跃表Skiplist 1. 简介1.1. Redis高性能键值存储数据库1.2. Redis的特点和优势1.3. 跳跃表Skiplist 2. 跳跃表的概念和背景2.1 跳跃表的概念2.2 跳跃表的发展历程和提出背景 3. 跳跃表的基本原理3.1 结构概述3.1.1 跳跃表的结构概述3.1.2 跳跃表的节点结构 3.2 …

Stable Diffusion【进阶篇】:真人漫改之迪士尼风格定制

大家好&#xff0c;我是极客菌 关于真人漫改是一个应用比较多的图片定制方向&#xff0c;本文以及后面的章节我们结合一些具体的大模型或者LORA来更深入的实践一下。 一. 迪士尼风格 在SD的大模型中&#xff0c;实现迪士尼或者皮卡斯风格的图片&#xff0c;首推 Disney Pix…

从零开始构建CNN模型

猫狗分类问题——从零开始构建CNN 我们将使用相同的体系结构&#xff0c;并进行一些小的更改&#xff0c;如下所示。 第一个线性层的输入尺寸发生变化&#xff0c;因为猫和狗的图像尺寸是(256,256)。添加了另一个线性层来为模型学习提供更多的灵活性。 让我们来看看实现网络架…

带你学习PID控制算法

#PID涉及相关知识 开环控制系统&#xff1a;开环系统&#xff0c;无反馈系统&#xff0c;即系统的输入不受输出的影响&#xff0c;在受到外界干扰输出效果减小&#xff0c;此时输入也不会增加&#xff0c;因为输出不会对输入施加影响&#xff0c;像是断开的环一样称为开环&…

二自由度机械臂软件系统(一)urdf和moveit2

一、urdf模型 参考链接&#xff1a;https://blog.csdn.net/weixin_45168199/article/details/105755388 这部分直接看参考链接就可以&#xff0c;主要思路如下 1、把sw中的零散零件按照机器人中连杆的分类整合成几个大零件 2、把几个大零件整合成装配体&#xff0c;并设置若干…

eNSP中静态NAT和动态NAT的配置和使用

一、静态NAT 1.拓扑图 a.新建拓扑图 b.PC端配置 PC1: PC2&#xff1a; c.路由器配置 AR1: <Huawei>system-view [Huawei]sysname R1 [R1]interface GigabitEthernet 0/0/0 [R1-GigabitEthernet0/0/0]ip address 192.168.1.254 24 [R1-GigabitEthernet0/0/0]quit…

全网最全图书管理后台系统 ---前端项目简介文档

仅供参考&#xff0c;请勿抄袭 图书管理后台系统 ---前端项目简介 Vue2基础脚手架Request http请求封装(src/utils/request.js)Axios--前端和后端的通信工具前端向后端发送请求&#xff0c;可以把数据传给后端&#xff0c;从后端提取数据 前端跨域解决方案 vue使用request.…

录音怎么转文字更高效?5款软件带你轻松拿捏文本转换~

临近大学生们最难熬的期末考试周&#xff0c;如何在短时间内复习完所有必考的科目也就成为大家迫在眉睫的首要任务。 想要在复习的过程中&#xff0c;更加高效地捕捉和整理关键信息、提高学习效率&#xff0c;那么录音转文字免费应用无疑是你的一大好帮手&#xff01; 倘若你…

关于docker存储overlay2相关问题

报错如下&#xff1a; 报错原因&#xff1a;使用rm -rf 清理overlay2导致的&#xff0c;非正常清理。 正常清理命令如下&#xff1a; # 清理Docker的所有构建缓存 docker builder prune# 删除旧于24小时的所有构建缓存 docker builder prune --filter "until24h"#删…

20240624(周一)欧美股市总结:AI股再熄火!标普纳指连跌三日,英伟达市值跌穿3万亿美元,芯片股指跌3%

市场等待周五的美国PCE重磅通胀数据&#xff0c;今年票委、旧金山联储主席戴利称降息之前“还有更多工作要做”&#xff0c;纳指尾盘加速跳水并收跌1%&#xff0c;但道指五连涨至五周高位。谷歌、微软脱离最高&#xff0c;英伟达跌6.7%为近两个月最差&#xff0c;三天累跌近13%…

vue3-openlayers 点击多边形弹框,高亮多边形,自定义属性传递,鼠标悬浮多边形上动态修改鼠标样式

本篇介绍一下使用vue3-openlayers点击多边形弹框&#xff0c;高亮多边形&#xff0c;自定义属性传递&#xff0c;鼠标悬浮多边形上动态修改鼠标样式 1 需求 加载天地图&#xff0c;polygon传递自定义属性标悬浮在polygon上&#xff0c;根据自定义属性&#xff0c;动态修改鼠标…

web系统数据库敏感数据处理

一、前言 web系统数据库中保存的公民信息不允许明文存储&#xff0c;比如手机号&#xff0c;身份证号&#xff0c;收货地址等。 二、处理方式 数据库中密文存储&#xff0c;web通过注解的方式对数据加解密处理&#xff0c;下面是处理方法 1、编写接口 public interface E…

IIC学习笔记

目录 #I2C涉及相关知识 #I2C相关介绍 欢迎指正&#xff0c;希望对你&#xff0c;有所帮助&#xff01;&#xff01;&#xff01; 个人学习笔记&#xff0c;参考文献&#xff0c;链接最后&#xff01;&#xff01;&#xff01; #I2C涉及相关知识 SDA串行数据线&#xff1a; Ser…

AI降重技术:论文查重率的智能解决方案

现在大部分学校已经进入到论文查重降重的阶段了。如果查重率居高不下&#xff0c;延毕的威胁可能就在眼前。对于即将告别校园的学子们&#xff0c;这无疑是个噩梦。四年磨一剑&#xff0c;谁也不想在最后关头功亏一篑。 查重率过高&#xff0c;无非以下两种原因。要么是作为“…

软通动力携子公司鸿湖万联中标南方电网调峰调频发电有限公司数据采集装置研究开发项目

近日&#xff0c;软通动力携子公司鸿湖万联成功中标南方电网调峰调频发电有限公司数据采集装置研究开发项目。该项目是针对智能化、国产化、自主可控业务需求研制的基于国产芯片、OpenHarmony系统的抽蓄电站机械化施工数据采集设备。本次中标是软通动力布局数字能源战略的一次胜…

大数据组件--Hue

Apache Hue hue是一个集成化的大数据可视化软件&#xff0c;可以通过hue访问浏览操作主流的大数据生态圈软件。hue本身来自于cloudera后来贡献给了apachehue本身是一个web项目&#xff0c;基于python实现的&#xff0c;通过该web项目的UI集成了各个软件的UI 下面是一个hue调度…

【MySQL】如果表被锁可以尝试看一下事务

今天在MySQL中删除表的时候&#xff0c;发现无法删除&#xff0c;一执行drop&#xff0c;navicat就卡死。 通过 SHOW PROCESSLIST显示被锁了 kill掉被锁的进程后依旧被锁 最后发现是由于存在为执行完的事务 SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX; kill掉这些事务以…

EXCEL表格怎么批量删除日期后的时间?

竞价师最近有点忙了&#xff0c;因为百度新出来一个“线索有效性诊断”功能 一、下载电话、表单、咨询表格 二、选中整列 三、选中ctrlf 进行替换&#xff0c;日期输入空格&#xff0c;时间输入*&#xff0c;替换为空即可&#xff01; 四、整列单元格格式“日期”拉倒底部&…

大脑网路分析的进展:基于大规模自监督学习的诊断| 文献速递-先进深度学习疾病诊断

Title 题目 BrainMass: Advancing Brain Network Analysis for Diagnosis with Large-scale Self-Supervised Learning 大脑网路分析的进展&#xff1a;基于大规模自监督学习的诊断 01 文献速递介绍 功能性磁共振成像&#xff08;fMRI&#xff09;利用血氧水平依赖&#x…