学习 React 笔记
官方教程
React API
React.Component
定义组件的Class基类,返回一个render(),其中是JSX描述的DOM结构,会通过React.CreateElement()创建为真是的DOM
React.mome
通过对比上一次和下一次的props,提示渲染组件组件的性能,接受第二个参数为函数,可以控制对比过程
React.Fragment
可以使得组件在不创建额外DOM元素的情况下,让 render()
方法中返回多个元素,可以使用<>..</>
代替。
React.forwardRef
React.forwardRed 会创建一个React组件,这个组件可以接受 ref 属性转发到其组件树下的另一个组件中,在以下两个场景时比较有用
- 转发 refs 到 DOM 组件中
- 在高阶组件中转发 refs
React.Refs
可以使用这个API访问DOM节点或者在render方法中创建React元素
在不同的组件中使用不同的Ref方法
- 在Class组件中使用React.createRef
- 在函数组件中使用React.forwardRef(或则useRef)
编写一个自动聚焦的输入框
- Class Component
class NameForm extends React.Component {
constructor(props) {
super(props);
this.inpRef = React.createRef()
}
componentDidMount() {
this.inpRef.current.focus();
}
render() {
return (
<div>
<input ref={this.inpRef}></input>
</div>
)
}
}
ReactDOM.render(
<NameForm />,
document.getElementById('app')
);
- Function Component(Hook)
function NameForm() {
const inpRef = React.useRef(null)
React.useEffect(()=>{
inpRef.current.focus()
},[])
return <input ref={inpRef}></input>
}
ReactDOM.render(
<NameForm />,
document.getElementById('app')
);
JSX
JSX是通过JS编写HTML结构的语法。
function App() {
return (
<p className="title">hello world</p>
);
}
ReactDOM.render(<APP />, document.getElementById("root"));
通过React.render(<App/>
, root) 将虚拟DOM转化为真实的DOM节点,并挂载到指定的节点上
而第一个参数必须有一个子节点,如果不提供可以使用React.Fragments或者<>...</>
替代。
而在这一步中,经过Babel转换后的代码如下:
function App() {
return React.createElement(
"p",
{ className: "title" },
"hello world"
);
}
ReactDOM.render(React.createElement(APP, null), document.getElementById("root"));
- React.createElement是JSX的语法糖,会把JSX语法转换为虚拟DOM
- React.render会将虚拟DOM转化为真实的DOM,并挂在指定的元素上
事件处理
- 事件命名采用小驼峰式(onClick)
- 使用JSX语法时应该传入一个函数(箭头函数,确保this正确),而不是一个字符串
// 创建是秃头
class MessageBox extends React.Component {
alertMe() {
alert('你刚才点了我一下。。。。');
}
render() {
return (
<div>
<h2 onClick={this.alertMe}>我会弹窗</h2>
<h2 onClick={(e) => { e.preventDefault() }}>禁止弹窗</h2>
</div>
)
}
}
// 渲染
ReactDOM.render(<MessageBox />, document.getElementById('app'), function () {
console.log('渲染完成啦!!');
});
条件处理
- 通过if-else去判断
function Demo(props) {
let dom;
if(props.isShow){
return <h1>Message!</h1>
}else{
return <h1></h1>
}
}
ReactDOM.render(<Demo isShow={true}/>, document.getElementById('app'));
- 元素变量
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = { isShow: true };
}
render() {
let isShow = this.state.isShow;
let button;
if (isShow) {
button = <div>你好</div>
} else {
button = <div>世界</div>
}
return (
<div>
{button}
<button onClick={() => this.setState({ isShow: !this.state.isShow })} >Change</button>
</div>
);
}
}
ReactDOM.render(
<Demo />,
document.getElementById('app')
);
- 与运算符 &&
条件一 && 条件二:条件一为真就展示条件二,条件一位假,就不展示。
编写一个展示水果数据,没有的时候就不显示。
function List(props){
let {list} = props
return (
<div>
{list.length !== 0 && <p>{list.toString()}</p>}
</div>
)
}
function Demo(props){
return (
<div>
<List list={['苹果','香蕉']}/>
<List list={[]}/>
<List list={['橘子','凤梨']}/>
</div>
)
}
ReactDOM.render(
<Demo/>,
document.getElementById('app')
);
- 三目运算符
还用水果列表
function List(props){
let {list} = props
return (
<div>
{list.length === 0 ? <p>--无数据--</p> : <p>{list.toString()}</p>}
</div>
)
}
function Demo(props){
return (
<div>
<List list={['苹果','香蕉']}/>
<List list={[]}/>
<List list={['橘子','凤梨']}/>
</div>
)
}
ReactDOM.render(
<Demo/>,
document.getElementById('app')
);
- 阻止组件渲染
判断条件,适当的返回null即可
function List(props){
let {list} = props
if(list.length === 0){
return null
}
return (
<div>
<p>{list.toString()}</p>
</div>
)
}
function Demo(props){
return (
<div>
<List list={['苹果','香蕉']}/>
<List list={[]}/>
<List list={['橘子','凤梨']}/>
</div>
)
}
ReactDOM.render(
<Demo/>,
document.getElementById('app')
);
列表 && Key
可以使用 map 渲染多个列表
key可以帮助React识别哪些元素改变了,比如删除或者添加,给每个元素唯一的标示,一般使用id或者index。
function List(props){
let {list} = props;
return (
<div>
<h3>水果列表</h3>
<ul>{list.map((e,i)=><li key={i}>{e}</li>)}</ul>
</div>
)
}
function Demo(props){
return (
<div>
<List list={['苹果','香蕉']}/>
<List list={['橘子','凤梨']}/>
</div>
)
}
ReactDOM.render(
<Demo/>,
document.getElementById('app')
);
表单
受控组件:如input、textarea、select通常维护自己的state,并且根据用户输入进行更新,通过setState更新。
在HTML中,标签、<textarea>、的值的改变通常是根据用户输入进行更新。在React中,可变状态通常保存在组件的状态属性中,并且只能使用 setState() 更新,而呈现表单的React组件也控制着在后续用户输入时该表单中发生的情况,以这种由React控制的输入表单元素而改变其值的方式,称为:“受控组件”。
————————————————
原文链接:https://blog.csdn.net/qq_41846861/article/details/86598797
使用表单和列表编写一个可以添加的表单列表
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = { value: '', list: [1,2] };
}
handleChange = (event)=> {
this.setState({ value: event.target.value });
}
handleSubmit = (event) => {
this.setState({ list: [...this.state.list, this.state.value]})
console.log(this.state.list,this.state.value)
event.preventDefault();
}
render() {
let {list} = this.state
return (
<div>
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
<List list={list} />
</div>
)
}
}
function List(props) {
let list = props.list;
// return <p>{list.toString()}</p>
return <ul>{list.map((e, i) => { return <li key={i}>{e}</li> })}</ul>
}
ReactDOM.render(
<NameForm />,
document.getElementById('app')
);
组件
组件的使用直接嵌入组件即可:
props<object>:组件内接受到的值,可以使用 componentName.defaultProps = {value: 0},设置默认值,需规范props的类型和是否必要时,请使用prop-type
state<object>:组件内的状态,可以使用this.setState({value:0}),改变(覆盖)state,并更新到DOM
PS:组件的props不可更改!
class组件
需要从React.Component上继承,有state,和props,有生命周期。
class List extends React.Component {
constructor(props){
super(props)
}
render(){
const {list} = this.props;
return
<div>
{list.map((item,index)=>{
return
<li key={item.id}>
<span>{item.title}</span>
</li>
})}
<div>
}
}
特点
有组件实例
有生命周期
有state 和 setState
函数组件
直接写一个函数,接收props(相当于函数参数),
function List(props){
const list = props;
reutrn <ul>
{list.map((item,index)=>{
return <li key={item.id}>
{item.title}
</li>
})}
</ul>
}
特点
没有组件实例
没有生命周期
没有state和setState,只有props
State和生命周期
state
类似Vue中的data,数据改变会同步更新到DOM,任何组件的state都是私有的(可以使用props传递),state只存在Class组件中。
更改state时,不可以直接this.state.value = newValue,而需要使用this.setState({value: newValue}),去替换原值。
异步的state,出于对性能的考虑,React会合并个多this.setState操作一起调用,
数据向下的,state是局部的私有的,出了拥有并且使用props传递的组件,其他组件都无法访问
// 创建时钟
class Clock extends React.Component {
constructor(props) {
super(props)
this.state = { date: new Date() }
}
// 组件挂载
componentDidMount() {
this.timer = setInterval(this.tick.bind(this), 1000)
}
// 组件卸载
componentWillUnmount() {
clearInterval(this.timer);
}
// 时间更新
tick() {
this.setState({ date: new Date() })
}
render() {
return (<h2>{`${this.state.date.toLocaleDateString()}