React组件知识简介
一、什么是组件
-
组件:组件是React的核心概念之一,在React中,前端的生态的搭建,功能的实现的基本单位,就是组件。React就是使用组件完成各个页面的渲染,功能的组合的,因此掌握组件知识是必要的。
-
类组件:
在react引入JavaScript ES6语法支持后,react对应的支持了新的类组件方式,用于代替原生类创建方式:React.createClass,可以通过继承React.Component实现了类组件的创建。
实现一个完整的类组件需要:
-
class
组件需要继承React.component
-
在
render
函数中return
一个react
元素,且render
函数必须实现
class App extends React.Component { constructor(props) { super(props); this.state = { value: '', }; } onChange = event => { this.setState({ value: event.target.value }); }; render() { return ( <div> <h1>Hello React Class Component!</h1> <input value={this.state.value} type="text" onChange={this.onChange} /> <p>{this.state.value}</p> </div> ); } }
-
-
函数组件
函数组件等效于 React 类组件,但其本质表示为一个函数而不是类,并且,函数组件中不存在状态或副作用 — 这就是为什么它们被称为功能无状态组件。当然,这里的不存在是指不能像类组件一样,可以直接管理自己props,函数组件则是使用React中的各种内置钩子来实现自身状态或副作用,这些钩子统一使用useXXX形式来命名,例如常用的useState()。
实现一个完整的函数组件需要:
- 组件的声明名必须首字母大写
- 最终要
return
一个react
元素 - 可以接收
props
对象作为参数(可为空)
const App = () => { const [value, setValue] = React.useState(''); const onChange = event => setValue(event.target.value); return ( <div> <h1>Hello React Function Component!</h1> <input value={value} type="text" onChange={onChange} /> <p>{value}</p> </div> ); };
二、受控组件
当组件的表单状态发生更新,onChange触发后由自身拦截并且使用state完成内部的状态管理,可对自身状态进行校验、过滤等操作。
-
特点
- 使用state管理状态变更
- onChange触发对应更新state事件
- setState完成页面渲染更新
-
示例
import React, { useState } from 'react'; const ControlledComponent = () => { const [value, setValue] = useState(''); const handleChange = event => setValue(event.target.value); return ( <div> <label> 输入: <input type="text" value={value} onChange={handleChange} /> </label> <p> <strong>输出:</strong> {value} </p> </div> ); }; export default ControlledComponent;
三、非受控组件
通过ref直接获取输入框的值,只获取到最后状态的结果值,在输入过程中没有对表单输入数据的操作,表单数据将交由 DOM 节点来处理。
-
特点
- ref实例和输入框的ref进行绑定
- 使用ref.current.value获取表单的值进行数据组装和提交
-
示例
import React, { useRef } from "react"; function UnControlledComponent() { const inputValue = useRef(); function handelClick() { const data = { name: inputRef.current.value, }; console.log(data); } return ( <div> 输入:<input ref={inputValue}></input> <button onClick={handelClick}>提交</button> </div> ); } export default UnControlledComponent;
注意:对于受控或非受控元素,组件本身是函数组件还是类组件都无关紧要。不受控制的元素(如文本输入、复选框、单选按钮和带有输入的整个表单)始终可以不受控制或控制。
四、组件的通信
-
4.1、组件之间的状态数据传递
-
使用props进行数据传递
import React from 'react'; const App = () => { const greeting = 'Welcome to React'; return ( <div> <Welcome text={greeting} /> </div> ); }; const Welcome = (props) => { return <h1>{props.text}</h1>; }; export default App;
-
使用解构props进行数据传递
import React from 'react'; const App = () => { const greeting = 'Welcome to React'; return ( <div> <Welcome text={greeting} /> {/*或者<Welcome text={"Welcome to React"} />*/} </div> ); }; const Welcome = ({ text }) => { return <h1>{text}</h1>; }; export default App;
-
使用内联pros进行数据传递
import * as React from 'react'; const App = () => { const greetingObject = { greeting: 'Welcome to React' }; return ( <div> <Welcome text={greetingObject} /> {/*或者<Welcome text={{ greeting: 'Welcome to React' }} />*/} </div> ); }; const Welcome = ({ text }) => { return <h1>{text.greeting}</h1>; }; export default App;
-
-
4.2、组件之间的状态控制管理
-
一般来说,有状态就会有对应的状态管理,在React中,一般通过useState来完成状态管理,但是这仅仅限于组件内部,因为 props 是只读的,不可变的,因此如果你想要交互式 React 组件,你必须使用一个控制函数来完成状态的控制。
import React from 'react'; const App = () => { const [count, setCount] = React.useState(0); return ( <div> {/*Button子组件*/} <Button label={count} disabled={true} {/*状态控制方法:() => setCount(count + 1)*/} onClick={() => setCount(count + 1)} /> </div> ); }; const Button = ({ label, disabled, onClick }) => ( {/*将父组件的方法和本身的按钮事件绑定,完成父组件控制子组件的状态*/} <button disabled={disabled} onClick={onClick}> {label} </button> ); export default App;
-
五、可复用组件
对于一个优秀的前端项目来说,设计一个可复用的组件是很有必要的,因为一个可复用的组件能够完成一类功能的封装,通用性也使得代码的量级会大大优化,一个组件要足够可复用应该:
- 单独抽离作为一个新组件
- 不依赖其他组件,且可以被重复使用,状态独立
-
例子:封装一个自定义的通用按钮
const App = () => { return ( <div> <Button label={'我是第一个按钮!'} handleClick={() => console.log('你点击了第一个按钮!')} /> <Button label={'我是第二个按钮!'} handleClick={() => console.log('你点击了第二个按钮!')} /> </div> ); }; const Button = ({ label, handleClick }) => { return ( <button type="button" onClick={handleClick}> {label} </button> ); };
-
再次优化、使得它的通用性更好,可以指定类型(type)、触发和按钮展示文案
const App = () => { return ( <div> <Button handleClick={() => console.log('你点击了第一个按钮!')}> 我是第一个按钮! </Button> <Button type="submit" handleClick={() => console.log('你点击了第二个按钮!')} > 我是第二个按钮! </Button> </div> ); }; const Button = ({ type = 'button', handleClick, children }) => { return ( <button type={type} onClick={handleClick}> {children} </button> ); };