react学习笔记,记录我在开发和学习过程中遇到的问题和知识点

2013年5月Facebook推出了React.js开源软件前端框架,函数式编程,是使用人数最多的前端框架,也拥有最健全的文档和完善的社区

React官网

16版本之后的react叫做 react fiber

一、开发环境准备

  1. 引入.js文件来使用React
  2. 通过脚手架工具来编码,但是最终代码不能运行,需要通过webpack等来编译

(官方提供的脚手架工具 Create-react-app )

1.如何使用脚手架工具?

  1. 下载node.js , 进入官方网站

node -v  //node版本号
npm -v   //npm 版本号

2.使用脚手架工具创建一个项目

打开命令行工具,依次执行命令

npx create-react-app my-app     //创建项目
cd my-app       //进入项目
npm start       //运行项目

正常情况下就会在浏览器中弹出以下页面,说明项目运行成功

3.运行项目

安装依赖包,在命令行中输入:

yarn install

然后重新启动npm start或者yarn start

4.工程目录

build           //打包之后自动生成的目录
public--        //生成的页面内容
        |  favicon.ico
        |  index.html
        |  manifest.json    //不需要,可以删除
src-----        //放置的是项目的源代码  
        |  index.js         //入口的js文件,放置整个项目需要引入的第三方模块或者文件
        |  index.css        //项目页面的全局css样式
        |  App.js           //负责往页面渲染一些内容
        |  App.css          //项目页面的css样式
        |  serviceWorker    //PWA的一些内容
        |
        |
node_modules    //项目中需要的第三方模块
.gitgnore       //这里面的内容不会上传到github 上
package.json    //对项目的配置进行说明性的东西,版本和和第三方模块等,以及start,npm run build进行项目打包
README.md       //对文件的说明描述
yarn lock       //放置整个项目依赖的第三方模块的版本信息,不需要做任何修改,放在这里就可以

可以在index.js文件中引入css文件

**index.js**

//引入了两个第三方模块
import React from 'react';
import ReactDOM from 'react-dom';

import './index.css'    //可以再index.js中引入css样式文件

import App from './App.js'  //在index.js中引入App.js,才能在浏览器渲染出App.js中写出的内容

//App里面的内容,通过这行代码挂载到页面id为root的标签下
ReactDOM.render(<App />,document.getElementById('root));

App.js中也可以引入css和svg

**App.js**

import logo from './logo.svg';
import './App.css';

//通过语法渲染内容
function App() {
  return (
    <div>
      hello world
    </div>
  );
}

二、React 组件

(使用create-react-app脚手架工具创建项目时,会判断当前环境是否有yarn这个工具,如果有的话就会用yarn进行依赖包的安装,生成yarn.lock文件;如果没有的话就会用npm进行安装,生成package-lock.json文件)

组件就是页面上的一部分,一个网页可以分成很多个组件,每个组件又可以拆分成一个小组件

我们可以把App.js叫做一个组件,在index.js中引入了react的组件,就是把react这个组件渲染到页面上的root元素之中

1.React 模块的作用

必须引入React这个模块,引入这个模块的作用就是解析JSX语法,如果没有引入,浏览器就会报错,因为识别不出来这个语法

import React from 'react'

//JSX语法
ReactDOM.render(<App />, document.getElementById('root')
);

假如没有引入React这个模块,就会出现下面这种情况

2.Conponent 模块

这几行被注释掉的代码的缩写相当于第一行代码,实际操作中直接写缩写后的import React, {Conponent } from 'react';

**App.js**

import React, {Conponent } from 'react';

// import { Component } from 'react';
// import React from 'react';
// const { Component } = React;
// const Component = React.Component

class App extends Component {
	//render函数决定了往页面上渲染的是什么内容
	render() {
		return (
		    <div>
		      hello world
		    </div>
  		);
	}

}


export default App;

3.引入多个组件

现在我们要引入App.js和Test.js两个组件到index.js当中去

**index.js**

import App from './App';
import Test from './Test';

//JSX语法
ReactDOM.render(<div><App /><Test /></div>, document.getElementById('root')
//因为ReactDOM.render语法只能解析一个标签,所以把<App />和<Test />放在一个div当中,让react去解析这一个div就可以

4、组件

JSX语法里面,有两种类型的标签

1.普通的html标签

可以看到这种类型的标签div都是小写的

render() {
  return (
    <div>
      hello world
    </div>
  );
}

2.组件标签

可以看到App标签首字母是大写的,所以我们在创建组件的时候直接以大写字母开头

ReactDOM.render(<App />,document.getElementById('root'));

通过判断字母大小写我们可以分辨出普通html标签和组件标签

三、使用React编写ToDoList功能

我们来看一下基本的TodoList组件内容

**TodoList.js**

import React, { Component } from 'react';

class TodoList extends Component {

  render() {
    return (
      <div>
        <input />
        <ul>
          <li>learn React</li>
          <li>learn Component</li>
        </ul>
      </div>
    );
 }

}

// 导出组件
export default TodoList;
**index.js**

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

import TodoList from './TodoList';

ReactDOM.render(<TodoList />,document.getElementById('root');

然后打开浏览器看一下html结构

能够看到input和ul外层还包裹着一层div,在这层div外部才是root,在有些情况,我们不需要这层多余的div,想让input和ul直接放到root下面,但是如果直接去掉TodoList里面的div,会出现报错显示无法解析,因为render下面只能有一个标签

react16提供了一个占位符 Fragment,他就是一个占位的组件,并不会生成标签,所以帮助我们解决报错问题而不会生成任何标签,非常适合这种使用情况

**TodoList**

import React, { Component, Fragment } from 'react';

class TodoList extends Component {

	render() {
		return (
		    <Fragment>
		    	<input />
		    	<ul>
		    		<li>learn React</li>
		    		<li>learn Component</li>
		    	</ul>
		    </Fragment>
  		);
	}

}

// 导出组件
export default TodoList;

打开浏览器看一下html结构

页面没有变化,和原来一样,但是dom结构已经精简了,达到了我们预期的要求

四、JSX语法

1.JSX基本语法

在JSX中嵌入一个表达式,首先声明一个name变量

const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

ReactDOM.render(
  element,
  document.getElementById('root')
);

… 甚至可以嵌入一个函数表达式

function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = (
  <h1>
    Hello, {formatName(user)}!
  </h1>
);

ReactDOM.render(
  element,
  document.getElementById('root')
);

formatName(user)调用变量user的属性,并且将formatName(user)放置在element中去,最后在ReactDOM.render中引入

并且在JSX中可以包含很多子标签,唯一要注意的是,不管有多少子标签,但是只能存在一个父标签

const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);

JSX表示对象

可以使用React.createElement()进行函数调用

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

完全等价于:

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

2.元素渲染

将一个react元素渲染到dom节点中去,需要传入ReactDOM.render()

const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));

3.更新已渲染的元素

react元素是一个不可变对象,无法更改它的子元素,想要更改的话,需要创建一个全新的元素传入ReactDOM.render()

据一个计时器的例子

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(element, document.getElementById('root'));
}

setInterval(tick, 1000);

注意:直接new Date()是一个变量,无法显示在页面的节点中,只有通过toLocaleTimeString()当法将其转化为字符串才可以显示

这个例子,setInterval每秒会调用一次,因此在页面上,会显示每秒的时间

五、生命周期

先上一张生命周期图示

Clock组件第一次被渲染到DOM中的时候,就为其设置一个计时器。这在 React 中被称为挂载(mount)

同时,当DOM中Clock组件被删除的时候,应该清除计时器。这在 React 中被称为卸载(unmount)

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
  }

  componentWillUnmount() {
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}