react-hooks常用API基本简绍

2023-11-16

介绍

react hooks 是 React 16.8 的新增特性。 它可以让我们在函数组件中使用 state 、生命周期以及其他 react 特性,而不仅限于 class 组件

react hooks 的出现,标示着 react 中不会在存在无状态组件了,只有类组件和函数组件

对比

存在即合理,hooks 也不例外,它的出现,就代表了它要解决一些 class 组件的缺陷或者不足,那么我们先来看看 class 组件有什么不足或者问题存在

根据网上的说法我总结出三点,当然每种问题都有其解决方案

问题 解决方案 缺点
生命周期臃肿,逻辑耦合  
逻辑难以复用 通过继承来解决 不支持多继承
  通过hok解决 会增加额外的组件嵌套,也会有一些性能的影响
  渲染属性 同上,层级臃肿,性能影响
class this 指向的问题 匿名函数 每次都创建新的函数,子组件复用不必要的渲染
  bind 需要写很多跟逻辑,状态无关的代码

而 hooks 对这些问题都有较好的解决方案

  1. 没有了 class 自然就没有了 this 指向问题
  2. 通过自定义 useEffect 来解决复用问题
  3. 通过使用 useEffect 来细分逻辑,减小出现逻辑臃肿的场景

当然,hooks 是一把双刃剑,用的好自己能够达到效果,用的不好反而会 降低开发效率和质量,那么我们接下来看看如用更好的使用 hooks 吧

具体使用

useState 的使用

简单例子

hooks 的能力,就是让我们在函数组件中使用 state, 就是通过 useState 来实现的,我们来看一个简单的例子

function App () {
  const [ count, setCount ] = useState(0)
  return (
    <div>
      点击次数: { count } 
      <button onClick={() => { setCount(count + 1)}}>点我</button>
    </div>
  )
}

useState 的使用非常简单,我们从 React 中拿到 useState 后,只需要在使用的地方直接调用 useState 函数就可以, useState 会返回一个数组,第一个值是我们的 state, 第二个值是一个函数,用来修改该 state 的,那么这里为什么叫 count 和 setCount?一定要叫这个吗,这里使用了 es6 的解构赋值,所以你可以给它起任何名字:如updateCountdoCountany thing,当然,为了编码规范,所以建议统一使用一种命名规范,尤其是第二个值

相同值

当我们在使用 useState 时,修改值时传入同样的值,我们的组件会重新渲染吗,例如这样

function App () {
 const [ count, setCount ] = useState(0)
 console.log('component render count')
 return (
    <div>
      点击次数: { count } 
      <button onClick={() => { setCount(count)}}>点我</button>
    </div>
 )
}

结果是不会,放心使用

useState 的默认值

useState 支持我们在调用的时候直接传入一个值,来指定 state 的默认值,比如这样 useState(0)useState({ a: 1 })useState([ 1, 2 ]),还支持我们传入一个函数,来通过逻辑计算出默认值,比如这样

function App (props) {
  const [ count, setCount ] = useState(() => {
     return props.count || 0
  })
  return (
    <div>
      点击次数: { count } 
      <button onClick={() => { setCount(count + 1)}}>点我</button>
    </div>
 )
}

这个时候,就有小伙伴问了,那我组件每渲染一次,useState 中的函数就会执行一遍吗,浪费性能,其实不会,useState 中的函数只会执行一次,我们可以做个测试

function App (props) {
 const [ count, setCount ] = useState(() => {
    console.log('useState default value function is call')
    return props.count || 0
 })
 return (
   <div>
     点击次数: { count } 
     <button onClick={() => { setCount(count + 1)}}>点我</button>
   </div>
  )
}

结果是:只会在当前组件的第一次渲染执行useState函数

setUseState 时获取上一轮的值

我们在使用 useState 的第二个参数时,我们想要获取上一轮该 state 的值的话,只需要在 useState 返回的第二个参数,也就是我们上面的例子中的 setCount 使用时,传入一个参数,该函数的参数就是上一轮的 state 的值

setCount((count => count + 1)

多个 useState 的情况

useState 我们不可能只使用一个,当我们使用多个 useState 的时候,那 react 是如何识别那个是哪个呢,其实很简单,它是靠第一次执行的顺序来记录的,就相当于每个组件存放useState 的地方是一个数组,每使用一个新的 useState,就向数组中 push 一个 useState,那么当然,当我们在运行时改变、添加、减少 useState 时,react 还能正常执行吗

function App (props) {
  let count, setCount
  let sum, setSum
  if (count > 2) {
    [ count, setCount ] = useState(0)
    [ sum, setSum ] = useState(10)
  } else {
    [ sum, setSum ] = useState(10)
    [ count, setCount ] = useState(0)
  }
  return (
    <div>
      点击次数: { count } 
      总计:{ sum }
      <button onClick={() => { setCount(count + 1); setSum(sum - 1)}}>点我</button>
    </div>
    )
}

当我们在运行时改变 useState 的顺序,数据会混乱,增加 useState, 程序会报错

不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层调用他们。遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确

同时推荐使用 eslint-plugin-react-hooks 插件来规范代码编写,针对这种情况进行校验

useState 的使用就是这么简单,我已经学会了, 接下来,我们看一下 useEffect 的使用

useEffect 的使用

Effect Hook 可以让你在函数组件中执行副作用操作,这里提到副作用,什么是副作用呢,就是除了状态相关的逻辑,比如网络请求,监听事件,查找 dom

简单例子

有这样一个需求,需要我们在组件在状态更新的时候改变 document.title,在以前我们会这样写代码

  class App extends Component {
    state = {
      count: 0
    }

    componentDidMount() {
      document.title = count
    }

    componentDidUpdate() {
      document.title = count
    }
    render () {
      const { count } = this.state
      return (
        <div>
          页面名称: { count } 
          <button onClick={() => { this.setState({ count: count++ })}}>点我</button>
        </div>
      )
    }
  }

使用 hooks 怎么写呢

function App () {
  const [ count, setCount ] = useState(0)

  useEffect(() => {
    document.title = count
  })

  return (
    <div>
      页面名称: { count } 
      <button onClick={() => { setCount(count + 1 )}}>点我</button>
    </div>
    )
}

useEffect 是什么呢,我们先忽略,回到我们总结的 class 组件存在的问题,useState 只是让我们的函数组件具有使用 state 的能力,那我们要解决 class 组件存在的问题,先来解决第一个,生命周期臃肿的问题

useEffect 生命周期

如果你熟悉 React class 的生命周期函数,你可以把 useEffect Hook 看做 componentDidMountcomponentDidUpdate 和 componentWillUnmount 这三个声明周期函数的组合。

以往我们在绑定事件、解绑事件、设定定时器、查找 dom 的时候,都是通过 componentDidMountcomponentDidUpdatecomponentWillUnmount 生命周期来实现的,而 useEffect 会在组件每次 render 之后调用,就相当于这三个生命周期函数,只不过可以通过传参来决定是否调用

其中注意的是,useEffect 会返回一个回调函数,作用于清除上一次副作用遗留下来的状态,如果该 useEffect 只调用一次,该回调函数相当于 componentWillUnmount 生命周期

具体看下面例子

  function App () {
    const [ count, setCount ] = useState(0)
    const [ width, setWidth ] = useState(document.body.clientWidth)

    const onChange = () => {
      setWidth(document.body.clientWidth)
    }

    useEffect(() => {
      window.addEventListener('resize', onChange, false)

      return () => {
        window.removeEventListener('resize', onChange, false)
      }
    })

    useEffect(() => {
      document.title = count
    })

    return (
      <div>
        页面名称: { count } 
        页面宽度: { width }
        <button onClick={() => { setCount(count + 1)}}>点我</button>
      </div>
      )
  }

接着我们前面的简单例子,我们上面例子要处理两种副作用逻辑,这里我们既要处理 title,还要监听屏幕宽度改变,按照 class 的写法,我们要在生命周期中处理这两种逻辑,但在 hooks 中,我们只需要两个 useEffect 就能解决这些问题,我们之前提到,useEffect 能够返回一个函数,用来清除上一次副作用留下的状态,这个地方我们可以用来解绑事件监听,这个地方存在一个问题,就是 useEffect 是每次 render 之后就会调用,比如 title 的改变,相当于 componentDidUpdate,但我们的事件监听不应该每次 render 之后,进行一次绑定和解绑,就是我们需要 useEffect 变成 componentDidMount, 它的返回函数变成 componentWillUnmount,这里就需要用到 useEffect 函数的第二个参数了

useEffect 的第二个参数

useEffect 的第二个参数,有三种情况

  1. 什么都不传,组件每次 render 之后 useEffect 都会调用,相当于 componentDidMount 和 componentDidUpdate
  2. 传入一个空数组 [], 只会调用一次,相当于 componentDidMount 和 componentWillUnmount
  3. 传入一个数组,其中包括变量,只有这些变量变动时,useEffect 才会执行

具体看下面例子

  function App () {
    const [ count, setCount ] = useState(0)
    const [ width, setWidth ] = useState(document.body.clientWidth)

    const onChange = () => {
      setWidth(document.body.clientWidth)
    }

    useEffect(() => {
      // 相当于 componentDidMount
      console.log('add resize event')
      window.addEventListener('resize', onChange, false)

      return () => {
        // 相当于 componentWillUnmount
        window.removeEventListener('resize', onChange, false)
      }
    }, [])

    useEffect(() => {
      // 相当于 componentDidUpdate
      document.title = count
    })

    useEffect(() => {
      console.log(`count change: count is ${count}`)
    }, [ count ])

    return (
      <div>
        页面名称: { count } 
        页面宽度: { width }
        <button onClick={() => { setCount(count + 1)}}>点我</button>
      </div>
      )
  }

根据上面的例子的运行结果,第一个 useEffect 中的 'add resize event' 只会在第一次运行时输出一次,无论组件怎么 render,都不会在输出,第二个 useEffect 会在每次组件 render 之后都执行,title 每次点击都会改变, 第三个 useEffect, 只要有在第一次运行和 count 改变时,才会执行,屏幕发生改变引起的 render 并不会影响第三个 useEffect

useContext

context 中的 Provider 和 Consumer,在类组件和函数组件中都能使用,contextType 只能在类组件中使用,因为它是类的静态属性,具体如何使用 useContext 呢,看下面的例子

// 创建一个 context
const Context = createContext(0)

// 组件一, Consumer 写法
class Item1 extends Component {
  render () {
    return (
      <Context.Consumer>
        {
          (count) => (<div>{count}</div>)
        }
      </Context.Consumer>
    )
  }
}
// 组件二, contextType 写法
class Item2 extends Component {
  static contextType = Context
  render () {
    const count = this.context
    return (
      <div>{count}</div>
    )
  }
}
// 组件一, useContext 写法
function Item3 () {
  const count = useContext(Context);
  return (
    <div>{ count }</div>
  )
}

function App () {
  const [ count, setCount ] = useState(0)
  return (
    <div>
      点击次数: { count } 
      <button onClick={() => { setCount(count + 1)}}>点我</button>
      <Context.Provider value={count}>
        <Item1></Item1>
        <Item2></Item2>
        <Item3></Item3>
      </Context.Provider>
    </div>
    )
}

通过运行上面的例子,我们得到的结果是,三种写法都能够实现我们的需求,但是,三种写有各自的优缺点,下面为对比出的结果

写法 优缺
consumer 嵌套复杂,Consumer 第一个子节点必须为一个函数,无形增加了工作量
contextType 只支持 类组件,无法在多 context 的情况下使用
useContext 不需要嵌套,多 context 写法简单

通过上面的比较,没理由继续使用 consumer 和 contextType

useMemo

useMemo 是什么呢,它跟 memo 有关系吗 ,说白了 memo 就是函数组件的 PureComponent,用来做性能优化的手段,useMemo 也是,useMemo 在我的印象中和 Vue 的 computed 计算属性类似,都是根据依赖的值计算出结果,当依赖的值未发生改变的时候,不触发状态改变,useMemo 具体如何使用呢,看下面例子

function App () {
  const [ count, setCount ] = useState(0)
  const add = useMemo(() => {
    return count + 1
  }, [count])
  return (
    <div>
      点击次数: { count }
      <br/>
      次数加一: { add }
      <button onClick={() => { setCount(count + 1)}}>点我</button>
    </div>
    )
}

上面的例子中,useMemo 也支持传入第二个参数,用法和 useEffect 类似

  1. 不传数组,每次更新都会重新计算
  2. 空数组,只会计算一次
  3. 依赖对应的值,当对应的值发生变化时,才会重新计算(可以依赖另外一个 useMemo 返回的值)

需要注意的是,useMemo 会在渲染的时候执行,而不是渲染之后执行,这一点和 useEffect 有区别,所以 useMemo 不建议有 副作用相关的逻辑

同时,useMemo 可以作为性能优化的手段,但不要把它当成语义上的保证,将来,React 可能会选择“遗忘”以前的一些 memoized 值,并在下次渲染时重新计算它们

useCallback

useCallback 是什么呢,可以说是 useMemo 的语法糖,能用 useCallback 实现的,都可以使用 useMemo, 在 react 中我们经常面临一个子组件渲染优化的问题, 尤其是在向子组件传递函数props时,每次 render 都会创建新函数,导致子组件不必要的渲染,浪费性能,这个时候,就是 useCallback 的用武之地了,useCallback 可以保证,无论 render 多少次,我们的函数都是同一个函数,减小不断创建的开销,具体如何使用看下面例子

const onClick = useMemo(() => {
  return () => {
    console.log('button click')
  }
}, [])

const onClick = useCallback(() => {
 console.log('button click')
}, [])

同样,useCallback 的第二个参数和useMemo一样,没有区别

useRef

useRef 有什么作用呢,其实很简单,总共有两种用法

  1. 获取子组件的实例(只有类组件可用)
  2. 在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的 this.xxx

获取子组件实例

上面提到了一点,useRef 只能获取子组件的实例,这在类组件中也是同样的道理,具体看下面的例子

// 使用 ref 子组件必须是类组件
class Children extends PureComponent {
  render () {
    const { count } = this.props
    return (
      <div>{ count }</div>
    )
  }
}

function App () {
  const [ count, setCount ] = useState(0)
  const childrenRef = useRef(null)
  // const 
  const onClick = useMemo(() => {
    return () => {
      console.log('button click')
      console.log(childrenRef.current)
      setCount((count) => count + 1)
    }
  }, [])
  return (
    <div>
      点击次数: { count }
      <Children ref={childrenRef}  count={count}></Children>
      <button onClick={onClick}>点我</button>
    </div>
    )
}

useRef 在使用的时候,可以传入默认值来指定默认值,需要使用的时候,访问 ref.current 即可访问到组件实例

类组件属性

有些情况下,我们需要保证函数组件每次 render 之后,某些变量不会被重复申明,比如说 Dom 节点,定时器的 id 等等,在类组件中,我们完全可以通过给类添加一个自定义属性来保留,比如说 this.xxx, 但是函数组件没有 this,自然无法通过这种方法使用,有的朋友说,我可以使用 useState 来保留变量的值,但是 useState 会触发组件 render,在这里完全是不需要的,我们就需要使用 useRef 来实现了,具体看下面例子

function App () {
  const [ count, setCount ] = useState(0)
  const timer = useRef(null)
  let timer2 
  
  useEffect(() => {
    let id = setInterval(() => {
      setCount(count => count + 1)
    }, 500)

    timer.current = id
    timer2 = id
    return () => {
      clearInterval(timer.current)
    }
  }, [])

  const onClickRef = useCallback(() => {
    clearInterval(timer.current)
  }, [])

  const onClick = useCallback(() => {
    clearInterval(timer2)
  }, [])

  return (
    <div>
      点击次数: { count }
      <button onClick={onClick}>普通</button>
      <button onClick={onClickRef}>useRef</button>
    </div>
    )
}

当我们们使用普通的按钮去暂停定时器时发现定时器无法清除,因为 App 组件每次 render,都会重新申明一次 timer2, 定时器的 id 在第二次 render 时,就丢失了,所以无法清除定时器,针对这种情况,就需要使用到 useRef,来为我们保留定时器 id,类似于 this.xxx,这就是 useRef 的另外一种用法

useReducer

useReducer 是什么呢,它其实就是类似 redux 中的功能,相较于 useState,它更适合一些逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等等的特定场景, useReducer 总共有三个参数

  1. 第一个参数是 一个 reducer,就是一个函数类似 (state, action) => newState 的函数,传入 上一个 state 和本次的 action
  2. 第二个参数是初始 state,也就是默认值,是比较简单的方法
  3. 第三个参数是惰性初始化,这么做可以将用于计算 state 的逻辑提取到 reducer 外部,这也为将来对重置 state 的 action 做处理提供了便利
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, {
    count: 0
  });
  return (
    <>
      点击次数: {state.count}
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </>
  );
}

useImperativeHandle

useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值,说简单点就是,子组件可以选择性的暴露给副组件一些方法,这样可以隐藏一些私有方法和属性,官方建议,useImperativeHandle应当与 forwardRef 一起使用,具体如何使用看下面例子

function Kun (props, ref) {
  const kun = useRef()

  const introduce = useCallback (() => {
    console.log('i can sing, jump, rap, play basketball')
  }, [])
  useImperativeHandle(ref, () => ({
    introduce: () => {
      introduce()
    }
  }));

  return (
    <div ref={kun}> { props.count }</div>
  )
}

const KunKun = forwardRef(Kun)

function App () {
  const [ count, setCount ] = useState(0)
  const kunRef = useRef(null)

  const onClick = useCallback (() => {
    setCount(count => count + 1)
    kunRef.current.introduce()
  }, [])
  return (
    <div>
      点击次数: { count }
      <KunKun ref={kunRef}  count={count}></KunKun>
      <button onClick={onClick}>点我</button>
    </div>
    )
}

其它hook

还有两个 hook,没什么好讲的,用的也不多,可以看看官方文档

  1. useLayoutEffect
  2. useDebugValue

自定义hook

我们之前总结出三个问题,class this 指向问题,生命周期逻辑冗余问题,都已得到解决,而逻辑难以复用,在前面的例子中并没有解决,要解决这个问题,就要通过 自定义 hook 来解决

自定义 Hook,可以将组件逻辑提取到可重用的函数中,来解决逻辑难以复用问题

前面有个例子是获取屏幕宽度变化的例子,假设我们有诸多组件都需要这个逻辑,那么我们只需要将其抽取成一个自定义 hook 即可,具体实现看下面例子

function useWidth (defaultWidth) {
  const [width, setWidth] = useState(document.body.clientWidth)

  const onChange = useCallback (() => {
    setWidth(document.body.clientWidth)
  }, [])

  useEffect(() => {
    window.addEventListener('resize', onChange, false)

    return () => {
      window.removeEventListener('resize', onChange, false)
    }
  }, [onChange])

  return width
}

function App () {

  const width = useWidth(document.body.clientWidth)

  return (
    <div> 
      页面宽度: { width }
    </div>
    )
}

通过上面的例子,我们可以看出

自定义 hook 是一个函数,其名称以 use 开头,函数内部可以调用其他的 hook,至于为什么要以 use 开头,是因为如果不以 use 开头,React 就无法判断某个函数是否包含对其内部 hook 的调用,React 也将无法自动检查你的 hook 是否违反了 hook 的规则,所以要以 use 开头

自定义 hook,真的很简单,不过具体什么样的逻辑,需要抽离成自定义 hook,这就需要工作中不段积累的经验去判断,避免为了 hook 而 hook

总结

在我学习和使用自定义 hook 时,我发现其实它的道理很简单,很多前端框架、库里面都有类似的概念,框架和库的设计最后都疏通同归,所以我们在学习一个新的框架、库或者理念时,不应该将其是为一个全新的东西,而更多的应该从自身掌握的内容去推导,去触类旁通,这样我们在学习的时候会事半功倍,在日益更新的前端领域,能够抽出更多的时间去理解更为核心的内容

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

react-hooks常用API基本简绍 的相关文章

  • 2020国内十大API接口服务平台

    API的概念早在上世纪60年代就已经出现 其代表的是应用程序的编程接口 是一些预先定义的函数 或指软件系统不同组成部分衔接的约定 换句话说 API是一个信使 它将用户的请求交付给用户所请求的提供者 然后将响应交付给用户 打个简单的比喻 日常

随机推荐

  • 【CVPR2023 Best Paper】Planning-oriented Autonomous Driving 阅读笔记

    Paper https openaccess thecvf com content CVPR2023 papers Hu Planning Oriented Autonomous Driving CVPR 2023 paper pdf Gi
  • 链圈的朋友们值得收藏!腾讯首席架构师教你两种区块链设计思路

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由敖萌发表于云 社区专栏 区块链发展到了现在 产生了很多不同形式的区块链技术 随着技术的发展 目前比较公认的看法是区块链已经走进了2 0时代 区块链1 0是以比特币为代表的去中心
  • 文件编码格式

    大家可能都知道文件编码格式 如gbk格式 ansi格式 字符以1byte编码 中文字符以2字节编码 unicode格式无论是字符还是中文字符都以2字节统一编码 utf 8格式则是可变长编码 不同编码格式的文件都有开头相应的字符标记来标识 如
  • pikachu靶场搭建教程(以物理主机访问虚拟机为例)

    1 提前下载好所需软件 pikachu phpstudy 服务器集成软件 2 在虚拟机上完成phpstudy的安装 并将下载好的pikachu文件夹放置于phpstudy的根目录下 例如我的是C phpstudy phpstudy pro
  • Keras学习:06.LSTM和双向LSTM讲解及实践

    本文主要介绍了LSTM与双向LSTM网路的原理和具体代码实现 长短期记忆 Long Short Term Memory LSTM 也是一种时间递归神经网络 最早由 Hochreiter Schmidhuber 在1997年提出 设计初衷是希
  • (附源码)计算机毕业设计ssm大学生心理健康管理系统

    项目运行 环境配置 Jdk1 8 Tomcat7 0 Mysql HBuilderX Webstorm也行 Eclispe IntelliJ IDEA Eclispe MyEclispe Sts都支持 项目技术 SSM mybatis Ma
  • Acwing 826. 单链表 (用数组模拟单链表)

    实现一个单链表 链表初始为空 支持三种操作 1 向链表头插入一个数 2 删除第k个插入的数后面的数 3 在第k个插入的数后插入一个数 现在要对该链表进行M次操作 进行完所有操作后 从头到尾输出整个链表 注意 题目中第k个插入的数并不是指当前
  • Remix连接本地&遇到的问题

    Remix连接本地 遇到的问题 前提条件 安装node node版本不要太低 最好14 1 安装remix npm install g remix project remixd 2 建立remix与本地文件连接 remixd s 具体文件项
  • 目标检测简介

    目标检测是一种与计算机视觉和图像处理相关的计算机技术 用于检测数字图像和视频中某一类语义对象 如人 建筑物或汽车 的实例 目标检测的研究领域包括多类别检测 边缘检测 突出目标检测 姿势检测 场景文本检测 人脸检测 行人检测等 目标检测作为场
  • C#基于LINQ对数据库的增删查改

    1 增加功能 主窗口 using System using System Collections Generic using System ComponentModel using System Data using System Draw
  • Unity 语法详解之查找游戏物体的方法(含查找隐藏物体)

    为了更好的看懂 有一个非常基础的知识 如果不知道可以移步去了解一下哦 unity gameobject和transform的区别和关联通俗解释 gameobject transform 菌菌巧乐兹的博客 CSDN博客 一 前情提要 大写的G
  • CF1512C A-B Palindrome 题解

    题目大意 给定一个字符串 长度为 a b a b a b 给定 a a a
  • 抽象方法 ——动物类的继承。

    package TcmStudy day25 abstract class Animal 抽象类 1 不能创建对象 抽象方法 没有实体 必须子类重写它 目的是为了子类完成规定动作的 起到模板的作用 子类没有重写 会报错 public abs
  • vue如何让el-breadcrumb面包屑导航栏根据路由跳转地址动态切换标题内容

    Vue如何让el breadcrumb面包屑导航栏根据路由跳转地址动态切换标题内容 废话少说 先上效果图 其实想要实现图片上的效果非常简单 我们直接使用路由元信息即可解决 关于路由元信息的解答vue router上面的开发文档写的非常详细
  • python中全部注释_Python中的注释

    1 1 注释的目的 通过用自己熟悉的语言 在程序中对某些代码进行标注说明 这就是注释的作用 能够大大增强程序的可读性 1 2 注释的分类 1 2 1 单行注释 以 开头 右边的所有东西当做说明 而不是真正要执行的程序 起辅助说明作用 我是注
  • 管道

    p The hero s birthday is birthday date format uppercase p
  • CentOS 8安装postgresql 13

    安装postgresql 登陆网址 https www postgresql org download linux redhat 选择postgresql版本和操作系统平台等信息 直接复制命令 依次执行 Install the reposi
  • ZK相关(转载)

    Paxos算法 https www douban com note 208430424 zAB https blog csdn net junchenbb0430 article details 77583955 utm medium di
  • static函数与普通函数

    全局变量 外部变量 的说明之前再冠以static 就构成了静态的全局变量 全局变量本身就是静态存储方式 静态全局变量当然也是静态存储方式 这两者在存储方式上并无不同 这两者的区别虽在于非静态全局变量的作用域是整个源程序 当一个源程序由多个源
  • react-hooks常用API基本简绍

    介绍 react hooks 是 React 16 8 的新增特性 它可以让我们在函数组件中使用 state 生命周期以及其他 react 特性 而不仅限于 class 组件 react hooks 的出现 标示着 react 中不会在存在