黑马React:基础拓展

2023-12-19

黑马React: D10-基础拓展

Date: December 18, 2023


useReducer

基础使用

作用: 让 React 管理多个 相对关联 的状态数据

补充:和useState的作用类似,用来管理相对复杂的状态数据

**特点:**useReducer返回值为一个数组, 可以解构处数值state与修改数值的方法dispatch(修改数值的唯一方法)

案例:

  1. 定义一个reducer函数(根据不同的action返回不同的新状态)
  2. 在组件中调用useReducer,并传入reducer函数和状态的初始值
  3. 事件发生时,通过dispatch函数分派一个action对象(通知reducer要返回哪个新状态并渲染UI)
import { useReducer } from 'react'

// 1. 定义reducer函数,根据不同的action返回不同的新状态
function reducer(state, action) {
  switch (action.type) {
    case 'INC':
      return state + 1
    case 'DEC':
      return state - 1
    default:
      return state
  }
}

function App() {
  // 2. 使用useReducer分派action
  const [state, dispatch] = useReducer(reducer, 0)
  return (
    <>
      {/* 3. 调用dispatch函数传入action对象 触发reducer函数,分派action操作,使用新状态更新视图 */}
      <button onClick={() => dispatch({ type: 'DEC' })}>-</button>
      {state}
      <button onClick={() => dispatch({ type: 'INC' })}>+</button>
    </>
  )
}

export default App


更新流程

Untitled




分派action传参

**做法:**分派action时如果想要传递参数,需要在action对象中添加一个payload参数,放置状态参数

// 定义reducer

import { useReducer } from 'react'

// 1. 根据不同的action返回不同的新状态
function reducer(state, action) {
  console.log('reducer执行了')
  switch (action.type) {
    case 'INC':
      return state + 1
    case 'DEC':
      return state - 1
    case 'UPDATE':
      return state + action.payload
    default:
      return state
  }
}

function App() {
  // 2. 使用useReducer分派action
  const [state, dispatch] = useReducer(reducer, 0)
  return (
    <>
      {/* 3. 调用dispatch函数传入action对象 触发reducer函数,分派action操作,使用新状态更新视图 */}
      <button onClick={() => dispatch({ type: 'DEC' })}>-</button>
      {state}
      <button onClick={() => dispatch({ type: 'INC' })}>+</button>
      <button onClick={() => dispatch({ type: 'UPDATE', payload: 100 })}>
        update to 100
      </button>
    </>
  )
}

export default App



useMemo

**作用:**它在每次重新渲染的时候能够缓存计算的结果

语法:

useMemo(() => {
	// 根据 count1 返回计算的结果
}, [count1])

说明:使用 useMemo 做缓存之后可以保证只有 count1 依赖项发生变化时才会重新计算

**使用场景:**消耗非常大的计算可以使用 useMemo

使用技巧:

1-指这个空数组只会在组件渲染完毕之后执行一次,即只要这个固定的 [1, 2, 3] 稳定的数组引用

const list = useMemo(() => {
	return [1, 2, 3]
}, [])

看个场景

原本用意: 基于count1的变化计算斐波那契数列之和 ,但是当我们修改count2状态的时候,斐波那契求和函数也会被执行,显然是一种浪费

Untitled

案例:

// useMemo
// 作用:在组件渲染时缓存计算的结果

import { useState } from 'react'

function factorialOf(n) {
  console.log('斐波那契函数执行了')
  return n <= 0 ? 1 : n * factorialOf(n - 1)
}

function App() {
  const [count, setCount] = useState(0)
  // 计算斐波那契之和
  **const sum = factorialOf(count)**

  const [num, setNum] = useState(0)

  return (
    <>
      {sum}
      <button onClick={() => setCount(count + 1)}>+count:{count}</button>
      <button onClick={() => setNum(num + 1)}>+num:{num}</button>
    </>
  )
}

export default App

Res:

Untitled



useMemo缓存计算结果

思路: 只有count发生变化时才重新进行计算

import { useMemo, useState } from 'react'

function fib (n) {
  console.log('计算函数执行了')
  if (n < 3) return 1
  return fib(n - 2) + fib(n - 1)
}

function App() {
  const [count, setCount] = useState(0)
  // 计算斐波那契之和
  // const sum = fib(count)
  // 通过useMemo缓存计算结果,只有count发生变化时才重新计算
  **const sum = useMemo(() => {
    return fib(count)
  }, [count])**

  const [num, setNum] = useState(0)

  return (
    <>
      {sum}
      <button onClick={() => setCount(count + 1)}>+count:{count}</button>
      <button onClick={() => setNum(num + 1)}>+num:{num}</button>
    </>
  )
}

export default App


React.memo

**作用:**允许组件在props没有改变的情况下跳过重新渲染

组件默认的渲染机制

**默认机制:**顶层组件发生重新渲染,这个组件树的子级组件都会被重新渲染

Case1:

效果:点击按钮,数字不断增加,同时不断输出子组件内容。很明显,父组件的改变,子组件也会被跟着重新渲染改变。

import { useState } from "react";

function Son() {
  console.log('我是子组件,我重新渲染了');
  return <div>this is son</div>
}

function App() {
  const [count, setCount] = useState(0)
  return (
    <div className="App">
      <button onClick={() => setCount(count + 1)}>+{count}</button>
    </div>
  )
}

export default App

Res:

Untitled


Case2:

// memo
// 作用:允许组件在props没有改变的情况下跳过重新渲染

import { useState } from 'react'

function Son() {
  console.log('子组件被重新渲染了')
  return <div>this is son</div>
}

function App() {
  const [, forceUpdate] = useState()
  console.log('父组件重新渲染了')
  return (
    <>
      <Son />
      <button onClick={() => forceUpdate(Math.random())}>update</button>
    </>
  )
}

export default App

Res:

Untitled


Case3:

使用 useMemo 来缓存计算结果

import { useState ,memo, useMemo } from "react"

// React.memo props比较机制

// 1. 传递一个简单类型的prop  props变化时组件重新渲染
// 2. 传递一个引用类型的prop  比较的新值和旧值的引用地址是否相同,相同则不重新渲染,不同则重新渲染

const MemoSon = memo(function Son({list}) {
  console.log('子组件重新渲染了')
  return <div>this is Son {list}</div>
})

function App() {
  const [count, setCount] = useState(0)
  const list = useMemo(() => {
    return [1,2,3]
  }, [])
  return (
    <div className="App">
      <MemoSon count={list}></MemoSon>
      <button onClick={() => setCount(count + 1)}>change count</button>
    </div>
  )
}

export default App;

Res:

Untitled



使用React.memo优化

**机制:**只有props发生变化时才重新渲染

下面的子组件通过 memo 进行包裹之后,返回一个新的组件MemoSon, 只有传给MemoSon的props参数发生变化时才会重新渲染

Case:

import { memo, useState } from "react";

function Son() {
  console.log('我是子组件,我重新渲染了');
  return <div>this is son</div>
}

const MemoSon = memo(function Son() {
  console.log('我是子组件,我重新渲染了');
  return <div>this is son</div>
})

function App() {
  const [count, setCount] = useState(0)
  return (
    <div className="App">
      <button onClick={() => setCount(count + 1)}>+{count}</button>
      <MemoSon/>
    </div>
  )
}

export default App

Res:

Untitled



props变化重新渲染

Case:

props变化子组件会重新渲染

import React, { useState } from 'react'

const MemoSon = React.memo(function Son() {
  console.log('子组件被重新渲染了')
  return <div>this is span</div>
})

function App() {
  console.log('父组件重新渲染了')

  const [count, setCount] = useState(0)
  return (
    <>
      <MemoSon count={count} />
      <button onClick={() => setCount(count + 1)}>+{count}</button>
    </>
  )
}

export default App

Res:

Untitled



props的比较机制

对于props的比较,进行的是‘浅比较’,底层使用 Object.is 进行比较,针对于对象数据类型,只会对比俩次的引用是否相等,如果不相等就会重新渲染,React并不关心对象中的具体属性

举个例子:

// prop是简单类型
Object.is(3, 3) => true //没有变化

// prop是引用类型(对象/数组)
Object([], []) => false // 有变化,React只关心引用是否变化

Case1:

传递一个简单数据类型

import { useState ,memo } from "react"

// React.memo props比较机制

// 1. 传递一个简单类型的prop  props变化时组件重新渲染
// 2. 传递一个引用类型的prop  比较的新值和旧值的引用地址是否相同,相同则不重新渲染,不同则重新渲染

const MemoSon = memo(function Son({count}) {
  console.log('子组件重新渲染了')
  return <div>this is Son {count}</div>
})

function App() {
  const [count, setCount] = useState(0)
  const num = 100
  return (
    <div className="App">
      <MemoSon count={num}></MemoSon>
      <button onClick={() => setCount(count + 1)}>change count</button>
    </div>
  )
}

export default App;

Res:

无返回

Case2:

传递一个复杂数据类型list。每次当我们点击 button 按钮的时候,都会引发父组件的重新渲染,从而也会引发 const list= [1, 2, 3] 的重新执行,因为其引用地址也会改变

import { useState ,memo } from "react"

// React.memo props比较机制

// 1. 传递一个简单类型的prop  props变化时组件重新渲染
// 2. 传递一个引用类型的prop  比较的新值和旧值的引用地址是否相同,相同则不重新渲染,不同则重新渲染

const MemoSon = memo(function Son({list}) {
  console.log('子组件重新渲染了')
  return <div>this is Son {list}</div>
})

function App() {
  const [count, setCount] = useState(0)
  const list = [1, 2, 3]
  return (
    <div className="App">
      <MemoSon count={list}></MemoSon>
      <button onClick={() => setCount(count + 1)}>change count</button>
    </div>
  )
}

export default App;

Res:

Untitled

说明:虽然俩次的list状态都是 [1,2,3] , 但是因为组件App俩次渲染生成了不同的对象引用list,所以传给MemoSon组件的props视为不同,子组件就会发生重新渲染



自定义比较函数

如果上一小节的例子,我们不想通过引用来比较,而是完全比较数组的成员是否完全一致,则可以通过自定义比较函数来实现

import React, { useState } from 'react'

// 自定义比较函数
function arePropsEqual(oldProps, newProps) {
  console.log(oldProps, newProps)
  return (
    oldProps.list.length === newProps.list.length &&
    oldProps.list.every((oldItem, index) => {
      const newItem = newProps.list[index]
      console.log(newItem, oldItem)
      return oldItem === newItem
    })
  )
}

const MemoSon = React.memo(function Son() {
  console.log('子组件被重新渲染了')
  return <div>this is span</div>
}, arePropsEqual)

function App() {
  console.log('父组件重新渲染了')
  const [list, setList] = useState([1, 2, 3])
  return (
    <>
      <MemoSon list={list} />
      <button onClick={() => setList([1, 2, 3])}>
        内容一样{JSON.stringify(list)}
      </button>
      <button onClick={() => setList([4, 5, 6])}>
        内容不一样{JSON.stringify(list)}
      </button>
    </>
  )
}

export default App


useCallback

看个场景

上一小节我们说到,当给子组件传递一个 引用类型 prop的时候,即使我们使用了 memo 函数依旧无法阻止子组件的渲染,其实传递prop的时候,往往传递一个回调函数更为常见,比如实现子传父,此时如果想要避免子组件渲染,可以使用 useCallback 缓存回调函数

Case:

当我们给子组件传入函数时,由于函数也会引用数据类型,所以即使使用memo进行缓存控制,也会造成 父组件刷新 时,导致子组件同样刷新的问题

import { useState ,memo, useMemo, onChange } from "react"

const Input = memo(function Input({ onChange }) {
  console.log(('子组件重新渲染了'))
  return <input type="text" onChange={(e) => onChange(e.target.value)}></input>
})

function App() {
  // 传给子组件的函数
  const changeHandler = (value) => console.log(value);
  // 触发父组件重新渲染的函数
  const [count, setCount] = useState(0)
  return (
    <div className="App">
      {/* 把函数作为 prop 传递给子组件 */}
      <Input onChange={changeHandler}></Input>
      <button onClick={() => setCount(count + 1)}>{count}</button>
    </div>
  )
}

export default App;

Res:

当我们不断点击按钮时,数字不断增加的同时,控制台也在不断输出子组件中的语句

Untitled



useCallback缓存函数

**作用:**在组件多次重新渲染的时候缓存函数

语法:

const changeHandler = useCallback((value) => console.log(value), [])

参数:1-需要缓存的函数 2-依赖项

  • 对2的补充说明

    []代表我们只需要将其缓存一次,后面的引用一直保持稳定。如果你想在依赖项变化的时候更新,那就传入一个依赖项即可。

理解:useCallback缓存之后的函数可以在组件渲染时保持引用稳定,也就是返回同一个引用

Case:

// useCallBack

import { memo, useCallback, useState } from 'react'

const MemoSon = memo(function Son() {
  console.log('Son组件渲染了')
  return <div>this is son</div>
})

function App() {
  const [, forceUpate] = useState()
  console.log('父组件重新渲染了')
  const onGetSonMessage = useCallback((message) => {
    console.log(message)
  }, [])

  return (
    <div>
      <MemoSon onGetSonMessage={onGetSonMessage} />
      <button onClick={() => forceUpate(Math.random())}>update</button>
    </div>
  )
}

export default App

Res:

Untitled



forwardRef

**作用:**允许组件使用ref将一个DOM节点暴露给父组件

语法:

const Son = forwardRef((props, ref) => {
	return <input type="text" ref={ref}/>
})

参数:

1-props:指给子组件传递的参数 2-ref:通过ref来绑定子组件,从而在父组件上拿到子组件

Case1:

不使用 forwardRef

import { useRef } from "react"

// 子组件
function Son() {
  return <input />
}

// 父组件
function App() {
  const sonRef = useRef(null)
  const showRef = () => {
    console.log(sonRef);
  }
  return (
    <>
      <Son ref={sonRef} />
      <button onClick={showRef}>focus</button>
    </>
  )
}

export default App

Res:

Untitled

Case2:

通过 ref 获取

import { forwardRef, useRef } from "react"

// 子组件
// function Son() {
//   return <input />
// }

const Son = forwardRef((props, ref) => {
  return <input type="text" ref={ref} />
})

// 父组件
function App() {
  const sonRef = useRef(null)
  const showRef = () => {
    console.log(sonRef);
    sonRef.current.focus()
  }
  return (
    <>
      <Son ref={sonRef} />
      <button onClick={showRef}>focus</button>
    </>
  )
}

export default App

Res:

Untitled




useImperativeHandle

**作用:**如果我们并不想暴露子组件中的DOM而是想暴露子组件内部的方法

语法:

const Input = forwardRef((props, ref) => {
  const inputRef = useRef(null)
  // 实现聚焦逻辑函数
  const focusHandler = () => {
    inputRef.current.focus()
  }
  // 暴露函数给父组件调用
  useImperativeHandle(ref, () => {
    return {
      focusHandler
    }
  })
  return <input type="text" ref={inputRef}/>
})

Case:

import { forwardRef, useImperativeHandle, useRef } from "react"

// 子组件
const Son = forwardRef((props, ref) => {
  const inputRef = useRef(null)
  // 实现聚焦逻辑函数
  const focusHandler = () => {
    inputRef.current.focus()
  }
  // 暴露函数给父组件调用
  useImperativeHandle(ref, () => {
    return {
      focusHandler
    }
  })
  return <input type="text" ref={inputRef}/>
})

// 父组件
function App() {
  const sonRef = useRef(null)
  const focusHandler = () => {
    console.log(sonRef.current);
    sonRef.current.focusHandler()
  }
  return (
    <>
      <Son ref={sonRef} />
      <button onClick={focusHandler}>focus</button>
    </>
  )
}

export default App

Res:

Untitled




Class API

**概念:**顾名思义,Class API就是使用ES6支持的原生Class API来编写React组件

特点:

1-通过类属性 state 定义状态数据

2-通过 setState 方法来修改状态数据

3-通过 render 来写UI模版(JSX语法一致)

Case:

通过一个简单的 Counter 自增组件看一下组件的基础编写结构:

// class API
import { Component } from 'react'

class Counter extends Component {
  // 状态变量
  state = {
    count: 0,
  }

  // 事件回调
  clickHandler = () => {
    // 修改状态变量 触发UI组件渲染
    this.setState({
      count: this.state.count + 1,
    })
  }

  // UI模版
  render() {
    return <button onClick={this.clickHandler}>+{this.state.count}</button>
  }
}

function App() {
  return (
    <div>
      <Counter />
    </div>
  )
}

export default App

Res:

Untitled



组件生命周期

**概念:**组件从创建到销毁的各个阶段自动执行的函数就是生命周期函数

图示:

Untitled

  1. componentDidMount:组件挂载完毕自动执行 - 异步数据获取
  2. componentWillUnmount: 组件卸载时自动执行 - 清理副作用,比如定时器或者事件绑定

Case:

基础案例:卸载组件

 // Class API 生命周期

import { Component, useState } from "react";

class Son extends Component {
  // 生命周期函数
  // 挂载时:组件渲染完毕执行一次。用于:发送网络请求
  componentDidMount() {
    console.log('组件渲染完毕了,请求发送起来')
  }

  // 卸载时:组件卸载前执行一次。用于:清理副作用
  componentWillUnmount() {
    console.log('组件卸载了')
  }
  render() {
    return <div>SSSon</div>
  }
}

function App() {
  const [show, setShow] = useState(true)
  return (
    <>
      {show && <Son />}
      <button onClick={() => setShow(false)}>unmount</button>
    </>
  )
}

export default App

Res:

Untitled

Case2:

问题:以下Case的son组件在卸载后,其中的 Interval 定时器仍然在继续运行,造成了内存泄漏

// Class API 生命周期

import { Component, useState } from "react";

class Son extends Component {
  // 生命周期函数
  // 挂载时:组件渲染完毕执行一次。用于:发送网络请求
  componentDidMount() {
    console.log('组件渲染完毕了,请求发送起来')
    // 开启定时器
    this.timer = setInterval(() => {
      console.log('定时器执行了')
    }, 1000)
  }

  // 卸载时:组件卸载前执行一次。用于:清理副作用
  componentWillUnmount() {
    console.log('组件卸载了')
  }
  render() {
    return <div>SSSon</div>
  }
}

function App() {
  const [show, setShow] = useState(true)
  return (
    <>
      {show && <Son />}
      <button onClick={() => setShow(false)}>unmount</button>
    </>
  )
}

export default App

Res:

Untitled

修复后:

// Class API 生命周期

import { Component, useState } from "react";

class Son extends Component {
  // 生命周期函数
  // 挂载时:组件渲染完毕执行一次。用于:发送网络请求
  componentDidMount() {
    console.log('组件渲染完毕了,请求发送起来')
    // 开启定时器
    this.timer = setInterval(() => {
      console.log('定时器执行了')
    }, 1000)
  }

  // 卸载时:组件卸载前执行一次。用于:清理副作用
  componentWillUnmount() {
    console.log('组件卸载了')
    // 清除定时器
    **clearInterval(this.timer)**
  }
  render() {
    return <div>SSSon</div>
  }
}

function App() {
  const [show, setShow] = useState(true)
  return (
    <>
      {show && <Son />}
      <button onClick={() => setShow(false)}>unmount</button>
    </>
  )
}

export default App

Res:

Untitled


组件通信

**概念:**类组件和Hooks编写的组件在组件通信的思想上完全一致

分类:

  1. 父传子:通过prop绑定数据
  2. 子传父:通过prop绑定父组件中的函数,子组件调用
  3. 兄弟通信:状态提升,通过父组件做桥接

使用总结:

1-思想保持一致,不管API怎么改变,父子通信的思想是一致的

2-类组件依赖于this

父传子

Case:

// class API
import { Component } from 'react'
// 1. 父传子 直接通过props子组件标签身上绑定父组件中的数据即可

class Son extends Component {
  render() {
    // 使用this.props.msg
    return <div>我是子组件 {this.props.msg}</div>
  }
}

class Parent extends Component {
  state = {
    msg: 'this is parent msg'
  }
  render() {
    return (
      <div>
        <h1>我是父组件</h1>
        <Son msg={this.state.msg}/>
      </div>
    )
  }
}

function App() {
  return (
    <>
      <Parent />
    </>
  )
}

export default App

Res:

Untitled


子传父

Case:

// class API
import { Component } from 'react'

class Son extends Component {
  render() {
    const { msg, onGetSonMsg } = this.props
    return (
      <>
        <div>this is Son, {msg}</div>
        <button onClick={() => onGetSonMsg('this is son msg')}>
          changeMsg
        </button>
      </>
    )
  }
}

class App extends Component {
  // 状态变量
  state = {
    msg: 'this is initail app msg',
  }

  onGetSonMsg = (msg) => {
    this.setState({ msg })
  }

  // UI模版
  render() {
    return (
      <>
        <Son msg={this.state.msg} onGetSonMsg={this.onGetSonMsg} />
      </>
    )
  }
}

export default App

Res:

Untitled

参考:

Component – React 中文文档

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

黑马React:基础拓展 的相关文章

随机推荐

  • YoloV7改进策略:双动态令牌混合器(D-Mixer)的TransXNet,实现YoloV7的有效涨点

    摘要 双动态令牌混合器 D Mixer 一种输入依赖的方式聚合全局信息和局部细节 D Mixer通过分别在均匀分割的特征片段上应用有效的全局注意力模块和输入依赖的深度卷积 使网络具有强大的归纳偏差和扩大的有效感受野 使用D Mixer作为基
  • 【计算机毕业设计】基于微信小程序的电子购物系统

    由于APP软件在开发以及运营上面所需成本较高 而用户手机需要安装各种APP软件 因此占用用户过多的手机存储空间 导致用户手机运行缓慢 体验度比较差 进而导致用户会卸载非必要的APP 倒逼管理者必须改变运营策略 随着微信小程序的出现 解决了用
  • 我的创作纪念日-IT从业者张某某

    机缘 勿忘初心 牢记使命 我成为创作者的初心是什么呢 时间有些久了 回头看下自己的第一篇博客 还是略显青涩的 有种不忍直视的感觉 我的第一篇博客 应该是想记录下工作中的一个演示项目 并想着把这个演示项目通过文章的方向进行记录下来 便于和团队
  • STM32 GPIO工作原理详解

    STM32 GPIO介绍 1 STM32引脚说明 GPIO是通用输入 输出端口的简称 是STM32可控制的引脚 GPIO的引脚与外部硬件设备连接 可实现与外部通讯 控制外部硬件或者采集外部硬件数据的功能 以STM32F103ZET6芯片为例
  • Js new Date() 年月日时分秒的日期时间格式排序

    new Date 日期对象 效果 排序前 2023 12 10 12 01 21 2023 12 10 18 53 09 2023 12 10 08 10 12 2023 12 10 00 06 06 2023 12 10 16 36 08
  • 关于“Python”的核心知识点整理大全26

    目录 10 3 9 决定报告哪些错误 10 4 存储数据 10 4 1 使用 json dump 和 json load number writer py number reader py 10 4 2 保存和读取用户生成的数据 对于用户生
  • 在AI技术的无情侵袭下,学学Java的23种设计模式还是非常有必要的

    目前国内80 程序员的主要工作是调用组合api实现各种业务需求 在顶层架构师设定好的框架下 做着重复且无聊的编码工作 如果未来ai被广泛应用 那么被替代的风险是很高的 比较扎心的是 其实目前用ai生成片段代码已经是各个公司比较普遍的做法了
  • 【计算机毕业设计】南宁周边乡村游

    随着我国经济迅速发展 人们对手机的需求越来越大 各种手机软件也都在被广泛应用 但是对于手机进行数据信息管理 对于手机的各种软件也是备受游客的喜爱 南宁周边乡村游被游客普遍使用 为方便游客能够可以随时进行南宁周边乡村游的数据信息管理 特开发了
  • Java版企业电子招标采购系统源码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis

    功能描述 1 门户管理 所有用户可在门户页面查看所有的公告信息及相关的通知信息 主要板块包含 招标公告 非招标公告 系统通知 政策法规 2 立项管理 企业用户可对需要采购的项目进行立项申请 并提交审批 查看所有的立项信息 主要功能包含 招标
  • 网络攻击3——拒绝服务攻击与缓冲区溢出攻击

    目录 拒绝服务攻击 拒绝服务攻击介绍 分布式拒绝服务攻击介绍 CDN 软件缺陷漏洞 缓冲区溢出 其它高级攻击 拒绝服务攻击 拒绝服务攻击不会破坏信息的机密性和完整性 而是破坏服务的可用性 拒绝服务攻击分为两大类 DoS 拒绝服务攻击 DDo
  • Java设计模式:模板方法模式

    作者主页 欢迎来到我的技术博客 个人介绍 大家好 本人热衷于 Java后端开发 欢迎来交流学习哦 如果文章对您有帮助 记得 关注 点赞 收藏 评论 您的支持将是我创作的动力 让我们一起加油进步吧 文章目录 一 模板方法模式的定义 二 模板方
  • 【计算机毕业设计】基于微信小程序的二手闲置交易市场系统

    随着计算机技术的成熟 互联网的建立 如今 PC平台上有许多关于二手闲置交易方面的应用程序 但由于使用时间和地点上的限制 用户在使用上存在着种种不方便 而开发一款基于微信小程序的二手闲置交易市场系统 能够有效地解决这个问题 本基于微信小程序的
  • 【计算机毕业设计】网络小说微信小程序

    社会的发展和科学技术的进步 互联网技术越来越受欢迎 网络小说也逐渐受到广大人民群众的喜爱 也逐渐进入了每个用户的使用 网络小说具有便利性 速度快 效率高 成本低等优点 因此 构建符合自己要求的操作系统是非常有意义的 本文从管理员 用户的功能
  • 如何看待名企的内推策略?

    内推肯定是可行的 现在 多数名企大厂都会有内推 不管是社招 还是校招 实习 有些公司通过内推获取的 简历数量甚至占到了总简历量的1 3 质量一般也不错 成本相对更低一些 内推想要做好 有效果 需要做到以下几点 做好内部宣贯工作 充分调动内部
  • pytest自动化框架运行全局配置文件pytest.ini

    还记得在之前的篇章中有讲到Pytest是目前主要流行的自动化框架之一 他有基础的脚本编码规则以及两种运行方式 pytest的基础编码规则是可以进行修改 这就是今日文章重点 看到这大家心中是否提出了两个问题 pytest的基础编码规则在哪可以
  • 钡铼无线R10A工业级路由器在工业机器人领域的创新应用

    随着工业机器人的普及 对于高可靠性和高稳定性的网络接入设备的需求也越来越大 传统的有线网络虽然稳定 但在现场布置和维护上面临很多困难 而无线网络虽然方便 但受到信号干扰和传输距离限制等问题的影响 如何解决这些问题 提高工业机器人在生产过程中
  • shell中的sort和uniq命令

    参考链接sort https www runoob com linux linux comm sort html 参考链接uniq https www runoob com linux linux comm uniq html 一 sort
  • 如何提高云服务器的安全性

    近年来 随着人们对云技术不断研发 可以说依托云技术出现的产物是十分的炙手可热 云服务器目前已用作企业和个人的常 用服务器产品 与传统服务器架构不同 云服务器为用户带来了非常有效和便捷的用户体验 值得站长们注意的是 在云服务 器的实际使用中
  • OpenCV4工业缺陷检测的六种方法

    文末送书 今天推荐一本机器视觉领域优质书籍 机器视觉 机器视觉是使用各种工业相机 结合传感器跟电气信号实现替代传统人工 完成对象识别 计数 测量 缺陷检测 引导定位与抓取等任务 其中工业品的缺陷检测极大的依赖人工完成 特别是传统的3C制造环
  • 黑马React:基础拓展

    黑马React D10 基础拓展 Date December 18 2023 useReducer 基础使用 作用 让 React 管理多个 相对关联 的状态数据 补充 和useState的作用类似 用来管理相对复杂的状态数据 特点 use