1.Refs

本小结参考博文
官方介绍
在典型的 React 数据流中,props 是父组件与子组件交互的唯一方式。要修改一个子组件,你需要使用新的 props 来重新渲染它。但是,在某些情况下,你需要在典型数据流之外强制修改子组件。被修改的子组件可能是一个 React 组件的实例,也可能是一个 DOM 元素。对于这两种情况,React 都提供了通过使用Refs来解决。

1.1 Refs创建

下面给出ref的三种创建形式:

  • 字符串形式的ref(过时)
  • 回调函数形式的ref
  • 函数创建

下面对三种情况分别进行介绍:

1.1.1 字符串形式的ref(过时)

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Children extends Component {sayName=()=>{}render() {return <input />;}
}
class Parent extends Component {constructor(props) {super(props);}componentDidMount() {console.dir(this.refs);// 拿到子组件内定义的方法// this.echoRef.focus();}render() {return (// 这里直接把回调传递下去了<><Children ref='echoRef' /><input ref='timeRef' /></>)}
}
ReactDOM.render(<Parent />,document.getElementById('root')
);

1.1.2 回调函数形式的ref

class App extends Component {state = { text: '' };inputRef = null;componentDidMount() {console.log('componentDidMount:', this.inputRef);}componentDidUpdate() {console.log('componentDidUpdate:', this.inputRef);}onFocus() {this.inputRef.focus();}render() {return (<div className='app'><input// 通过回调函数的形式传递 refref={ e => {this.inputRef = e;alert(e);} }text={ this.state.text }onChange={ e => {this.setState({text: e.target.value});}}/><button onClick={() => this.onFocus()}>聚焦</button></div>)}
}
const rootElement = document.getElementById("app")
ReactDOM.render(<App/>, rootElement);

回调函数会以内联函数的形式定义的,在更新的时候他会执行两次,第一次传入参数null,第二次传入参数DOM元素。·下面这种回调函数以class的绑定函数的形式定义的,可以避免上面那种两次执行情况,但是在大多数情况下是无关紧要的,所以使用上面哪种方式都行

import React, { Component } from 'react';
import ReactDOM from 'react-dom';class Children extends Component {constructor(props) {super(props);}componentDidMount() {console.dir(this.inputRef);}setRef = (e) => {this.inputRef = e;}// 此方法暴露给父组件inputFocus = () => {this.inputRef.focus();}render() {return <input ref={this.setRef} />;}}
class Parent extends Component {constructor(props) {super(props);}componentDidMount() {console.dir(this.echoRef);// 拿到子组件内定义的方法this.echoRef.inputFocus();}// 定义绑定ref函数setRef = (e) => {this.echoRef = e;}render() {return (// 这里不再直接绑定ref,而是上述函数<Children ref={this.setRef} />)}
}
ReactDOM.render(<Parent />,document.getElementById('root')
);

1.1.3 createRef

import React, { Component } from 'react';
import ReactDOM from 'react-dom';class Parent extends Component {constructor(props) {super(props);// 创建一个ref,这个ref随便你取什么名字this.echoRef = React.createRef();}componentDidMount(){console.log(this.echoRef);}render() {// 这里的ref就是必须这么写了,通过ref属性将this.echoRef与子组件关联return <div ref={this.echoRef}>你好啊,echo。</div>}
}
ReactDOM.render(<Parent />,document.getElementById('root')
);

当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。值得注意的是一个ref,用在了多个元素上它永远以最后关联的DOM为准

import React, { Component, Fragment } from 'react';
import ReactDOM from 'react-dom';class Parent extends Component {constructor(props) {super(props);// 创建一个ref,这个ref随便你取什么名字this.echoRef = React.createRef();}componentDidMount() {console.dir(this.echoRef.current);// 这里调用了孙子组件的方法this.echoRef.current.timeStepRef.current.handleClick();}render() {return (<Children ref={this.echoRef} userName="echo" />)}
}class Children extends Component {constructor(props) {super(props);this.timeStepRef = React.createRef();}state = {userName: '听风是风'}// 这个方法给父组件调用handleClick = () => { console.log('我在调用子组件的方法。') }render() {return (<Grandson ref={this.timeStepRef} />)}
}class Grandson extends Component {constructor(props) {super(props)}// 这个方法给祖父组件使用handleClick = () => { console.log('我是给上上层组件使用的方法') }render() {return (<div>你好,我是孙子组件。</div>)}
}
ReactDOM.render(<Parent />,document.getElementById('root')
);

当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性。如上图的对象解构,我们在父级组件通过this.echoRef.current.timeStepRef.current.handleClick();调用了孙子组件的方法,所以不管组件嵌套多少层,只有有定义ref你就一定能向下访问到你想要的属性,当然,这种做法非常不好!你不能在函数组件上使用 createRef属性,因为他们没有实例。比如下面这个例子:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';function Children () {return <div>我是子组件</div>;
}
class Parent extends Component {constructor(props) {super(props);// 创建一个ref,这个ref随便你取什么名字this.echoRef = React.createRef();}componentDidMount() {console.dir(this.echoRef.current);}render() {return (//函数组件无法被直接使用<Children ref={this.echoRef} userName="echo" />)}
}
ReactDOM.render(<Parent />,document.getElementById('root')
);

但是呢,我们是可以在函数组件内,为其它DOM或者组件绑定ref,比如这个例子:

import React, { createRef } from 'react';
import ReactDOM from 'react-dom';function Children(props, ref) {const inputRef =createRef();const handleClick = ()=>{inputRef.current.focus();}return (//react渲染需要一个父组件,当没有父组件时,就可以使用<>这个空标签 也可以使用<Fragment><><input ref={inputRef} /><button onClick={handleClick}>点我让输入框聚焦</button></>);
}
ReactDOM.render(<Children />,document.getElementById('root')
);

1.2 Refs转发(forwardRef )

  • 可以给函数组件绑定ref,
  • ref转发

Ref 转发是一个可选特性,其允许某些组件接收 ref,并将其向下传递(换句话说,“转发”它)给子组件。如果要在函数组件中使用 ref,你可以使用 forwardRef(可与 useImperativeHandle 结合使用)实现。

import React, { Component, forwardRef, useRef, useImperativeHandle, createRef } from 'react';
import ReactDOM from 'react-dom';function Children(props, ref) {// useRef是一个hook,你只用知道它可以创建refconst inputRef = useRef();// 你可以通过这种方式创建// const inputRef = createRef()const sayName = () => {console.log(1);}useImperativeHandle(ref, () => ({focus: () => {// 这里操作的是input自带的focus方法inputRef.current.focus();}}));return <input ref={inputRef} />;
}
// 由于函数组件不能用ref,这里使用`forwardRef`包裹了一层
Children = forwardRef(Children);
class Parent extends Component {constructor(props) {super(props);// 创建一个ref,这个ref随便你取什么名字this.echoRef = React.createRef();}componentDidMount() {console.log(this.echoRef);this.echoRef.current.focus();}render() {return (<Children ref={this.echoRef} />)}
}
ReactDOM.render(<Parent />,document.getElementById('root')
);
  • 首先forwardRef接受一个函数,此函数支持2个参数props与ref,props很好理解,就是上层传递下来的属性,而ref自然也是上层传递下来的ref。比较巧的是我们的Children本身就是个函数,因此我们直接使用forwardRef进行了包裹,可以理解为给组件升了个级。

  • 而在Children内部const inputRef = useRef()这一句,也是使用hook提供的API创建一个ref,他与createRef的原理以及含义上有一定差异,不过这里我们就理解为创建了一个ref。

  • 紧接着inputRef与函数组件内部的input相关联,也就是说现在函数组件内是可以直接使用input内置的属性方法。前面说了,函数组件自己内部还是可以使用ref的,只是我们不能直接用ref关联一个函数组件,但是前面我们通过forwardRef给函数组件升了级。

  • 紧接着,我们通过useImperativeHandle将函数组件内部能访问到的input上的属性方法,再次暴露给了父组件,useImperativeHandle中的ref其实就是上层传递的,这里就是通过此方法,将上层ref与函数组件内部产生了关联。我们自己定义了一个focus方法,而这个方法内部执行的却是input的focus方法,组件内部可以通过inputRef.current.focus访问到input的方法。

  • 于是我们在父组件中通过this.echoRef.current.focus()访问到了函数组件暴露给它的方法,而这个方法本质执行的其实是input自带的focus方法。

  • 不知道你理解没有,这里我们通过forwardRef帮父组件做了一次转发,父组件其实想访问的就是input的方法,但是函数组件在中间隔了一层,父组件就没法直接拿到,而我们通过useImperativeHandle帮父组件代劳了一次,成功达到了目的。

其实forwardRef除了能让函数组件使用ref外,还有另一种强大的作用就是转发ref

  • 比如A>B>C的组件结构,你在A中创建了一个ref,你希望将这个ref作为props传递给B,然后在B中接受这个ref再去去关联C,以达到在A中可以访问到C的属性。我们可以假想有一个hoc的场景,父组件希望访问B组件,但是B组件被hoc包裹了一层,也就是一个高阶组件。此时你的ref假设绑定在了hoc生成的B,那么ref将访问hoc组件而非B组件。那么怎么让父组件可以访问到这个B组件呢?我们可以借用forwardRef:
import React, { Component, forwardRef } from 'react';
import ReactDOM from 'react-dom';function hocComponent(Component) {// 单纯包装了传入的组件,生成了一个新的组件,只是在生成中我们还用了forwardRef在外面包了一层return forwardRef((props, ref) => {return <Component {...props} ref={ref} />})
}
class Parent extends Component {constructor(props) {super(props);// 创建一个ref,这个ref随便你取什么名字this.echoRef = React.createRef();}componentDidMount() {console.log(this.echoRef);this.echoRef.current.handleClick();}render() {// 传入Children给高阶组件,得到了一个新组件const Child = hocComponent(Children);return (<Child ref={this.echoRef} />)}
}
class Children extends Component {constructor(props) {super(props);}handleClick = () => {console.log('给父级调用的方法')}render() {return <>我是子组件啊</>;}
}
ReactDOM.render(<Parent />,document.getElementById('root')
);

这个例子就解释了hoc的情况,这个例子相对上面参杂了hook的例子来说应该好理解一点,这里就不多解释。至少到这里,我们解释了forwardRef的两种作用,一是也可以给函数组件绑定ref,第二点就是ref转发,比如hoc包裹,我们绕过绕过高阶组件,拿到高阶组件内部真正的组件属性。

另外!!!A>B>C,假设B是函数组件,我们希望A的ref绑定C从而访问C,其实还有一种做法,就是不要直接ref绑定,而是把ref作为props传递下去后再绑定,这样不管B是不是函数组件,都能成功绑定到C,再来个例子:

import React, { Component, forwardRef } from 'react';
import ReactDOM from 'react-dom';function Children(props) {return (// 子组件接受了这个ref,然后再通过ref进行绑定<input ref={props.inputRef} />);
}class Parent extends React.Component {constructor(props) {super(props);this.echoRef = React.createRef();}componentDidMount() {console.dir(this.echoRef.current);}handleClick = () => {// 成功访问了子组件下的子组件this.echoRef.current.focus();}render() {return (<><ChildreninputRef={this.echoRef}//我们希望把这个ref作为props传递下去/><button onClick={this.handleClick}>点我聚焦</button></>);}
}
ReactDOM.render(<Parent />,document.getElementById('root')
);

因为给函数组件上添加ref会警告,那么我们就不用ref,而是把创建的ref作为属性传下去,在子组件中接受后,再绑定给你要访问的DOM或者组件,这样不仅解决了函数组件绑定ref的问题,还搞定了ref转发的问题。

1.3 注意事项

另外,我们在通过ref获取子组件属性时,比如获取一个函数,请注意函数的写法,比如这个例子中,我们能拿到sayName,但拿不到sayAge,这是因为后者本质上是绑定在原型上,无法通过这种方式直接访问,但是你可以通过原型找到它。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';class Children extends Component {constructor(props) {super(props);}sayName = () => { }sayAge() { }render() {// 父级传递来的props,最后给了input用了return <input />;}}
class Parent extends Component {constructor(props) {super(props);}componentDidMount() {console.dir(this.echoRef);}// 定义绑定ref函数setRef = (e) => {this.echoRef = e;}render() {return (// 这里直接把回调传递下去了<Children ref={this.setRef} />)}
}
ReactDOM.render(<Parent />,document.getElementById('root')
);

2. Hooks

Hook 是 React 16.8 的新增特性。什么时候我会用 Hook? 如果你在编写函数组件并意识到需要向其添加一些 state,以前的做法是必须将其转化为 class。现在你可以在现有的函数组件中使用 Hook。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

2.1 State Hook (useState)

调用 useState 方法的时候做了什么? 它定义一个 “state 变量”。我们的变量叫 count, 但是我们可以叫他任何名字,比如 banana。这是一种在函数调用时保存变量的方式 —— useState 是一种新方法,它与 class 里面的 this.state 提供的功能完全相同。一般来说,在函数退出后变量就会”消失”,而 state 中的变量会被 React 保留。

useState 需要哪些参数? useState() 方法里面唯一的参数就是初始 state。不同于 class 的是,我们可以按照需要使用数字或字符串对其进行赋值,而不一定是对象。在示例中,只需使用数字来记录用户点击次数,所以我们传了 0 作为变量的初始 state。(如果我们想要在 state 中存储两个不同的变量,只需调用 useState() 两次即可。)

useState 方法的返回值是什么? 返回值为:当前 state 以及更新 state 的函数。这就是我们写 const [count, setCount] = useState() 的原因。这与 class 里面 this.state.count 和 this.setState 类似,唯一区别就是你需要成对的获取它们。如果你不熟悉我们使用的语法,我们会在本章节的底部介绍它。

import React, { useState } from 'react';function Example() {// 声明一个叫 "count" 的 state 变量const [count, setCount] = useState(0);return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}
  • 读取 State

当我们想在 class 中显示当前的 count,我们读取 this.state.count:

<p>You clicked {this.state.count} times</p>

在函数中,我们可以直接用 count:

<p>You clicked {count} times</p>
  • 更新 State

在 class 中,我们需要调用 this.setState() 来更新 count 值:

  <button onClick={() => this.setState({ count: this.state.count + 1 })}>Click me</button>

在函数中,我们已经有了 setCount 和 count 变量,所以我们不需要 this:

  <button onClick={() => setCount(count + 1)}>Click me</button>

2.2 Effect Hook (useEffect)

你之前可能已经在 React 组件中执行过数据获取、订阅或者手动修改过 DOM。我们统一把这些操作称为“副作用”,或者简称为“作用”。useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用的能力。它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API。

import React, { useState, useEffect } from 'react';function Example() {const [count, setCount] = useState(0);// Similar to componentDidMount and componentDidUpdate:useEffect(() => {// Update the document title using the browser APIdocument.title = `You clicked ${count} times`;});return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}

在 React 的 class 组件中,render 函数是不应该有任何副作用的。一般来说,在这里执行操作太早了,我们基本上都希望在 React 更新 DOM 之后才执行我们的操作。

这就是为什么在 React class 中,我们把副作用操作放到 componentDidMount 和 componentDidUpdate 函数中。回到示例中,这是一个 React 计数器的 class 组件。它在 React 对 DOM 进行操作之后,立即更新了 document 的 title 属性。

class Example extends React.Component {constructor(props) {super(props);this.state = {count: 0};}componentDidMount() {document.title = `You clicked ${this.state.count} times`;}componentDidUpdate() {document.title = `You clicked ${this.state.count} times`;}render() {return (<div><p>You clicked {this.state.count} times</p><button onClick={() => this.setState({ count: this.state.count + 1 })}>Click me</button></div>);}
}

注意,在这个 class 中,我们需要在两个生命周期函数中编写重复的代码。这是因为很多情况下,我们希望在组件加载和更新时执行同样的操作。从概念上说,我们希望它在每次渲染之后执行 —— 但 React 的 class 组件没有提供这样的方法。即使我们提取出一个方法,我们还是要在两个地方调用它。现在让我们来看看如何使用 useEffect 执行相同的操作。

import React, { useState, useEffect } from 'react';function Example() {const [count, setCount] = useState(0);useEffect(() => {document.title = `You clicked ${count} times`;});return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}

useEffect 做了什么? 通过使用这个 Hook,你可以告诉 React 组件需要在渲染后执行某些操作。React 会保存你传递的函数(我们将它称之为 “effect”),并且在执行 DOM 更新之后调用它。在这个 effect 中,我们设置了 document 的 title 属性,不过我们也可以执行数据获取或调用其他命令式的 API。

为什么在组件内部调用 useEffect? 将 useEffect 放在组件内部让我们可以在 effect 中直接访问 count state 变量(或其他 props)。我们不需要特殊的 API 来读取它 —— 它已经保存在函数作用域中。Hook 使用了 JavaScript 的闭包机制,而不用在 JavaScript 已经提供了解决方案的情况下,还引入特定的 React API。

useEffect 会在每次渲染后都执行吗 是的,默认情况下,它在第一次渲染之后和每次更新之后都会执行。(我们稍后会谈到如何控制它。)你可能会更容易接受 effect 发生在“渲染之后”这种概念,不用再去考虑“挂载”还是“更新”。React 保证了每次运行 effect 的同时,DOM 都已经更新完毕。

与 componentDidMount 或 componentDidUpdate 不同,使用 useEffect 调度的 effect 不会阻塞浏览器更新屏幕,这让你的应用看起来响应更快。大多数情况下,effect 不需要同步地执行。在个别情况下(例如测量布局),有单独的 useLayoutEffect Hook 供你使用,其 API 与 useEffect 相同。

2.2.1 effect 清除

之前,我们研究了如何使用不需要清除的副作用,还有一些副作用是需要清除的。例如订阅外部数据源。这种情况下,清除工作是非常重要的,可以防止引起内存泄露!在 React class 中,你通常会在 componentDidMount 中设置订阅,并在 componentWillUnmount 中清除它。例如,假设我们有一个 ChatAPI 模块,它允许我们订阅好友的在线状态。以下是我们如何使用 class 订阅和显示该状态:

class FriendStatus extends React.Component {constructor(props) {super(props);this.state = { isOnline: null };this.handleStatusChange = this.handleStatusChange.bind(this);}componentDidMount() {ChatAPI.subscribeToFriendStatus(this.props.friend.id,this.handleStatusChange);}componentWillUnmount() {ChatAPI.unsubscribeFromFriendStatus(this.props.friend.id,this.handleStatusChange);}handleStatusChange(status) {this.setState({isOnline: status.isOnline});}render() {if (this.state.isOnline === null) {return 'Loading...';}return this.state.isOnline ? 'Online' : 'Offline';}
}

你可能认为需要单独的 effect 来执行清除操作。但由于添加和删除订阅的代码的紧密性,所以 useEffect 的设计是在同一个地方执行。如果你的 effect 返回一个函数,React 将会在执行清除操作时调用它:

import React, { useState, useEffect } from 'react';function FriendStatus(props) {const [isOnline, setIsOnline] = useState(null);useEffect(() => {function handleStatusChange(status) {setIsOnline(status.isOnline);}ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);// Specify how to clean up after this effect:return function cleanup() {ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);};});if (isOnline === null) {return 'Loading...';}return isOnline ? 'Online' : 'Offline';
}

为什么要在 effect 中返回一个函数? 这是 effect 可选的清除机制。每个 effect 都可以返回一个清除函数。如此可以将添加和移除订阅的逻辑放在一起。它们都属于 effect 的一部分。

React 何时清除 effect? React 会在组件卸载的时候执行清除操作。正如之前学到的,effect 在每次渲染的时候都会执行。这就是为什么 React 会在执行当前 effect 之前对上一个 effect 进行清除。

2.2.2 effect 性能优化

在某些情况下,每次渲染后都执行清理或者执行 effect 可能会导致性能问题。在 class 组件中,我们可以通过在 componentDidUpdate 中添加对 prevProps 或 prevState 的比较逻辑解决:

componentDidUpdate(prevProps, prevState) {if (prevState.count !== this.state.count) {document.title = `You clicked ${this.state.count} times`;}
}

这是很常见的需求,所以它被内置到了 useEffect 的 Hook API 中。如果某些特定值在两次重渲染之间没有发生变化,你可以通知 React 跳过对 effect 的调用,只要传递数组作为 useEffect 的第二个可选参数即可:

useEffect(() => {function handleStatusChange(status) {setIsOnline(status.isOnline);}ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);return () => {ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);};
}, [props.friend.id]); // 仅在 props.friend.id 发生变化时,重新订阅

上面这个示例中,我们传入 [props.friend.id] 作为第二个参数。这个参数是什么作用呢?如果 [props.friend.id]的值是 5,而且我们的组件重渲染的时候 [props.friend.id] 还是等于 5,React 将对前一次渲染的 [5] 和后一次渲染的 [5] 进行比较。因为数组中的所有元素都是相等的(5 === 5),React 会跳过这个 effect,这就实现了性能的优化。

当渲染时,如果 [props.friend.id]的值更新成了 6,React 将会把前一次渲染时的数组 [5] 和这次渲染的数组 [6] 中的元素进行对比。这次因为 5 !== 6,React 就会再次调用 effect。如果数组中有多个元素,即使只有一个元素发生变化,React 也会执行 effect。

2.3 Hook 规则

2.3.1 只在最顶层使用 Hook

不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层以及任何 return 之前调用他们。

function Form() {// 1. Use the name state variableconst [name, setName] = useState('Mary');// 2. Use an effect for persisting the formuseEffect(function persistForm() {localStorage.setItem('formData', name);});// 3. Use the surname state variableconst [surname, setSurname] = useState('Poppins');// 4. Use an effect for updating the titleuseEffect(function updateTitle() {document.title = name + ' ' + surname;});// ...
}

那么 React 怎么知道哪个 state 对应哪个 useState?答案是 React 靠的是 Hook 调用的顺序。因为我们的示例中,Hook 的调用顺序在每次渲染中都是相同的,所以它能够正常工作:

// ------------
// 首次渲染
// ------------
useState('Mary')           // 1. 使用 'Mary' 初始化变量名为 name 的 state
useEffect(persistForm)     // 2. 添加 effect 以保存 form 操作
useState('Poppins')        // 3. 使用 'Poppins' 初始化变量名为 surname 的 state
useEffect(updateTitle)     // 4. 添加 effect 以更新标题// -------------
// 二次渲染
// -------------
useState('Mary')           // 1. 读取变量名为 name 的 state(参数被忽略)
useEffect(persistForm)     // 2. 替换保存 form 的 effect
useState('Poppins')        // 3. 读取变量名为 surname 的 state(参数被忽略)
useEffect(updateTitle)     // 4. 替换更新标题的 effect

只要 Hook 的调用顺序在多次渲染之间保持一致,React 就能正确地将内部 state 和对应的 Hook 进行关联。但如果我们将一个 Hook (例如 persistForm effect) 调用放到一个条件语句中会发生什么呢?

  // 												

react04-Ref与Hook相关推荐

  1. git hook分支_Git hook(钩子文件)机制

    githooks(5) NAME githooks - Hooks(钩子) used by git SYNOPSIS $GIT_DIR/hooks/* 简介 Hooks(钩子),是一些存放于$GIT_ ...

  2. 16.钩子事件hookEvent与插件。

    概览 1.hookEvent 是 Vue 的自定义事件结合生命周期钩子实现的一种从组件外部为组件注入额外生命周期方法的功能. 2.插件用于增强Vue. 1.hookEvent 是 Vue 的自定义事件 ...

  3. 前端面试题----百题大战(超详细哦,包含代码和示例哦,记得一键三连哦,持续更新中ing...)

    你在前端开发中使用过哪些框架和库?简要介绍一下它们和它们的优点和缺点. Vue.js:Vue.js 是一个渐进式 JavaScript 框架,它通过组合各种特性和插件,支持更加灵活的功能开发和定制化, ...

  4. reactjs三个常用的Hook:State Hook、 Effect Hook、 Ref Hook

    1. React Hook/Hooks是什么? (1). Hook是React 16.8.0版本增加的新特性/新语法 (2). 可以让你在函数组件中使用 state 以及其他的 React 特性 2. ...

  5. React 学习笔记 —— Ref Hook

    用以下三种方式创建 Ref 都可以 import React from 'react'export default function Count () {const [count ,setCount] ...

  6. ref使用之react / react hook

    在react典型的数据流中,props传递是父子组件交互的一种方式:通过传递一个新的props值来使子组件重新render,从而达到父子组件通信.某些情况下(例如和第三方的dom库整合,或者某个dom ...

  7. react学习—ref Hook

    ref Hook 一.ref Hook 1.useRef 2.其它使用 一.ref Hook 1.useRef useRef函数: 一个参数:默认值 返回一个固定的对象,{current: 值} im ...

  8. vue3学习笔记(ref, reactive, setup, hook...)

    目录 一.搭建项目 二.常用的Composition API 1.ref函数(实现响应式) 2.reactive函数 3.vue2和vue3响应式的区别 4. setup参数 5.计算属性和监视 6. ...

  9. 浅谈react hook ( ref)

    import React ,{useRef,useState,PureComponent} from "react"; import ReactDOM from "rea ...

  10. hook修改信息_React系列二十一 Hook(二)高级使用

    一. Hook高级使用 1.1. useReducer 很多人看到useReducer的第一反应应该是redux的某个替代品,其实并不是. useReducer仅仅是useState的一种替代方案: ...

最新文章

  1. python字符串转浮点数
  2. ​孙家广院士:大数据软件的机遇与挑战
  3. ld3320语音识别模块工作原理_变频空调功率模块工作原理与故障检测
  4. 模板方法在Spring事务中的应用
  5. 关于毕业租房的一些碎碎念。
  6. CentOS 安装过程中格式化 SATA 硬盘巨慢的问题
  7. HTML5 响应式图片
  8. go语言快速刷《程序员面试金典》(3)
  9. LeetCode 1488. 避免洪水泛滥(贪心+set二分查找)
  10. IP计算机取证,计算机取证1资料.doc
  11. 在线重定义生产环境大表分区的惨烈踩雷记录
  12. 接口测试--测试工具apipost脚本大全
  13. 安卓获取res下的资源文件:string字符串、color颜色、dimen尺寸、array数组、drawable图片和xml、anim/animator动画、raw媒体、assets资源
  14. 比较sql server两个数据库
  15. cmd的常用命令分类详解
  16. 靶机Tempus Fugit wirteup
  17. 华为MateBook D加装硬盘和内存
  18. 启发式搜索: A*算法
  19. JVM致命错误日志(hs_err_pid.log)解读
  20. PHP一句话木马免杀(通过VirusTotal测试)

热门文章

  1. Unity关于无法新建项目的可能解决办法
  2. 客制化键盘编程_客制化键盘QMK固件入门-修改keyboard和keymap
  3. java程序员学习路线指南
  4. 大学一级课题c语言报告,c语言一级课题总结(16页)-原创力文档
  5. EMV技术学习和研究(三)应用初始化读应用数据
  6. 超链接标签 a (锚点链接)
  7. Android模拟点击的四种方式
  8. NRF51822重启程序跑不起来不运行的解决办法,amazing!!!
  9. 蓝牙芯片|伦茨科技-智能蓝牙BLE5.2芯片ST17H66
  10. 解决:“由于可能不会将凭据发送到远程计算机,因此将不会进行连接。若要获得协助,请与您的系统管理员联系”