# React.js快速进坑 > **React** 用于构建 Web 和原生交互界面的库 。 ## 1. Vue.js 对比 React 都是构建UI的框架,但关注点不同: - Vue.js 对 HTML 进行了扩展。各种指令 - React 对 JavaScript 进行了扩展,新增一个语法-JSX **因此,Vue在构建页面上更便捷,而React在构建页面时可以使用全部的JS能力。** ## 2. 安装 > 与Vue.js一样,有CDN链接;也可以通过npm独立安装;当然也有对应的脚手架工具。 为了更快下载必要js文件,将CDN链接上的js下载本地。 - babel: 转译jsx语法,即将jsx 转换成 js对象(虚拟DOM) - React核心库:提供核心功能。比如如何定义组件,Hook等等 - React DOM库:提供与DOM相关的功能。比如 将React组件 渲染到页面中,输出信息... ### 2.1 Hello, world ```html Hello
``` ## 3. JSX > 形似 `

Hello, World.

`这样的语法,看着 既不是 HTML 标签, 也不是 JS中数据类型。它就是 `jsx`. ### 3.1 渲染数据 在React中,可以使用`{}`将一个JS表达式的值 绑定到 JSX 中。 ```jsx let username = 'guoguo'; // 在React中可以使用 "{}" 去 在jsx中渲染数据 // 在"{js表达式}"中,编写的是 JS表达式。类似与 Vue的插值语法"{{}}" let element =

Hello, {username}.

; //

Hello, daxia.

``` ### 3.2 绑定属性 > 在开发UI时,jsx的操作会像HTML标签那样去指定各种属性。 **由于 JSX 最终会被 babel 转译成 JS对象。因此JSX的属性命名规则要遵从JS规范。** - 不能使用js中关键字后者保留字 - 属性名字 推荐使用 驼峰命名法 camelCase 实现时注意以下几点: 1. 那些是关键字或保留字的HTML属性需要改名:for => htmlFor; class => className 2. 那些包含多个单词的HTML属性需要转换成驼峰命名:rowspan =>rowSpan; colspan => colSpan; ... 3. 剩下那些就无需改变,直接可以使用。 ```jsx // let element = ( //

// Hello, React. //

// ); /** *! 1. jsx元素必须闭合 *! 2. 在jsx中注释内容的话 需要使用 绑定语法 */ let element = (
{/* jsx元素必须闭合*/}
); ReactDOM.createRoot(document.getElementById('root')).render(element); ``` ## 4. 事件处理 > 所有UI界面都需要通过事件来完成交互的。 > > 不同与Vue,有v-on指令来处理事件,react是通过jsx相对应的事件属性来实现的 React在处理事件时,和原生DOM对象类似。可以通过对应事件相关属性来注册监听器。 不同的是: 1. 原生DOM事件属性 都是 全小写的;而React是 基于原生事件属性转换后的驼峰命名。 2. 原生DOM事件绑定的值类型为 string;而React JSX 事件绑定的值类型为 function。 ```html ``` ```jsx // React中的实现 function handleClick() { alert('你敢点我???'); } const element = ; ReactDOM.createRoot(document.querySelector('#root')).render(element); ``` ### 4.1 事件对象 > 在实际开发中,当某一事发生后开发者需要根据当前事件获取相关的信息数据。此时就需要找到事件对象。不同的事件,会创建不同事件对象,并且不同的事件对象包含的数据也不尽相同。 那么怎么获取 事件对象 呢?默认情况下,JSX中注册所有监听器函数都会接收一个 事件对象 作为 唯一入参。因此在需要时在事件监听器函数中定义形参接收即可。 ```jsx // 事件监听的第一个参数 就是 事件对象 function handleClick(e) { console.log(e); alert('你敢点我???'); } function handleChage(e) { // 每次文本改后将其打印出来 console.log('changed:', e.target.value); } function handleSubmit(e) { e.preventDefault(); // 取消默认行为 alert('submited.'); } const element = (
{/**1 点击事件 **/} {/**2 change事件 **/} {/* input元素的change事件 和原生的input事件 是一样的 */} {/**3 submit事件 **/}

这旮瘩是表单

); ``` ### 4.2 监听器中的this > 在React16之前,事件的监听器中this可能会被频繁使用。因此我们需要记住this的绑定值。 > > 但是在React18之后,即推出Hook之后,开发者就可以绕过 JS 中难以理解的this指向。 原生事件属性绑定的监听器中的this ```html ``` 但是在React中 监听器的this 与HTML属性注册事件是一样的,即监听器中的this不会绑定任何事。 ```html
``` 如果这些监听器函数中的this需要有一个有效值: ```html
``` ### 4.3 给监听器传入额外参数 默认监听器中只会接收一个参数,即事件对象。 如果想要传入额外参数,像这样 ```jsx function deleteListItem(e, id) { console.log(e, id); } let element = ( ); ReactDOM.createRoot(document.querySelector('#root')).render(element); ``` - bind函数的实现 会导致传入参数位置固定,不够灵活 - 自己套壳实现 可以自行传入参数,因此位置灵活 - 实际应用 都可以。 ## 5. 组件 > React组件更像是一个函数,返回组件最终渲染后的效果(UI)。这里函数的名字就是组件名。为了和其他普通函数区分,组件的名称 遵循 大坨峰命名法(PascalCase)。 ```jsx // 定义组件 function Greeting(){ return

大家,下午好。

} // 组件的渲染 let element = ; // 将组件 => jsx(React元素) ReactDOM.createRoot(document.querySelector('#root')).render(element); ``` ### 5.1 props 所有函数定义的组件 也都会接收一个唯一参数,即props。和Vue中一样,都是单向数据流。推荐数据是从父组件向其后代流动。 本质上 props 是一个 object对象。存储父组件给绑定的所有属性集合。 ```jsx function Parent(props) { console.log('parent', props); return (

谁是爹》

); } function Child(props) { console.log('child', props); return (
这是儿子,它叫 {props.name}。今年 {props.age} 岁。
); } let element = ; // 将组件 => jsx(React元素) ReactDOM.createRoot(document.querySelector('#root')).render(element); ``` props 是 组件与外部数据交互的接口。同时还是响应式,即当props中数据发生变化后,组件会及时重新渲染。 ==注意:props 是 "只读的"!,当在使用props的时候,虽然语法上是可以修改其属性,但是React会检查该操作,一旦发现就会抛出一个类型异常: Uncaught TypeError: Cannot assign to read only property 'age' of object。== ### 5.2 state state 是 组件内部自己拥有的状态数据。不同于 props ,props 是 只读的,但是 state 是可以修改的。同时state变化后,组件会重新渲染。 如果想要组件内部拥有状态state,在不使用hooks时,必须通过es6中的类来定义组件,这样在类组件渲染时,会创建组件实例。通过组件实例的state属性 去存储 所有内部的状态(state类型为object对象)。 其中,类名就是组件名,也遵循PascalCase命名法。 ```jsx // 定义类Greeting 继承自 React.Component // 此时,即为Greeting 组件 class Greeting extends React.Component { // 定义render实例方法 render() { return (

你好,兄弟!

); } } ``` 上述代码要求: 1. 类必须继承`React.Component`才会是组件 2. 必须含有render实例方法,用来返回组件最终渲染效果UI 接下来,看一个计数器案例: ```jsx class Counter extends React.Component { // 添加状态 state = { name: '计数器', count: 0, // 定义一个计数的状态值 }; reduceOne() { // console.log(this); // 类Vue,如果直接修改state可以吗? // this.state.count--;// wrong // 正确做法 this.setState({ count: this.state.count - 1, }); } addOne = () => { // console.log(this); this.setState({ count: this.state.count + 1, }); }; render() { // 1 在类组件中 通过this先拿到组件实例,然后通过访问state属性得到所有的状态。 return (

{this.state.name}

当前值:{this.state.count}

); } } ``` 上面代码小结: 1. 获取状态state:通过 `this`先拿到组件实例;再访问state属性获取到所有的状态。 2. 修改状态state:必须通过组件实例的`setState方法`才可以。 3. `setState(newState | (prevState, props) => newState)`该方法在修改状态时,会将旧的state与setState传入新的state合并后产生的新状态对象 替换 旧状态对象的方式来实现响应式的。因此在调用setState时,要么直接传入一个新的状态对象,或者传入一个函数,该回调函数返回一个新state对象。 ### 5.3 组件生命周期 ## 6. 条件渲染 ## 7. 列表渲染 ### 7.1 JS各种循环 ### 7.2 数组map方法 ## 8. Hooks ### 8.1 useState ### 8.2 useEffect ### 8.3 useMemo ### 8.4 useCallback ## 9. refs & dom