如果你想学习React,可以按照以下学习路径:
-
HTML、CSS和JavaScript基础:React是基于JavaScript的,因此需要掌握HTML、CSS和JavaScript的基础知识。
-
ES6语法:React使用ES6语法来编写代码,因此需要掌握ES6语法的基础知识,如箭头函数、模板字符串、解构赋值等。
*ES6是ECMAScript 2015标准的简称,是JavaScript的一种更新版本,引入了许多新的语法和特性。以下是ES6语法的基础知识:
- *箭头函数:*箭头函数是一种简洁的函数定义方式,可以使用箭头符号(=>)来代替function关键字。例如:
// ES5 function add(a, b) { return a + b; } // ES6 const add = (a, b) => a + b;
- *模板字符串:*模板字符串是一种新的字符串定义方式,可以使用反引号(`)来定义字符串,并使用${}来嵌入JavaScript表达式。例如:
// ES5 var name = 'Alice'; var greeting = 'Hello, ' + name + '!'; // ES6 const name = 'Alice'; const greeting = `Hello, ${name}!`;
- *解构赋值:*解构赋值是一种新的赋值方式,可以将数组或对象中的值解构出来,并赋值给变量。例如:
// ES5 var person = { name: 'Alice', age: 18 }; var name = person.name; var age = person.age; // ES6 const person = { name: 'Alice', age: 18 }; const { name, age } = person;
除了箭头函数、模板字符串和解构赋值之外,ES6还引入了许多其他语法特性。以下是一些常见的ES6语法特性:
-
*let和const关键字:*let和const关键字用于声明变量和常量。let声明的变量具有块级作用域,const声明的常量不可更改。例如:
let count = 0; count = 1; const PI = 3.14159;
- 默认参数值:可以为函数的参数设置默认值,当参数未传递时使用默认值。例如:
function greet(name = 'World') { console.log(`Hello, ${name}!`); } greet(); // 输出:Hello, World! greet('Alice'); // 输出:Hello, Alice!
- *展开运算符:*展开运算符可以将数组或对象展开为单独的元素,或将多个元素合并为一个数组或对象。例如:
const numbers = [1, 2, 3]; const colors = ['red', 'green', 'blue']; const combined = [...numbers, ...colors]; console.log(combined); // 输出:[1, 2, 3, 'red', 'green', 'blue'] const person = { name: 'Alice', age: 18 }; const { name, ...rest } = person; console.log(name); // 输出:'Alice' console.log(rest); // 输出:{ age: 18 }
以上是ES6语法的一些常见特性。在实际开发中,还需要了解其他ES6语法特性,如模块化、Promise、async/await等
*ES6模块化的特点包括:
- 模块化作用域:每个模块都有自己的作用域,模块内部定义的变量和函数不会污染全局作用域。
- 静态加载:模块加载时是静态的,即在编译时就能确定模块的依赖关系,而不是在运行时动态加载。
- 导入导出:模块导出使用export关键字,导入使用import关键字。
- 单例模式:每个模块只会被加载一次,且多次导入同一个模块只会执行一次。
下面是一个简单的ES6模块化示例:
// math.js export const pi = 3.1415926; export function square(x) { return x * x; } // app.js import { pi, square } from './math.js'; console.log(pi); // 3.1415926 console.log(square(2)); // 4
在上面的示例中,math.js模块通过export关键字导出了pi和square两个变量和函数,app.js模块通过import关键字导入了math.js模块中的pi和square。导入后可以直接使用这些变量和函数。
-
React基础知识:需要学习React的基础知识,如组件化、虚拟DOM、单向数据流、生命周期等。
React是一个用于构建UI界面的JavaScript库,它采用了组件化、虚拟DOM、单向数据流和生命周期等概念来提高开发效率和代码可维护性。
组件化是React的核心概念之一,它将UI界面拆分成一个个独立的组件,每个组件都有自己的状态和属性,可以通过props来传递数据。组件化的优势在于可以让开发者将复杂的UI界面拆分成小的、可重用的组件,从而降低代码的复杂度和维护成本。
虚拟DOM是React的另一个重要概念,它是一种轻量级的、存在于内存中的DOM结构,可以通过React的diff算法来快速计算出UI界面的变化,并进行高效的更新。相比于直接操作真实的DOM,虚拟DOM具有更高的性能和更好的可维护性。
单向数据流是React推崇的数据管理模式,它将数据流向UI界面的方向限定为单向,即只能从父组件向子组件传递数据。这种模式可以让开发者更加容易理解数据的流向,从而提高代码的可维护性和可读性。
生命周期是React组件在不同阶段会触发的一系列回调函数,包括组件的初始化、更新和卸载等过程。通过生命周期函数,开发者可以在不同的阶段进行一些操作,比如初始化组件的状态、更新组件的UI界面等。生命周期函数的使用可以让开发者更加容易控制组件的行为,从而提高代码的可维护性和可扩展性。
React的生命周期函数分为三类:
- Mounting:组件被创建并插入到DOM中时触发的生命周期函数,包括constructor、componentDidMount等函数。
- Updating:组件的props或state发生变化时触发的生命周期函数,包括shouldComponentUpdate、componentDidUpdate等函数。
- Unmounting:组件从DOM中移除时触发的生命周期函数,包括componentWillUnmount等函数。
-
JSX语法:需要掌握JSX语法,如JSX元素、JSX表达式、JSX属性等。
JSX元素是JSX语法中的一个基本概念,它类似于HTML元素,用于描述UI界面中的一个组件或元素。JSX元素的语法类似于HTML元素,但是需要用大括号包裹JavaScript表达式。例如:
const element = <h1>Hello, {name}!</h1>;
在这个例子中,
<h1>
就是一个JSX元素,name
是一个JavaScript表达式,用于动态生成UI界面。JSX表达式是JSX语法中的另一个基本概念,它用于在JSX中嵌入JavaScript表达式。JSX表达式需要用大括号包裹,例如:
const element = <h1>{1 + 2 + 3}</h1>;
在这个例子中,
{1 + 2 + 3}
就是一个JSX表达式,用于动态生成UI界面。JSX属性是JSX语法中的一个重要概念,它用于给JSX元素添加属性。JSX属性的语法类似于HTML属性,但是需要用大括号包裹JavaScript表达式。例如:
const element = <img src={imageUrl} alt={imageAlt} />;
在这个例子中,
src
和alt
就是JSX属性,imageUrl
和imageAlt
是JavaScript表达式,用于动态生成属性值。- react定义的一种类似于XML的JS扩展语法: JS + XML本质是 React.createElement(component, props, ...children) 方法的语法糖,用来简化创建虚拟DOM ;它不是字符串, 也不是HTML/XML标签,它最终产生的就是一个JS对象;
1>定义虚拟DOM时,不要写引号。
2>标签中混入js表达式时要用{},遇到以 { 开头的代码,以JS语法解析
3>样式的类名指定不要用class,要用className.
4>内联样式,要用 style={key : value} 的形式去写
5>虚拟DOM元素只能有一个根元素
6> 虚拟DOM元素必须有结束标签
7.标签首字母:遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
(1).若小母开头,则将该标签转为html中同名元素,若htm1中无该标签对应的同名元素,则报错。
(2).若大好字母开头,react就去润染对应的组件,若组件没有定义,则报错。
8>jsx 语法只识别 js 语句,不识别 js 表达式,所以 jsx 语法必须产生一个值,可以用变量接收则为 js 语句:
- 一定注意区分:【jsi语句(代码)】【js也达式】
- 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地力,下面这些都是麦达式: 1). a 2). a+b 3). demo(1) 4). arr.map() 5). function test () {}
- 语句(代码):下面这些都是语句(代码): (1).if(){} (2).for(){} (3).switch(){case : xxxx}
9>jsx 语法最终会被 babel 转换成 React.createElement() 方法,创建出虚拟DOM , 关于虚拟DOM:
1).本质是Object类型的对象(一般对象)
2).虚拟DOM比较“轻”,真实DOM比较“重”,因为虚拟DOM是React内部在用,无需真实DOM上那么多的属性。
3).虚拟DOM最终会被 ReactDOM.render( virtualDOM, containerDOM ) 转化为真实DOM,呈现在页面上。
-
React组件的状态和属性:需要学习如何使用状态和属性来管理组件的数据。
组件三大核心属性
state:
- state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
- 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
- state 的值必须是对象,状态必须通过setState进行更新,且更新是一种合并,不是替换。
//1.创建组件 class Weather extends React.Component { //初始化状态 state = {isHot:false,wind:'微风'} render(){ const {isHot,wind} = this.state return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1> } //自定义方法————要用赋值语句的形式+箭头函数 changeWeather = ()=>{ const isHot = this.state.isHot this.setState({isHot:!isHot}) } } //2.渲染组件到页面 ReactDOM.render(<Weather />, document.getElementById('root')) 复制代码
props
- 每个组件对象都会有props(properties的简写)属性
- 组件标签的所有属性都保存在props中
- 通过标签属性从组件外向组件内传递变化的数据
- 注意: 组件内部不要修改props数据
//创建组件 class Person extends React.Component{ constructor(props){ //构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props // console.log(props); super(props) console.log('constructor',this.props); } //对标签属性进行类型、必要性的限制 static propTypes = { name:PropTypes.string.isRequired, //限制name必传,且为字符串 sex:PropTypes.string,//限制sex为字符串 age:PropTypes.number,//限制age为数值 } //指定默认标签属性值 static defaultProps = { sex:'男',//sex默认值为男 age:18 //age默认值为18 } render(){ // console.log(this); const {name,age,sex} = this.props //props是只读的 //this.props.name = 'jack' //此行代码会报错,因为props是只读的 return ( <ul> <li>姓名:{name}</li> <li>性别:{sex}</li> <li>年龄:{age+1}</li> </ul> ) } } //渲染组件到页面 ReactDOM.render(<Person name="jerry"/>,document.getElementById('test1')) 复制代码
- 函数组件使用 props
//创建组件 function Person (props){ const {name,age,sex} = props return ( <ul> <li>姓名:{name}</li> <li>性别:{sex}</li> <li>年龄:{age}</li> </ul> ) } Person.propTypes = { name:PropTypes.string.isRequired, //限制name必传,且为字符串 sex:PropTypes.string,//限制sex为字符串 age:PropTypes.number,//限制age为数值 } //指定默认标签属性值 Person.defaultProps = { sex:'男',//sex默认值为男 age:18 //age默认值为18 } //渲染组件到页面 ReactDOM.render(<Person name="jerry"/>,document.getElementById('test1')) 复制代码
refs
- 组件内的标签可以定义ref属性来标识自己
- 字符串形式ref:不推荐使用,未来版本即将废弃,如果你目前还在使用
this.refs.textInput
这种方式访问 refs ,我们建议用回调函数或createRef
API 的方式代替。
// DOM 中定义 <input ref="input1" type="text" placeholder="点击按钮提示数据"/> // 使用 const {input1} = this.refs alert(input1.value) 复制代码
- 回调形式:
// ref 定义的回调函数,会被 react 调用,且传入 DOM 本身 <input ref={c => this.input1 = c } type="text" placeholder="点击按钮提示数据"/> // 使用 showData = ()=>{ const {input1} = this alert(input1.value) } //如果 ref 回调函数是以内联函数的方式定义的(上述方式),因为不确定内联函数是否是最新的,在更新过程中它会被执行两次,第一次传入参数 null(用于清空函数),然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题(如下),但是大多数情况下它是无关紧要的。 saveInput = (c)=>{ this.input1 = c; console.log('@',c); } <input ref={this.saveInput} type="text"/><br/><br/> 复制代码
- React.createRef()
// 当运行到 ref 时, react 会将当前DOM存储在 myRef 这个容器中,通过 current 属性会被获取。 // React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”的,如果在不同 DOM 定义相同的 ref,则后面的 DOM 将顶替之前的 ref <input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/> <button onClick={this.showData}>点我提示左侧的数据</button> myRef = React.createRef() showData = ()=>{ alert(this.myRef.current.value); }
-
React路由和Redux:需要掌握React路由和Redux的使用,以构建复杂的单页应用程序。
React路由是指将不同的页面或视图组件映射到不同的URL路径上的过程。React中可以使用第三方库React Router来实现路由功能,React Router提供了一系列API和组件,可以帮助开发者实现路由功能,包括Route、Link、Switch等组件。
Redux是一种用于管理应用程序状态的JavaScript库,它可以帮助开发者更好地组织和管理应用程序的状态,从而提高代码的可维护性和可扩展性。Redux的核心概念包括Store、Action和Reducer等,开发者可以通过这些概念来实现状态的管理和更新。
在实际开发中,React路由和Redux经常会一起使用,以构建复杂的单页应用程序。开发者可以使用React Router来实现路由功能,同时使用Redux来管理应用程序的状态,从而实现更加复杂的应用程序逻辑。例如,当用户导航到不同的页面时,可以通过Redux来更新应用程序的状态,从而实现更加复杂的页面交互。
总之,React路由和Redux都是React中非常重要的概念,开发者需要深入理解这些概念,才能更好地构建复杂的单页应用程序。同时,需要注意合理使用这些概念,避免过度使用,从而导致代码的复杂性和维护难度增加。
-
React性能优化:需要了解React性能优化的技巧,如虚拟列表、懒加载、代码分割等。
虚拟列表:虚拟列表是一种优化技巧,它可以帮助开发者优化长列表的性能。虚拟列表的原理是只渲染可见区域内的列表项,而不是渲染整个列表。这样可以减少渲染的元素数量,从而提高性能。
懒加载:懒加载是一种优化技巧,它可以帮助开发者优化页面加载的性能。懒加载的原理是延迟加载某些组件或资源,只有当需要使用时才进行加载。这样可以减少页面的加载时间,从而提高性能和用户体验。
代码分割:代码分割是一种优化技巧,它可以帮助开发者优化应用程序的加载速度。代码分割的原理是将应用程序的代码分割成多个小文件,只在需要时才进行加载。这样可以减少应用程序的加载时间,从而提高性能和用户体验。
使用PureComponent或React.memo:PureComponent和React.memo都是React中用于优化组件性能的工具。它们可以帮助开发者避免不必要的渲染,从而提高组件的性能。
避免过度渲染:在React中,组件的渲染是一个比较昂贵的操作,因此需要尽量避免过度渲染。开发者可以通过shouldComponentUpdate或React.memo来优化组件的渲染,从而提高性能。
-
React服务器渲染:需要学习如何使用React服务器渲染,以提高应用程序的性能和SEO优化。
React服务器渲染的原理是在服务器端将React组件渲染成HTML字符串,然后将HTML字符串返回给客户端。客户端可以直接使用这些HTML字符串,不需要再进行客户端渲染,从而提高应用程序的性能和SEO优化。
React服务器渲染的优点包括:
- 提高性能:React服务器渲染可以减少客户端渲染的时间,从而提高应用程序的性能和用户体验。
- 改善SEO:React服务器渲染可以让搜索引擎更容易地爬取网页内容,从而提高SEO效果。
- 改善首次加载时间:React服务器渲染可以让用户更快地看到应用程序的内容,从而提高用户体验。
React服务器渲染的实现需要使用第三方库,比如Next.js、Gatsby等。这些库提供了一系列API和工具,可以帮助开发者实现服务器渲染功能,并提供了一些优化技巧,比如缓存、预取等,可以进一步提高应用程序的性能和用户体验。
以上是React的学习路径。在学习过程中,可以结合实际项目进行练习和实践,以加深理解和掌握React的使用。