React安装和核心概念

安装

npx create-react-app 项目名称

JSX

JSX表示对象,Babel会把JSX转译成一个React.createElement()函数调用。

import React from "react"
import ReactDOM from "react-dom"
const name = "Jack"
const element = (
    <div>Hello, {name}!</div>
)
ReactDOM.render(element, document.getElementById("root"))

React DOM 在渲染所有输入内容之前,默认会进行转译。它可以确保在你的应用中,永远不会注入那些并非自己明确编写的内容。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止XSS(cross-site-scripting, 跨站脚本)攻击。

元素渲染

React元素是不可变对象,一旦被创建,你就无法更改它的子元素或者属性。

组件

注意:组件名称必须大写字母开头!!!

React会将小写字母开头的组件视为原生的DOM标签。

函数组件(无状态组件)

接收唯一带有数据的 “props”(代表属性)对象与并返回一个 React 元素。

const name = "Jack"
function Element() {
    return (<div>Hello, {name}!</div>)
}
ReactDOM.render(<Element />, document.getElementById("root"))

函数组件使用时给子组件传值转换为单个对象props传值。

function Element(props) {
    return (<div>Hello, {props.name}!</div>)
}
const element = (<Element name={name}/>)
类组件(有状态组件)
const name = "Jack"
class Element extends React.Component {
    render() {
        return (<div>Hello, {name}!</div>)
    }
}
ReactDOM.render(<Element />, document.getElementById("root"))

类组件通过props接收父组件传的值:

class Element extends React.Component {
    render() {
        return (<div>Hello, {this.props.name}!</div>)
    }
}

向class组件中添加局部的state

  • 方式1
class Element extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            age: 18
        };
    }
    render() {
        return (<div>Hello, {this.props.name}, 年龄:{this.state.age}!</div>)
    }
}
  • 方式2
class Element extends React.Component {
    state = {
        age: 18
    };
    render() {
        return (<div>Hello, {this.props.name}, 年龄:{this.state.age}!</div>)
    }
}

this.setState()更新组件,setState()的更新会合并。

class Element extends React.Component {
    state = {
        count: 0
    };
    componentDidMount() {
        this.setState({
            count: 2
        })
    }
    render() {
        return (
            <div>
                <div>计数器:{this.state.count}</div>
            </div>
        )
    }
}
Props的只读性

组件声明无论是函数组件还是类组件创建的,都不能修改props。所有的React组件都必须像纯函数一样保护它们的props不被更改。

组件的声明周期

在这里插入图片描述

class Element extends React.Component {
    /*
    * 如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。
    * 函数中不要调用setState方法
    * 避免props的值赋值给state
    */
    constructor(props) {
        super(props);
        this.state = {
            age: 18
        };
    }
    // 组件挂载时
    componentDidMount() {}
    /*
    * 组件更新后立即渲染,初次加载不执行, 如果 shouldComponentUpdate() 返回值为 false,则不会调用 componentDidUpdate()。
    * getSnapshotBeforeUpdate()的返回值是componentDidUpdate的第三个参数
    */
    componentDidUpdate(prevProps, prevState, snapshot) {}
    // 组件卸载时执行 不应调用setState,因为该组件永远不会重新渲染
    componentWillUnmount() {}
    // 唯一必须实现的方法
    render() {
        return (<div>Hello, {this.props.name}, 年龄:{this.state.age}!</div>)
    }
    // 不常用的生命周期
    // 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期方法的任何返回值将作为参数传递给 componentDidUpdate()。
    getSnapshotBeforeUpdate(prevProps, prevState) {}
    // 判断 React 组件的输出是否受当前 state 或 props 更改的影响。默认行为是 state 每次发生变化组件都会重新渲染。大部分情况下,你应该遵循默认行为。
    // 首次渲染或使用forceUpdate()时不会调用该方法   渲染执行之前被调用
    // 仅作为性能优化的方式而存在
    // 如果 shouldComponentUpdate() 返回 false,则不会调用 UNSAFE_componentWillUpdate(),render() 和 componentDidUpdate()。
    shouldComponentUpdate(nextProps, nextState, nextContext) {}
    // 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用
    static getDerivedStateFromProps(props, state) {}
    // 仅使用 Error boundaries 组件来从意外异常中恢复的情况;不要将它们用于流程控制。
    /*
    * React 的开发和生产构建版本在 componentDidCatch() 的方式上有轻微差别。
    * 在开发模式下,错误会冒泡至 window,这意味着任何 window.onerror 或 window.addEventListener('error', callback) 会中断这些已经被 componentDidCatch() 捕获的错误。
    * 相反,在生产模式下,错误不会冒泡,这意味着任何根错误处理器只会接受那些没有显式地被 componentDidCatch() 捕获的错误。
    * 如果发生错误,你可以通过调用 setState 使用 componentDidCatch() 渲染降级 UI,但在未来的版本中将不推荐这样做。 可以使用静态 getDerivedStateFromError() 来处理降级渲染。
    * */
    static getDerivedStateFromError() {}
    componentDidCatch(error, errorInfo) {}
}

事件处理

采用驼峰命名法

此语法问题在于每次渲染 LoggingButton 时都会创建不同的回调函数。在大多数情况下,这没什么问题,但如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题。

在这两种情况下,React 的事件对象 e 会被作为第二个参数传递。如果通过箭头函数的方式,事件对象必须显式的进行传递,而通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。

class Element extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 0
        };
        this.handleClick = this.handleClick.bind(this)
    }
    // 方法一(推荐)
    handleClick() {
        this.setState(state => {
            return {
                count: state.count + 1
            }
        })
    }
    // 方法二
    handleClick1() {
        this.setState(state => ({
            count: state.count + 2
        }))
    }
    render() {
        return (
            <div>
                <div>计数器:{this.state.count}</div>
                <button onClick={this.handleClick}>+1</button>
                <button onClick={() => this.handleClick1()}>+2</button>
            </div>
        )
    }
}

组件渲染

  • t条件渲染if() {} else {}渲染, &&渲染,三目运算
render() {
    let button;
    if (this.state.flag) {
        button = (<button onClick={this.handleClick}>+1</button>)
	} else {
    	button = (<button onClick={() => this.handleClick1()}>+2</button>)
	}
    return (
        <div>
        	<div>计数器:{this.state.count}</div>
			{button}
		</div>
	)
}
class Element extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            count: true,
            relCount: "a"
        }
    }
    render() {
        return (
            <div>{this.state.count && this.state.relCount}</div>
        )
    }
}
  • 列表(JSX允许嵌入任何表达式)
class Element extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            numbers: [1, 2, 3, 4, 5]
        }
    }
    render() {
        return (
            <ul>
                {this.state.numbers.map((item) => (
                    <li key={item.toString()}>{item}</li>
                ))}
            </ul>
        )
    }
}
  • 表单
class Element extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            value: "Jack",
            textArea: "请撰写一篇关于你喜欢的 DOM 元素的文章",
            fruit: "",
        }
        this.handleChange = this.handleChange.bind(this)
        this.handleSubmit = this.handleSubmit.bind(this)
    }
    handleChange(event) {
        const target = event.target;
        const value = target.value;
        const name = target.name;
        this.setState({
            [name]: value,
        })
    }
    handleSubmit(event) {
        alert(this.state.value + this.state.textArea + this.state.fruit)
        event.preventDefault();
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>名字:
                    <input name="value" value={this.state.value} onChange={this.handleChange}/>
                </label>
                <label>textarea
                    <textarea name="textArea" value={this.state.textArea} onChange={this.handleChange}/>
                </label>
                <label>你喜欢的水果
                    <select name="fruit" value={this.state.fruit} onChange={this.handleChange}>
                        <option value="葡萄柚">葡萄柚</option>
                        <option value="酸橙">酸橙</option>
                        <option value="椰子">椰子</option>
                        <option value="芒果">芒果</option>
                    </select>
                </label>
                <input type='submit' value='提交'/>
            </form>
        )
    }
}

状态提升(类似Vue中的子组件给父组件传值)

class Child extends  React.Component {
    constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
    }
    handleChange(event) {
        this.props.inputChange(event.target.value)
    }
    render() {
        return (
            <div>
                <span>你好:</span>
                <input value={this.props.name} onChange={this.handleChange}/>
            </div>
        )
    }
}
class Element extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: "Jack"
        };
        this.handleChange = this.handleChange.bind(this);
    }
    handleChange(value) {
        this.setState({
            name: value
        })
    }
    render() {
        return (
            <div>
                <Child name={this.state.name} inputChange={this.handleChange}/>
            </div>
        )
    }
}

组合和继承

组合
class Element extends React.Component {
    render() {
        return (
            <div>{this.props.left}{this.props.right}</div>
        )
    }
}
const left = <span>名字:</span>
const right = <span>Jack</span>
const element = (<Element left={left} right={right}/>)
ReactDOM.render(element, document.getElementById("root"))
继承

## 组合和继承

#### 组合

```javascript
class Element extends React.Component {
    render() {
        return (
            <div>{this.props.left}{this.props.right}</div>
        )
    }
}
const left = <span>名字:</span>
const right = <span>Jack</span>
const element = (<Element left={left} right={right}/>)
ReactDOM.render(element, document.getElementById("root"))
继承

不常见

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值