React学习笔记(一)

认识React

React是一个用于构建用户界面JavaScript库,可以用来构建 Web 应用(使用ReactDOM)(不止如此,还有React Native)。

react-dom:渲染 Web、react-native:构建手机应用

React 是基于组件的,在React中用组件来表示页面中的部分内容,通过组合、复用多个组件,就可以实现完整的页面功能

React主要有2个包,react包是核心,提供创建元素、组件等功能,react-dom 包提供 DOM 渲染等相关功能。

基本使用

React 安装

npm i react react-dom
// 引入 react、react-dom 的 js 文件
<script src="./node_modules/react/umd/react.development.js"></script>
<script src="./node_modules/react-dom/umd/react-dom.development.js"></script>

<script>
    // 创建 React 元素
    const title = React.createElement('h1', null, 'Hello React');
    // 渲染 React 元素到 root 节点下
    ReactDom.render(title, document.getElementById('root'));
</script>

使用 React 脚手架
初始化项目:

npx create-react-app my-app

index.js:

import React from 'react'
import ReactDOM from 'react-dom'

const title = React.createElement('h1', null, 'Hello, React!!!');
ReactDOM.render(title, document.getElementById('root'));

启动项目

npm start

JSX

JSX 是 JavaScript XML 的简写,表示在 JavaScript 代码中写 XML(HTML)格式的代码。

声明式语法更直观,与HTML结构相同

const title =(<h1>Hello, JSX!</h1>);  // JSX 语法,创建 react 元素
ReactDOM.render(title, document.getElementById('root'));

JSX不是标准的 ECMAScript 语法,它是 ECMAScript 的语法扩展,需要使用 babel 编译处理后才能在浏览器环境中使用(编译JSX语法的包:@babel/preset-react

React 元素的属性名使用的是驼峰命名法,一些特殊属性名和 HTML 属性名有些区别:
class => className、for => htmlFor、tabindex => tabIndex

另外没有子节点的 React 元素可以用 />结束(JSX中的约定)。

嵌入 JS 表达式

语法:{js 表达式}

const name = 'Qanx';
const div = (<div>Hello, {name}</div>);
ReactDOM.render(div, document.getElementById('root'));
JSX条件渲染

根据条件渲染特定的JSX结构。

const loadData1 = () => {
    return (isLoding ? <div>loading……</div> : <div>数据加载完成1</div>);
};
const loadData2 = () => {
    return (isLoding && <div>loading1……</div>);  // 逻辑与运算符, 逻辑中断
};
JSX列表渲染

渲染一组数据,使用数组的map()方法,map 会返回处理后的数据。

渲染列表时应该添加 key 属性,key属性的值要保证唯一

const songs = [{ id: 1, name: '痴心绝对' }, { id: 2, name: '像我这样的人' }, { id: 3, name: '南山南' }];
const test = [<li key='1'>痴心绝对</li>, <li key='2'>像我这样的人</li>, <li key='4'>南山南</li>];

const div = (
    <div>
        <ul>
            {songs.map(item => <li key={item.id}>{item.name}</li>)}
        </ul>
        <ul>{test}</ul>
    </div>
);
ReactDOM.render(div, document.getElementById('root'));
JSX样式处理

行内样式:

const div = (
    <div style={{ color: 'red',backgroundColor: 'skyblue' }}>Hello</div>  // 样式属性同样遵循驼峰命名
); 

外部样式(className):

.testDiv {
    background-color: skyblue
}
import './css/index.css'

const div = (<div className='testDiv'>Hello</div>);

React完全利用JS语言自身的能力来编写UI,而不是造轮子增强HTML功能

React组件

组件是 React 的核心内容,使用 React 就是在使用组件。 React组件是独立的,组件表示页面中的部分功能,通过复用、组合可以实现完整页面功能

函数组件

函数组件是指使用 JS 的函数(或箭头函数)创建的组件。约定:

  1. 函数的名称必须以大写字母开头
  2. 函数组件必须有返回值,表示该组件的结构
  3. 返回值为 null,则表示不渲染任何内容
import React from 'react';
import ReactDOM from 'react-dom/client';

const Hello = () => (<div>Hello, 函数组件!</div>);
const root = ReactDOM.createRoot(document.getElementById('root'));  // createRoot 为 react 18新语法, 在包 react-dom/client 中
root.render(<Hello />);
类组件

类组件是指使用 ES6 的 class 创建的组件。约定:

  1. 类名称必须以大写字母开头
  2. 类组件应该继承 React.Component父类,从而可以使用父类中提供的方法或属性
  3. 类组件必须提供 render()方法,且方法必须有返回值,表示该组件的结构
import React from 'react';
import ReactDOM from 'react-dom/client';

class Hello extends React.Component {
    render () {
        return (<div>Hello, 类组件!</div>);
    }
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Hello />);

组件作为一个独立的个体,一般都会放到一个单独的JS文件中

组件抽离为独立的 js 文件
import React from 'react'

//const Hello = () => (<div>Hello, 函数组件!</div>);
class Hello extends React.Component {
    render () {
        return (<div>Hello, 类组件!</div>);
    }
}
export default Hello  // 导出 Hello 组件
import React from 'react'
import ReactDOM from 'react-dom/client'

import Hello from './Hello';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Hello />);

React 事件处理

React 事件绑定语法与 DOM 事件语法贴近:

  1. 语法:on+事件名称={事件处理},如:onClick={()=>console.log(‘click’)}
  2. React 事件采用驼峰命名法
import React from "react";

// 1. 类组件
// class App extends React.Component {
//   handleClick () {
//     console.log("单击事件触发了")
//   }
//   render () {
//     return (<button onClick={this.handleClick}>按钮</button>);
//   }
// }
// 2. 函数组件
const App = () => {
  function handleClick () {
    console.log("单击事件触发了");
  }
  return (<button onClick={handleClick}>按钮</button>);
};
export default App;
事件对象

通过事件处理程序的参数获取到事件对象。React 中的事件对象叫做:合成事件(对象)

合成事件:兼容所有浏览器,不用担心跨浏览器兼容性问题

const App = () => {
  function handleClick (e) {
    e.preventDefault();  // 阻止浏览器的默认行为
    console.log('事件对象', e);
  }
  return (<a href="http://www.baidu.com" onClick={handleClick}>百度</a>);
};

有状态组件和无状态组件

函数组件又叫无状态组件,类组件又叫做有状态组件。

  1. 状态(state)即数据
  2. 函数组件没有自己的状态,只负责数据展示
  3. 类组件有自己的状态,负责更新UI,让页面“动”起来
state

状态(State)即数据,是组件内部的私有数据,只能在组件内部使用。

state的值是一个对象,表示一个组件中可以有多个数据

class Timer extends React.Component {
    constructor() {
        super();
        this.state = { count: 0 };  // 初始化 state
    }
    // state = { count: 0 };  // 简化语法

    render () {
        return (
            <div>
                <h1>Timer: {this.state.count}</h1>
            </div>
        );
    }
}
setState()修改状态

状态是可以改变的,语法:this.setState({要修改的数据})

  1. 不要直接修改 state 中的值,而是通过 setState 方法修改
  2. setState 的作用有两个:①修改state、②更新UI(更新UI会重新渲染UI,所以直接修改state页面是不会发生改变的)
class Timer extends React.Component {
    state = { count: 0 };

    render () {
        return (
            <div>
                <h1>Timer: {this.state.count}</h1>
                <button onClick={() => this.setState({ count: this.state.count + 1 })}>+1</button>
            </div>
        );
    }
}

数据驱动视图的思想


抽离事件处理函数:

class Timer extends React.Component {
    state = { count: 0 };

    onIncrement () {
        this.setState({ count: this.state.count + 1 });  // 这里调用时,this 为 undefined
    }

    render () {
        return (
            <div>
                <h1>Timer: {this.state.count}</h1>
                <button onClick={this.onIncrement}>+1</button>
            </div>
        );
    }
}

上面代码中 this 为 undefined

事件绑定中 this 指向

箭头函数

利用箭头函数自身不绑定 this 的特性,让 this 指向外部环境的 this:

class Timer extends React.Component {
    state = { count: 0 };

    onIncrement () {
        this.setState({ count: this.state.count + 1 });  // 这里 this 指向调用的 this
    }

    render () {
        // 箭头函数中的 this 执行外部环境,这里是 render() 方法
        return (
            <div>
                <h1>Timer: {this.state.count}</h1>
                <button onClick={() => this.onIncrement()}>+1</button>
            </div>
        );
    }
}
Function.prototype.bind()

使用 ES5 中的 bind() 方法,将事件处理程序中的 this 与组件实例绑定到一起。

class Timer extends React.Component {
    constructor() {
        super();
        this.state = { count: 0 };
        // 1. bind() 函数会创建一个新的绑定函数, 它包装了原函数对象, 这个新函数的 this 被指定为 bind() 的第一个参数
        // 2. bind() 函数返回一个原函数的拷贝(新的绑定函数), 然后重新赋值给原来的函数
        // 3. 调用绑定函数通常会导致执行包装函数
        this.onIncrement = this.onIncrement.bind(this);

    }

    onIncrement () {
        this.setState({ count: this.state.count + 1 });
    }

    render () {
        return (
            <div>
                <h1>Timer: {this.state.count}</h1>
                <button onClick={this.onIncrement}>+1</button>
            </div>
        );
    }
}
class 的实例方法

利用箭头函数形式的 class 实例方法:

class Timer extends React.Component {
    state = { count: 0 };

    onIncrement = () => this.setState({ count: this.state.count + 1 });  // this 指向的是当前 Timer 实例

    render () {
        return (
            <div>
                <h1>Timer: {this.state.count}</h1>
                <button onClick={this.onIncrement}>+1</button>
            </div>
        );
    }
}

表单处理

受控组件

React 将 state 与表单元素的值 value 绑定到一起,由 state 的值来控制表单元素的值,这种受 React 控制的表单元素又叫做受控组件。使用步骤:

  1. 在 state 中添加一个状态,作为表单元素的 value 值(控制表单元素值的来源为 state)
  2. 给表单元素绑定 change 事件,将表单元素的值设置为 state 值(控制表单元素值的变化)
class Form extends React.Component {
    state = { name: '', gender: '1', isChecked: true, desc: '' };

    handleForm = (e) => {
        const target = e.target;  // 获取当前 DOM 对象
        const value = target.type === 'checkbox' ? target.checked : target.value;  // 根据类型获取值
        this.setState({ [target.name]: value });  // 设置对象的值(属性名表达式语法)
    };
    render = () => (
        <div>
            <input type="text" name="name" value={this.state.name} onChange={this.handleForm} /><br />
            <select name="gender" value={this.state.gender} onChange={this.handleForm}>
                <option value='1'></option>
                <option value='0'></option>
            </select><br />
            <div>
                <input type='checkbox' name="isChecked" checked={this.state.isChecked} onChange={this.handleForm} />看电影
            </div>
            <textarea name="desc" value={this.state.desc} onChange={this.handleForm}></textarea>
            <div>
                name: {this.state.name}<br />
                gender: {this.state.gender}<br />
                isChecked: {this.state.isChecked.toString()}<br />
                desc: {this.state.desc}
            </div>
        </div>
    );
}

属性名表达式语法:属性名表达式

非受控组件

原生 DOM,不受 React state 管理的表单元素,使用步骤:

  1. 调用 React.createRef() 方法创建一个 ref 对象
  2. 将创建好的 ref 对象添加到表单元素
  3. 通过 ref 对象获取到对应表单元素的值
class Form extends React.Component {
    constructor() {
        super();
        this.txtRef = React.createRef();
    }

    inputChange = () => {
        console.log(this.txtRef.current.value);
    };

    render = () => {
        return (
            <div>
                <input type="text" ref={this.txtRef} onChange={this.inputChange} />
            </div>
        );
    };
}

本文系B站黑马前端React教程学习笔记。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qanx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值