React-Hooks 和 React-Redux

news2024/11/29 22:48:51

Hooks基本介绍-------------------------

  • Hooks:钩子、钓钩、钩住, Hook 就是一个特殊的函数,让你在函数组件中获取状态等 React 特性 ,是 React v16.8 中的新增功能

  • 作用:为函数组件提供状态、生命周期等原本 class 组件中提供的 React 功能

    • 可以理解为通过 Hooks 为函数组件钩入 class 组件的特性

  • 注意:Hooks 只能在函数组件中使用,自此,函数组件成为 React 的新宠儿

React v16.8 版本前后,组件开发模式的对比:

  • React v16.8 以前: class 组件(提供状态) + 函数组件(展示内容)

  • React v16.8 及其以后:

    1. class 组件(提供状态) + 函数组件(展示内容)

    2. Hooks(提供状态) + 函数组件(展示内容)

    3. 混用以上两种方式:部分功能用 class 组件,部分功能用 Hooks+函数组件

总结

注意1:虽然有了 Hooks,但 React 官方并没有计划从 React 库中移除 class

注意2:有了 Hooks 以后,不能再把函数组件称为无状态组件了,因为 Hooks 为函数组件提供了状态

为什么要有 Hooks

  • 组件的状态逻辑复用
    • 在 Hooks 之前,组件的状态逻辑复用经历了:mixins(混入)、HOCs(高阶组件)、render-props 等模式

    • (早已废弃)mixins 的问题:1 数据来源不清晰 2 命名冲突

    • HOCs、render-props 的问题:重构组件结构,导致组件形成 JSX 嵌套地狱问题

  • class 组件自身的问题
    • 选择:函数组件和 class 组件之间的区别以及使用哪种组件更合适

    • 需要理解 class 中的 this 是如何工作的

    • 相互关联且需要对照修改的代码被拆分到不同生命周期函数中

    • 相比于函数组件来说,不利于代码压缩和优化,也不利于 TS 的类型推导

注意:

之前的react语法并不是以后就不用了,class 组件相关的 API 在hooks中可以不用

  • class 自身语法,比如,constructor、static 等
  • 钩子函数,componentDidMountcomponentDidUpdatecomponentWillUnmount
  • this 相关的用法

useState-Hooks

useState-基本使用

  • useState作用:为函数组件提供状态(state),不能在类组件中调用

  • useState使用场景:当你想要在函数组件中,使用组件状态时,就要使用 useState Hook 了

  • 约定:修改状态的函数名称以 set 开头,后面跟上状态的名称

  • 多次调用 useState 多个状态和修改状态的函数之间不会相互影响

  • useState 提供的状态,是函数内部的局部变量,可以在函数内的任意位置使用

  • 每次渲染,useState 获取到的都是最新的状态值(react会记住最新的状态值),useState 的初始值(参数)只会在组件第一次渲染时生效

语法:

import { useState } from 'react'

// 参数:状态初始值可以是任意值
// 返回值:stateArray 是一个数组
const stateArray = useState(0)

// 索引 0 表示:状态值(state)
const state = stateArray[0]
// 索引 1 表示:修改状态的函数(setState(newValue)` 是一个函数,参数表示:*新的状态值*)
const setState = stateArray[1]

状态的读取和修改:

  • 读取状态

const Counter = () => {
  const [user, setUser] = useState({ name: 'jack', age: 18 })
  
  return (
      <div>
        <p>姓名:{user.name}</p>
            <p>年龄:{user.age}</p>
    </div>
  )
}

  • 修改状态
    • 调用该函数后,将使用新的状态值替换旧值
    • 修改状态后,因为状态发生了改变,所以,该组件会重新渲染
    • setUser(newValue) 是一个函数,参数表示:新的状态值 。调用这个函数,新的状态值会覆盖原来的状态值,所以,这里和class的setState不一样,区分一下,class的setState需要修改哪个值就传哪个值,内部会做状态的合并,hooks呢修改状态值会直接覆盖不会合并,所以hooks修改状态值需要先对原来的值进行取值解构,再修改。
const Counter = () => {
  // 利用数组解构提取状态和修改状态
  const [user, setUser] = useState({ name: 'jack', age: 18 })
  
  const onAgeAdd = () => {
    setUser({
      ...user,
      age: user.age + 1
    })
  }
  
  return (
  	<div>
    	<p>姓名:{user.name}</p>
			<p>年龄:{user.age}</p>
     	<button onClick={onAgeAdd}>年龄+1</button>
    </div>
  )
}

useState-使用规则

  • 如何为函数组件提供多个状态?

    • 调用 useState Hook 多次即可,每调用一次 useState Hook 可以提供一个状态

    • useState Hook 多次调用返回的 [state, setState],相互之间,互不影响

  • useState 等 Hook 的使用规则:

    • React Hooks 只能直接出现在 函数组件 中

    • React Hooks不能嵌套在 if/for/其他函数 中

    • 原理:React 是按照 Hooks 的调用顺序来识别每一个 Hook,如果每次调用的顺序不同,导致 React 无法知道是哪一个 Hook

useEffect-Hooks

useEffect-基本含义

  • 作用:处理函数组件中的副作用(side effect)
  • 副作用是相对于主作用来说的,一个功能(比如,函数)除了主作用,其他的作用就是副作用 对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)
  • 常见的副作用(side effect):数据(Ajax)请求、手动修改 DOM、localStorage、console.log 操作等
  • useEffect完全指南:useEffect 完整指南 — Overreacted

useEffect-基本使用

  • 使用时机

import { useEffect } from 'react'

// 1 
// 触发时机: 第一次渲染会执行 、 每次组件重新渲染都会再次执行
// componentDidMount + ComponentDidUpdate
useEffect(() => {})

// 2(使用频率最高)
// 触发时机:只在组件第一次渲染时执行
// componentDidMount
useEffect(() => {}, [])

// 3(使用频率最高)
// 触发时机:1 第一次渲染会执行 2 当 count(某个状态) 变化时才会次执行
// componentDidMount + componentDidUpdate(判断 count 有没有改变)
useEffect(() => {}, [count])

// 4
useEffect(() => {
  // 返回值函数的执行时机:组件卸载时
  // 在返回的函数中,清理工作
  return () => {
  	// 相当于 componentWillUnmount
  }
}, [])

//5
useEffect(() => {
  
  // 返回值函数的执行时机:1 组件卸载时 2 count 变化时
  // 在返回的函数中,清理工作
  return () => {}
}, [count])
  • 发送请求

  • 在组件中,可以使用 useEffect Hook 来发送请求(side effect)获取数据

  • 注意:effect 只能是一个同步函数,不能使用 async

    • 因为如果 effect 是 async 的,此时返回值是 Promise 对象。这样的话,就无法保证清理函数被立即调用

  • 为了使用 async/await 语法,可以在 effect 内部创建 async 函数,并调用

// 错误演示:不要给 effect 添加 async
useEffect(async () => {
  const res = await axios.get('http://xxx')
  return () => {}
}, [])

// 正确使用
useEffect(() => {
  const loadData = async () => {
    const res = await axios.get('http://xxx')
  }
  loadData()
  
  return () => {}
}, [])

useContext-Hooks

作用

  • 在函数组件中,获取 Context 中的值。要配合 Context 一起使用。

语法

  • useContext 的参数:Context 对象,即:通过 createContext 函数创建的对象

  • useContext 的返回值:Context.Provider 中提供的 value 数据

import { useContext } from 'react'

const { color } = useContext(ColorContext)

useContext Hook<Context.Consumer> 的区别:获取数据的位置不同

  • <Context.Consumer>:在 JSX 中获取 Context 共享的数据

  • useContext:在 JS 代码 或者 JSX 中获取 Context 的数据

const ColorContext = createContext()

const Child = () => {
  // 在普通的 JS 代码中:
  const { color } = useContext(ColorContext)

  return (
    <div>
      useContext 获取到的 color 值:{ color }
      {/* 在 JSX 中: */}
    	<ColorContext.Consumer>
        {color => <span>共享的数据为:{color}</span>}
      </ColorContext.Consumer>
    </div>
  )
}

useState-useRef

useRef-用法

  • 参数:在获取 DOM 时,一般都设置为 null(获取 DOM 对象时,如果拿不到 DOM 对象,此时,获取到的值就是 null)

  • 返回值:包含 current 属性的对象。

  • 注意:只要在 React 中进行 DOM 操作,都可以通过 useRef Hook 来获取 DOM(比如,获取 DOM 的宽高等)

  • 注意:useRef不仅仅可以用于操作DOM,还可以操作组件

import { useRef } from 'react'

const App = () => {
  // 1 使用useRef能够创建一个ref对象
  const inputRef = useRef(null)

  const add = () => {
    // 3 通过 inputRef.current 来访问对应的 DOM
    console.log(inputRef.current.value)
    inputRef.current.focus()
  }
  
  return (
    <section className="todoapp">
      {/* 2 将 ref 对象设置为 input 的 ref 属性值。目的:将 ref 对象关联到 input 对应的 DOM 对象上 */}
      <input type="text" placeholder="请输入内容" ref={inputRef} />
      <button onClick={add}>添加</button>
    </section>
  )
}

export default App

Redux基本介绍------------------------

作用:集中式存储和管理应用的状态、处理组件通讯问题时,无视组件之间的层级关系、简化大型复杂应用中组件之间的通讯问题、数据流清晰,易于定位 Bug

Redux核心概念

为了让代码各部分职责清晰、明确,Redux 代码被分为三个核心概念:action/reducer/store

action(动作)

  • 描述要做的事情,特点:只描述做什么

  • 是一个js对象必须带有type属性,用于区分动作的类型

  • 根据功能的不同,可以携带额外的payload有效的载荷参数数据来完成相应功能

  • 例如 计数器功能描述
    { type: 'increment', payload: 10 } // +10
    { type: 'decrement', payload: 10 } // -10
  •  为了使action功能 多元并且灵活化,需要使用 action creator 函数去创建action,目的:简化多次使用 action 时,重复创建 action 对象,函数返回值依然是个action对象。
  • const decrement = payload => ({ type: 'decrement', payload })

reducer(函数)

  • 用来处理 action 并更新状态,是 Redux 状态更新的地方
  • 函数签名为:(prevState, action) => newState

  • 接收上一次的状态和 action 作为参数,根据 action 的类型,执行不同操作,最终返回新的状态,注意:该函数一定要有返回值,即使状态没有改变也要返回上一次的状态

  • 约定:reducer 是一个纯函数(相同的输入总是得到相同的输出),并且不能包含 side effect 副作用(比如,不能修改函数参数、不能修改函数外部数据、不能进行异步操作等)

  • 对于 reducer 来说,为了保证 reducer 是一个纯函数,不要:

    1. 不要直接修改参数 state 的值(也就是:不要直接修改当前状态,而是根据当前状态值创建新的状态值)

    2. 不要使用 Math.random() / new Date() / Date.now() / ajax 请求等不纯的操作

    3. 不要让 reducer 执行副作用(side effect)

  • // 示例:
    // state 上一次的状态
    // action 当前要执行的动作
    const reducer = (state=10, action) => {
      switch (action.type) {
        // 计数器增加
        case 'increment':
          // 返回新状态
          // return state + 1
          // 根据 action 中提供的 payload 来决定到底增加多少
          return state + action.payload
          // 注意:一定要有 default,如果将来 reducer 无法处理某个 action,
             就直接将上一次的状态返回即可
        default:
          return state
      }
    }

store(仓库)

  • 整合 action 和 reducer,一个应用只有一个 store

  • 维护应用的状态,获取状态:store.getState()

  • 发起状态更新时,需要分发 action:store.dispatch(action)

  • 创建 store 时接收 reducer 作为参数const store = createStore(reducer)

  • 订阅(监听)状态变化:const unSubscribe = store.subscribe(() => {})

  • 取消订阅状态变化: unSubscribe()

核心代码

import {createStore} from 'redux'

// 创建 store
// 参数为:reducer 函数
const store = createStore(reducer)

// 更新状态
// dispatch 派遣,派出。表示:分发一个 action,也就是发起状态更新
store.dispatch(action)
store.dispatch( increment(2) )

// 获取状态
const state = store.getState()

// 其他 API------
// 监听状态变化
const unSubscribe = store.subscribe(() => {
  // 状态改变时,执行相应操作
  // 比如,记录 redux 状态
  console.log(store.getState())
})

// 取消监听状态变化
unSubscribe()

Redux获取状态默认值执行过程

  • 只要创建 store,给createStore(传递了 reducer),那么,Redux 就会调用一次 reducer
  • Redux 内部第一次调用 reducer: reducer的默认传值的type和payload为     (undefined, {type: "@@redux/INITv.a.4.t.t.p"})
  • 因为传入的状态值是 undefined ,并且是一个随机的 action type,因为是一个随机的 action type,所以,reducer 中 switch 一定无法处理该 action,那就一定会走 default。也就是直接返回了状态的默认值:10
  • Redux 内部拿到状态值store.getState()(比如,此处的 10)以后,就用这个状态值,来作为了 store 中状态的默认值

Redux代码执行流程

  1. 创建 store 时,Redux 就会先调用一次 reducer,来获取到默认状态(10)

  2. 然后分发动作 store.dispatch(action)更新状态

  3. 只要调用了dispatch操作,Redux store 内部就会调用 reducer 传入:上一次的状态(当前示例中就是:10)和当前传入的 action({ type: 'increment' }),计算出新的状态并返回

  4. reducer 执行完毕后,将最新的状态交给 store,store 用最新的状态替换旧状态,状态更新完毕

import { createStore } from 'redux'
const store = createStore(reducer)

// reducer(10, { type: 'increment' })
function reducer(state = 10, action) {
  console.log('reducer:', state, action)
  switch (action.type) {
    case 'increment':
      return state + 1
    default:
      return state
  }
}

console.log('状态值为:', store.getState()) // 10

// 发起更新状态:
// 参数: action 对象
store.dispatch({ type: 'increment' })
// 相当于: reducer(10, { type: 'increment' })

console.log('更新后:', store.getState()) // 11

React-Redux介绍

react-redux 库是 Redux 官方提供的 React 绑定库,为 React 接入 Redux,实现在 React 中使用 Redux 进行状态管理。 React 和 Redux 是两个独立的库,两者之间职责独立。因此,为了实现在 React 中使用 Redux 进行状态管理 ,就需要一种机制,将这两个独立的库关联在一起。这时候就用到 React-Redux 这个绑定库了。

react-redux 文档

react-redux 的使用分为两大步:

1 全局配置(只需要配置一次)

  1. 安装 react-redux:  yarn add react-redux  

  2. 从 react-redux 中导入 Provider 组件

  3. 导入创建好的 redux 仓库

  4. 使用 Provider 包裹整个应用

  5. 将导入的 store 设置为 Provider 的 store 属性值

index.js

// 导入 Provider 组件
import { Provider } from 'react-redux'
// 导入创建好的 store
import store from './store'

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector('#root')
)

2 组件接入(获取状态或修改状态)

获取状态:useSelector hook

  • useSelector:获取 Redux 提供的状态数据

  • 参数:selector 函数,用于从 Redux 状态中筛选出需要的状态数据并返回

  • 返回值:筛选出的状态

import { useSelector } from 'react-redux'

const App = () => {
  const count = useSelector(state => state)
  
  return (
  	<div>
    	<h1>计数器:{count}</h1>
      <button>数值增加</button>
			<button>数值减少</button>
    </div>
  )
}

修改状态:useDispatch hook

  • useDispatch:拿到 dispatch 函数,分发 action,修改 redux 中的状态数据

import { useDispatch } from 'react-redux'

const App = () => {
  const dispatch = useDispatch()
  
  return (
  	<div>
    	<h1>计数器:{count}</h1>
      {/* 调用 dispatch 分发 action */}
      <button onClick={() => dispatch(increment(2))}>数值增加</button>
			<button onClick={() => dispatch(decrement(5))}>数值减少</button>
    </div>
  )
}

总结

  • 任何一个组件都可以直接接入 Redux,也就是可以直接:1 修改 Redux 状态 2 接收 Redux 状态

  • 并且,只要 Redux 中的状态改变了,所有接收该状态的组件都会收到通知,也就是可以获取到最新的 Redux 状态

  • 这样的话,两个组件不管隔得多远,都可以直接通讯了  

redux数据流动过程:

Redux应用

代码结构

 /store        --- 在 src 目录中创建,用于存放 Redux 相关的代码
   /actions    --- 存放所有的 action
   /reducers   --- 存放所有的 reducer
   index.js    --- redux 的入口文件,用来创建 store

Redux应用

ActionType

  • Action Type 指的是:action 对象中 type 属性的值

  • Redux 项目中会多次使用 action type,比如,action 对象、reducer 函数、dispatch(action) 等

  • 目标:集中处理 action type,保持项目中 action type 的一致性

  • action type 的值采用:'domain/action'(功能/动作)形式,进行分类处理,比如,

    • 计数器:'counter/increment' 表示 Counter 功能中的 increment 动作

    • 登录:'login/getCode' 表示登录获取验证码的动作

    • 个人资料:'profile/get' 表示获取个人资料

步骤

  1. 在 store 目录中创建 actionTypes 目录或者 constants 目录,集中处理

  2. 创建常量来存储 action type,并导出

  3. 将项目中用到 action type 的地方替换为这些常量,从而保持项目中 action type 的一致性

// actionTypes 或 constants 目录:

const increment = 'counter/increment'
const decrement = 'counter/decrement'

export { increment, decrement }

// --

// 使用:

// actions/index.js
import * as types from '../acitonTypes'
const increment = payload => ({ type: types.increment, payload })
const decrement = payload => ({ type: types.decrement, payload })

// reducers/index.js
import * as types from '../acitonTypes'
const reducer = (state, action) => {
  switch (action.type) {
    case types.increment:
      return state + 1
    case types.decrement:
      return state - action.payload
    default:
      return state
  }
}
  • 注:额外添加 Action Type 会让项目结构变复杂,此操作可省略 ( 大型项目推荐使用 ) 。但,domain/action 命名方式强烈推荐!

Redux应用

Reducer的分离与合并

  • 随着项目功能变得越来越复杂,推荐 使用多个 reducer:按照项目功能划分,每个功能使用一个 reducer 来处理该功能的状态更新
  • 项目中会有多个 reducer,但是 store 只能接收一个 reducer,因此,需要将多个 reducer 合并为一根 reducer,才能传递给 store
  • 合并方式:使用 Redux 中的 combineReducers 函数

  • 注意:合并后,Redux 的状态会变为一个对象,对象的结构与 combineReducers 函数的参数结构相同

    • 比如,此时 Redux 状态为:{ a: aReducer 处理的状态, b: bReducer 处理的状态 }

  •  整个 Redux 应用的状态变为了对象,但是,对于每个 reducer 来说,每个 reducer 只负责整个状态中的某一个值,每个reducer只负责自己要处理的状态

  • 合并 reducer 后,redux 处理方式:只要合并了 reducer,不管分发什么 action,所有的 reducer 都会执行一次。各个 reducer 在执行的时候,能处理这个 action 就处理,处理不了就直接返回上一次的状态。所以,我们分发的某一个 action 就只能被某一个 reducer 来处理,也就是最终只会修改这个 reducer 要处理的状态,最终的表现就是:分发了 action,只修改了 redux 中这个 action 对应的状态!

import { combineReducers } from 'redux'

// 计数器案例,状态默认值为:0
const aReducer = (state = 0, action) => {}
// Todos 案例,状态默认值为:[]
const bReducer = (state = [], action) => {}

// 合并多个 reducer 为一个 根reducer
const rootReducer = combineReducers({
  aReducer: aReducer,
  bReducer: bReducer
})

// 创建 store 时,传入 根reducer
const store = createStore(rootReducer)

// 此时,合并后的 redux 状态: { a: 0, b: [] }



reducer状态合并后,再次访问每个状态的时候,这个状态就是合并后的对象了,需要.上对象访问状态
import { useSelector } from 'react-redux'

const App = () => {
  const count = useSelector(state => state.aReducer)
  const list = useSelector(state => state.bReducer)
}

注释:(个人针对redux的理解叙述)

  • const increment= payload => ({ type: 'increment', payload })
  • redux作为一个状态管理工具,将数据的状态分为了三部分,action、reducers和store
  • action作为一个描述数据用途的对象, { type: 'increment', payload: 10 },这里可以将这个用途对象理解为一个标志,increment就是计数器增加的标志,表示将来需要增加的标识
  • 当我们进行点击行为增加数据的时候,会调用store就会调用这个增加的标识store.dispacth(increment())
  • store.dispatch发起状态更新后,只要调用了dispatch操作,Redux store 内部就会调用 reducer 并且传入上一次的状态和当前传入的 action标识,相当于会给reduce分发一个状态标志"increment",从而使用switch函数进行标识的配对,分发正确的逻辑内容,计算出新的状态并返回
  • reducer 执行完毕后,将最新的状态交给 store,store 用最新的状态替换旧状态,状态更新完

注:

redux在这里 createStore 的使用已经过时,想要了解数据分发传递的实验过程可以参考上面,新的用法逻辑提现在新的文章中...

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

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

相关文章

51、基于注解方式开发Spring WebFlux,实现生成背压数据,就是实现一直向客户端发送消息

★ Spring WebFlux的两种开发方式 1. 采用类似于Spring MVC的注解的方式来开发。此时开发时感觉Spring MVC差异不大&#xff0c;但底层依然是反应式API。2. 使用函数式编程来开发★ 基于注解开发Spring WebFlux 开发上变化并不大&#xff0c;主要是处理方法的返回值可使用Mon…

Devos勒索病毒:网络安全的新威胁,勒索病毒解密,数据恢复

随着信息技术的飞速发展&#xff0c;网络安全问题日益凸显。近年来&#xff0c;一种名为Devos的勒索病毒在全球范围内肆虐&#xff0c;给企业和个人带来了极大的损失。本文将详细介绍Devos勒索病毒的特点、传播途径以及预防和应对措施&#xff0c;帮助大家更好地认识和防范这一…

针对JavaScript混淆加密,JShaman推出新功能

JShaman英文版在最新的一次更新时&#xff0c;增加了新功能&#xff1a; JavaScript代码混淆加密完成后&#xff0c;可以显示各功能耗时、处理的AST节点数量&#xff0c; 以此可知对代码做了哪些保护处理。 如上图所示&#xff0c;在此例中&#xff0c;对代码共进行了23项混淆…

Python标准数据类型-List(列表)

✅作者简介&#xff1a;CSDN内容合伙人、阿里云专家博主、51CTO专家博主、新星计划第三季python赛道Top1&#x1f3c6; &#x1f4c3;个人主页&#xff1a;hacker707的csdn博客 &#x1f525;系列专栏&#xff1a;零基础入门篇 &#x1f4ac;个人格言&#xff1a;不断的翻越一座…

无涯教程-JavaScript - IMPRODUCT函数

描述 IMPRODUCT函数以x yi或x yj文本格式返回1到255个复数的乘积。两个复数的乘积为- $$(A BI)(C DI)(AC-BD)(A B)1 $$ 语法 IMPRODUCT (inumber1, [inumber2] ...)争论 Argument描述Required/OptionalInumber11 to 255 complex numbers to multiply.Required[inumbe…

xCode14.3.1运行MonkeyDev出现“Executable Not Found“的解决办法

安装MonkeyDev遇到的坑 环境&#xff1a;Xcode Version 14.3.1 (14E300c) 错误提示 is not a valid path to an executable file. 报错 /Users/xxxx//Library/Developer/Xcode/DerivedData/MonTest-ccparhdyzjuqhjdergwrngpfwwoh/Build/Products/Debug-iphoneos/MonTest.app…

基于大规模测量和多任务深度学习的电子鼻系统目标识别、浓度预测和状态判断

Target discrimination, concentration prediction, and status judgment of electronic nose system based on large-scale measurement and multi-task deep learning 摘要 为了实现响应特征的自动提取&#xff0c;简化模型的训练和应用过程&#xff0c;设计了一种双块知识…

python3网络爬虫--爬取B站视频弹幕(附源码)

文章目录 一&#xff0e;前言二&#xff0e;配置Protobuf 环境&生成编译文件1&#xff0e;配置Protobuf 环境2&#xff0e;生成编译文件 三&#xff0e;解析弹幕四&#xff0e;自动解析弹幕五&#xff0e;总结六&#xff0e;参考 本篇博文记录一下爬取B站弹幕的主要思路以及…

Pandas模块:Python科学计算神器之一

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们点赞👍🏻、收藏⭐️、…

SpotBugs检查java代码:不应该依赖平台默认编码(DM_DEFAULT_ENCODING)

https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html#internationalization-i18n 一个字节转换为字符串&#xff08;或字符串转化为字节&#xff09;的函数调用没有明确指明编码&#xff0c;而是依赖平台默认的编码&#xff0c;这可能导致应用在不同平台上的行为…

mac电脑做为开发机的一些初始化操作

Terminal设置 风格设置 修改Terminal提示符 /etc/zshrc 此处控制&#xff0c;大概70行左右 PS1"%n%m %1~ %# "目录颜色设置 编辑文件 vim ~/.bash_profile输入以下内容 export LS_OPTIONS--colorauto # 如果没有指定&#xff0c;则自动选择颜色 export CLICOLOR…

【C++漂流记】一文搞懂类与对象的封装

本篇文章主要说明了类与对象中封装的有关知识&#xff0c;包括属性和行为作为整体、访问权限、class与struct的区别、成员属性的私有化&#xff0c;希望这篇文章可以帮助你更好的了解类与对象这方面的知识。 文章目录 一、属性和行为作为整体二、访问权限三、class与struct的区…

spark集成hudi

启动spark-shell spark-shell \ > --jars /opt/software/hudi-spark3.1-bundle_2.12-0.12.0.jar \ > --conf spark.serializerorg.apache.spark.serializer.KryoSerializer\ > --conf spark.sql.extensionsorg.apache.spark.sql.hudi.HoodieSparkSessionExtension2…

腾讯云AI绘画:探究AI创意与技术的新边界

目录 一、2023的“网红词汇”——AI绘画二、智能文生图1、智能文生图的应用场景2、风格和配置的多样性3、输入一段话&#xff0c;腾讯云AI绘画给你生成一张图4、文本描述生成图像&#xff0c;惊艳全场 三、智能图生图&#xff1a;重新定义图像美学1、智能图生图的多元应用场景2…

Nginx 解析漏洞

文章目录 Nginx 解析漏洞1. 空字节漏洞1.1 漏洞描述1.2 漏洞复现1.3 修复方案 2. Nginx 解析漏洞复现2.1 漏洞描述2.2 漏洞复现2.3 获取GetShell2.4 修复方案 3. Nginx 文件名逻辑漏洞3.1 漏洞描述3.2 漏洞原理3.3 漏洞复现3.3.1 环境启动3.3.2 漏洞验证 3.4 漏洞利用3.5 修复方…

X(推特)“鸡贼”手段曝光:这些广告并没有标注,你知道吗?

在使用推特的时候&#xff0c;有些人可能会注意到&#xff0c;一些广告并没有正确地标注&#xff0c;看起来很像普通的内容&#xff0c;十分难以区分。美国的联邦贸易委员会&#xff08;FTC&#xff09;和欧盟的欧洲广告标准局&#xff08;EASA&#xff09;等机构都对广告标签有…

WhatsApp的两个商业模式该如何选择

WhatsApp Business 是什么 目前 WhatsApp 提供两种商业模式&#xff0c;企业应根据自身需求选择相应版本。 第一个版本是 WhatsApp Business&#xff1a;初创企业只需一个手机应用程序&#xff0c;便可以个体单位与客户轻松互动; 另一个版本是 WhatsApp Business API&#xff…

如何优雅地实现接口防刷

背景 最近在学习redis&#xff0c;想到了之前的写的一个案例demo&#xff0c;实现了接口的流量防刷。主要是为了防止爬虫爬取接口&#xff0c;当然可以适用于那些需要进行流控的系统&#xff0c;shigen画了一张草图展示主要的原理和过程&#xff1a; 首先用户请求系统的接口&a…

一篇文章教会你如何降低代码的冗余度——探索指针数组,数组指针,函数指针,函数指针数组,回调函数的奥妙

前言&#xff1a;人们总说指针是c语言的灵魂&#xff0c;是因为指针的使用技巧是“千姿百态”的&#xff0c;程序员可以通过指针来直接访问内存&#xff0c;这就赋予了它功能的多样性以及更多意想不到的编程技巧与方式&#xff0c;在本篇文章中&#xff0c;笔者就给大家带来指针…

同时安装python2和3解决方案

我先安装python3后&#xff0c;按照网上步骤&#xff0c;继续安装好python2&#xff0c;直接运行python -v只能显示python2&#xff0c;运行python3找不到此命令&#xff0c;通过https://blog.csdn.net/qq_64409509/article/details/131514944这篇文章找到了解决方案&#xff0…