一.编写第一个react应用程序
1.全局安装create-react-app
$ npm install -g create-react-app
如果不想全局安装,可以直接使用npx
$ npx create-react-app your-app 也可以实现相同的效果
2.创建一个项目
$ create-react-app your-app 注意命名方式
Creating a new React app in /dir/your-app.
Installing packages. This might take a couple of minutes. 安装过程较慢,可以推荐使用yarn
Installing react, react-dom, and react-scripts...
这需要等待一段时间,这个过程实际上会安装三个东西
出现下面的界面,表示创建项目成功:
Success! Created your-app at /dir/your-app
Inside that directory, you can run several commands:
npm start
Starts the development server.
npm run build
Bundles the app into static files for production.
npm test
Starts the test runner.
npm run eject
Removes this tool and copies build dependencies, configuration files
and scripts into the app directory. If you do this, you can’t go back!
We suggest that you begin by typing:
cd your-app
npm start
Happy hacking!
根据上面的提示,通过cd your-app
命令进入目录并运行npm start
即可运行项目。
生成项目的目录结构如下:
├── README.md 使用方法的文档
├── node_modules 所有的依赖安装的目录
├── yarn-lock.json 锁定安装时的包的版本号,保证团队的依赖能保证一致。
├── package.json
├── public 静态公共目录
└── src 开发用的源代码目录
常见问题:
npm安装失败
切换为npm镜像为淘宝镜像
使用yarn,如果本来使用yarn还要失败,还得把yarn的源切换到国内
yarn config set registry https://registry.npm.taobao.org // 配置yarn镜像源
yarn config list // 查看yarn 镜像列表
如果还没有办法解决,请删除node_modules及yarn-lock.json然后重新执行cnpm install命令
再不能解决就删除node_modules及yarn-lock.json的同时清除npm缓存npm cache clean --force
之后再执行npm install
命令
环境变量问题
react-scripts 版本过高问题 ( 降低版本 [email protected])
二.元素与组件
react开发需要引入多个依赖文件:react.js、react-dom.js,分别又有开发版本和生产版本,create-react-app里已经帮我们把这些东西都安装好了。把通过CRA创建的工程目录下的src目录清空,然后在里面重新创建一个index.js. 写入以下代码:
// 从 react 的包当中引入了 React。只要你要写 React.js 组件就必须引入React, 因为react里有一种语法叫JSX,稍后会讲到JSX,要写JSX,就必须引入React
import React from 'react'
// ReactDOM 可以帮助我们把 React 组件渲染到页面上去,没有其它的作用了。它是从 react-dom 中引入的,而不是从 react 引入。
import ReactDOM from 'react-dom'
// ReactDOM里有一个render方法,功能就是把组件渲染并且构造 DOM 树,然后插入到页面上某个特定的元素上
ReactDOM.render(
// 这里就比较奇怪了,它并不是一个字符串,看起来像是纯 HTML 代码写在 JavaScript 代码里面。语法错误吗?这并不是合法的 JavaScript 代码, “在 JavaScript 写的标签的”语法叫 JSX- JavaScript XML。
欢迎进入React的世界
,
// 渲染到哪里
document.getElementById('root')
)
三.函数式组件( 无状态组件 PureComponent)
由于元素没有办法传递参数,所以我们就需要把之前定义的变量改为一个方法,让这个方法去return一个元素:
import React from 'react'
import ReactDOM from 'react-dom'
// 特别注意这里的写法,如果要在JSX里写js表达式(只能是表达式,不能流程控制),就需要加 {},包括注释也是一样,并且可以多层嵌套
const app = (props) => 欢迎进入{props.name}的世界
ReactDOM.render(
app({
name: 'react'
}),
document.getElementById('root')
)
这里我们定义的方法实际上也是react定义组件的第一种方式-定义函数式组件,这也是无状态组件。但是这种写法不符合react的jsx的风格,更好的方式是使用以下方式进行改造
import React from 'react'
import ReactDOM from 'react-dom'
const App = (props) => 欢迎进入{props.name}的世界
ReactDOM.render(
// React组件的调用方式
,
document.getElementById('root')
)
这样一个完整的函数式组件就定义好了。但要注意!注意!注意!组件名必须大写,否则报错。
四.class组件
ES6的加入让JavaScript直接支持使用class来定义一个类,react的第二种创建组件的方式就是使用的类的继承,ES6 class
是目前官方推荐的使用方式,它使用了ES6标准语法来构建,看以下代码:
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
render () {
return (
// 注意这里得用this.props.name, 必须用this.props
欢迎进入{this.props.name}的世界
)
}
}
ReactDOM.render(
,
document.getElementById('root')
)
运行结果和之前完全一样,因为JS里没有真正的class,这个class只是一个语法糖, 但二者的运行机制底层运行机制不一样。
函数式组件是直接调用, 在前面的代码里已经有看到
es6 class
组件其实就是一个构造器,每次使用组件都相当于在实例化组件,像这样:
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
render () {
return (
欢迎进入{this.props.name}的世界
)
}
}
const app = new App({
name: 'react'
}).render()
ReactDOM.render(
app,
document.getElementById('root')
)
五.组件的组合、嵌套
将一个组件渲染到某一个节点里的时候,会将这个节点里原有内容覆盖
组件嵌套的方式就是将子组件写入到父组件的模板中去,且react没有Vue中的内容分发机制(slot),所以我们在一个组件的模板中只能看到父子关系
// 从 react 的包当中引入了 React 和 React.js 的组件父类 Component
// 还引入了一个React.js里的一种特殊的组件 Fragment
import React, { Component, Fragment } from 'react'
import ReactDOM from 'react-dom'
class Title extends Component {
render () {
return (
欢迎进入React的世界
)
}
}
class Content extends Component {
render () {
return (
React.js是一个构建UI的库
)
}
}
/** 由于每个React组件只能有一个根节点,所以要渲染多个组件的时候,需要在最外层包一个容器,如果使用div, 会生成多余的一层dom
class App extends Component {
render () {
return (
)
}
}
**/
// 如果不想生成多余的一层dom可以使用React提供的Fragment组件在最外层进行包裹
class App extends Component {
render () {
return (
)
}
}
ReactDOM.render(
,
document.getElementById('root')
)
#JSX 原理
要明白JSX的原理,需要先明白如何用 JavaScript 对象来表现一个 DOM 元素的结构?
看下面的DOM结构
<div class='app' id='appRoot'>
<h1 class='title'>欢迎进入React的世界h1>
<p>
React.js 是一个帮助你构建页面 UI 的库
p>
div>
上面这个 HTML 所有的信息我们都可以用 JavaScript 对象来表示:
{
tag: 'div',
attrs: {
className: 'app', id: 'appRoot'},
children: [
{
tag: 'h1',
attrs: {
className: 'title' },
children: ['欢迎进入React的世界']
},
{
tag: 'p',
attrs: null,
children: ['React.js 是一个构建页面 UI 的库']
}
]
}
但是用 JavaScript 写起来太长了,结构看起来又不清晰,用 HTML 的方式写起来就方便很多了。
于是 React.js 就把 JavaScript 的语法扩展了一下,让 JavaScript 语言能够支持这种直接在 JavaScript 代码里面编写类似 HTML 标签结构的语法,这样写起来就方便很多了。编译的过程会把类似 HTML 的 JSX 结构转换成 JavaScript 的对象结构。
下面代码:
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
render () {
return (
欢迎进入React的世界
React.js 是一个构建页面 UI 的库
)
}
}
ReactDOM.render(
,
document.getElementById('root')
)
编译之后将得到这样的代码:
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
render () {
return (
React.createElement(
"div",
{
className: 'app',
id: 'appRoot'
},
React.createElement(
"h1",
{ className: 'title' },
"欢迎进入React的世界"
),
React.createElement(
"p",
null,
"React.js 是一个构建页面 UI 的库"
)
)
)
}
}
ReactDOM.render(
React.createElement(App),
document.getElementById('root')
)
React.createElement
会构建一个 JavaScript 对象来描述你 HTML 结构的信息,包括标签名、属性、还有子元素等, 语法为
React.createElement(
type,
[props],
[...children]
)
所谓的 JSX 其实就是 JavaScript 对象,所以使用 React 和 JSX 的时候一定要经过编译的过程:
JSX —使用react构造组件,bable进行编译—> JavaScript对象 —
ReactDOM.render()
—>DOM元素 —>插入页面
#组件中DOM样式
一共有四种
想给虚拟dom添加行内样式,需要使用表达式传入样式对象的方式来实现:
// 注意这里的两个括号,第一个表示我们在要JSX里插入JS了,第二个是对象的括号
Hello world
行内样式需要写入一个样式对象,而这个样式对象的位置可以放在很多地方,例如render
函数里、组件原型上、外链js文件中
class
React推荐我们使用行内样式,因为React觉得每一个组件都是一个独立的整体
其实我们大多数情况下还是大量的在为元素添加类名,但是需要注意的是,class
需要写成className
(因为毕竟是在写类js代码,会收到js规则的限制,而class
是关键字)
Hello world
有时候需要根据不同的条件添加不同的样式,比如:完成状态,完成是绿色,未完成是红色。那么这种情况下,我们推荐使用classname/classnames这个包:
styled-components
是针对React写的一套css-in-js框架,简单来讲就是在js中写css。npm链接
styled-components是一个第三方包,要安装
#todoList
组件化开发React todolist, 项目开发中的组件的基本目录结构基本上是这样的:
/your-project
- src
- …
- components
- YourComponentOne
- index.js/YourComponentOne.js
- YourComponentTwo
- index.js/YourComponentTwo.js
- index.js 用于导出组件
注意:一个组件只干一件事情 ,所以TodoList和TodoItem要做成两个组件,这样也方便于后期理解shouldComponentUpdate
六.组件的数据挂载方式
React中数据分为两个部分