Vue核心知识点
学习网址:
React学习网址
一.安装React
1.前言
如果你是在学习 React 或创建一个新的单页应用,请使用 Create React App。
2.介绍
是一个用于学习 React 的舒适环境,也是用 React 创建新的单页应用的最佳方式。
它会配置你的开发环境,以便使你能够使用最新的 JavaScript
特性,提供良好的开发体验,并为生产环境优化你的应用程序。你需要在你的机器上安装 Node >= 10.16 和 npm >=
5.6。要创建项目,请执行:
npx create-react-app my-app
cd my-app
npm start
注意:
第一行的 npx 不是拼写错误 —— 它是 npm 5.2+ 附带的 package 运行工具。
初始化项目:
二.CDN链接
可以通过 CDN 获得 React 和 ReactDOM 的 UMD 版本。
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
上述版本仅用于开发环境,不适合用于生产环境。压缩优化后可用于生产的 React 版本可通过如下方式引用:
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
如果需要加载指定版本的 react 和 react-dom,可以把 17 替换成所需加载的版本号。
三.JSX
注意点:
推荐使用小括号包裹react元素
基本使用方法:
const element = <h1>Hello, world!</h1>;
即这个element就被称为 JSX,是一个 JavaScript 的语法扩展。我们建议在 React 中配合使用 JSX,JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。
3.1在 JSX 中嵌入表达式
在下面的例子中,我们声明了一个名为 name 的变量,然后在 JSX 中使用它,并将它包裹在大括号中:
const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;
ReactDOM.render(
element,
document.getElementById('root')
);
在 JSX 语法中,你可以在大括号内放置任何有效的 JavaScript 表达式。例如,2 + 2,user.firstName 或 formatName(user) 都是有效的 JavaScript 表达式。
3.2 JSX 也是一个表达式
在编译之后,JSX 表达式会被转为普通 JavaScript 函数调用,并且对其取值后得到 JavaScript 对象。
也就是说,你可以在 if 语句和 for 循环的代码块中使用 JSX,将 JSX 赋值给变量,把 JSX 当作参数传入,以及从函数中返回 JSX:
例如;
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
3.3 JSX 特定属性
你可以通过使用引号,来将属性值指定为字符串字面量:
const element = <div tabIndex="0"></div>;
也可以使用大括号,来在属性值中插入一个 JavaScript 表达式:
const element = <img src={user.avatarUrl}></img>;
3.3 JSX 防止注入攻击
你可以安全地在 JSX 当中插入用户输入内容:
const title = response.potentiallyMaliciousInput;
// 直接使用是安全的:
const element = <h1>{title}</h1>;
React DOM 在渲染所有输入内容之前,默认会进行转义。它可以确保在你的应用中,永远不会注入那些并非自己明确编写的内容。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(cross-site-scripting, 跨站脚本)攻击。
3.4 JSX 表示对象
Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。
以下两种示例代码完全等效:
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
React.createElement() 会预先执行一些检查,以帮助你编写无错代码,但实际上它创建了一个这样的对象:
// 注意:这是简化过的结构
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
这些对象被称为 “React 元素”
它们描述了你希望在屏幕上看到的内容。React 通过读取这些对象,然后使用它们来构建 DOM 以及保持随时更新。
四、元素渲染
4.1 根Dom节点
假设你的 HTML 文件某处有一个
<div id="root"></div>
我们将其称为“根” DOM 节点,因为该节点内的所有内容都将由 React DOM 管理。
4.2渲染Dom根节点
想要将一个 React 元素渲染到根 DOM 节点中,只需把它们一起传入 ReactDOM.render():
<div id="root"></div>
。。。
const element = <h1>Hello, world</h1>;
ReactDOM.render(
element,
document.getElementById('root')
);
4.3 更新已渲染的元素
React 元素是不可变对象。一旦被创建,你就无法更改它的子元素或者属性。一个元素就像电影的单帧:它代表了某个特定时刻的 UI。
根据我们已有的知识,更新 UI 唯一的方式是创建一个全新的元素,并将其传入 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);
五、组件和props
5.1 定义组件
定义组件最简单的方式就是编写 JavaScript 函数:
注意:这里得函数名Welcome首字母必须大写。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
这时这个Welcome就是也组件。
该函数是一个有效的 React 组件,因为它接收唯一带有数据的 “props”(代表属性)对象与并返回一个 React 元素。这类组件被称为“函数组件”,因为它本质上就是 JavaScript 函数。
5.2 适用Es6语法中类定义组件
你同时还可以使用 ES6 的 class 来定义组件:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
5.3 渲染租组件
const element = <Welcome name="Sara" />;
当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)以及子组件(children)转换为单个对象传递给组件,这个对象被称之为 “props”。
上面得Welcomef即为:自定义组件
注意: 组件名称必须以大写字母开头。
5.4 Props 的只读性
组件无论是使用函数声明还是通过 class 声明,都决不能修改自身的 props。来看下这个 sum 函数:
纯函数
function sum(a, b) {
return a + b;
}
这样的函数被称为“纯函数”,因为该函数不会尝试更改入参,且多次调用下相同的入参始终返回相同的结果。
相反,下面这个函数则不是纯函数,因为它更改了自己的入参:
function withdraw(account, amount) {
account.total -= amount;
}
六、State和生命周期
6.1 state介绍
State 与 props 类似,但是 state 是私有的,并且完全受控于当前组件。
6.2 将函数组件转换成 class 组件
通过以下五步将 Clock 的函数组件转成 class 组件:
1创建一个同名的 ES6 class,并且继承于 React.Component。
2.添加一个空的 render() 方法。
将函数体移动到 render() 方法之中。
3.在 render() 方法中使用 this.props 替换 props。
4.删除剩余的空函数声明。
如下:
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
每次组件更新时 render 方法都会被调用,但只要在相同的 DOM 节点中渲染 ,就仅有一个 Clock 组件的
class 实例被创建使用。这就使得我们可以使用如 state 或生命周期方法等很多其他特性。
6.3向 class 组件中添加局部的 state
1.把 render() 方法中的 this.props.date 替换成 this.state.date :
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
2.添加一个 class 构造函数,然后在该函数中为 this.state 赋初值:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
通过以下方式将 props 传递到父类的构造函数中:
constructor(props) {
super(props);
this.state = {date: new Date()};
}
Class 组件应该始终使用 props 参数来调用父类的构造函数。
3.移除 元素中的 date 属性:
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
完整代码
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
6.4 将生命周期方法添加到 Class 中
当 Clock 组件第一次被渲染到 DOM 中的时候,就为其设置一个计时器。这在 React 中被称为“挂载(mount)”。
同时,当 DOM 中 Clock 组件被删除的时候,应该清除计时器。这在 React 中被称为“卸载(unmount)”。
我们可以为 class 组件声明一些特殊的方法,当组件挂载或卸载时就会去执行这些方法:
class Clock extends React.Component {
...
componentDidMount() {
//componentDidMount() 方法会在组件已经被渲染到 DOM 中后运行
}
componentWillUnmount() {
//组件卸载时调用
}
...
}
这些方法叫做“生命周期方法”。
6.5 正确地使用 State
不要直接修改 State
例如,此代码不会重新渲染组件:
// Wrong
this.state.comment = 'Hello';
而是应该使用 setState():
// Correct
this.setState({comment: 'Hello'});
注意:构造函数是唯一可以给 this.state 赋值的地方:
6.6 State的异步更新
因为 this.props 和 this.state 可能会异步更新,所以你不要依赖他们的值来更新下一个状态。
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
要解决这个问题,可以让 setState() 接收一个函数而不是一个对象。这个函数用上一个 state 作为第一个参数,将此次更新被应用时的 props 做为第二个参数:
// Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
上面使用了箭头函数,不过使用普通的函数也同样可以
6.7State 的更新会被合并
当你调用 setState() 的时候,React 会把你提供的对象合并到当前的 state。
6.8 数据是向下流动的
不管是父组件或是子组件都无法知道某个组件是有状态的还是无状态的,并且它们也并不关心它是函数组件还是 class 组件。
这就是为什么称 state 为局部的或是封装的的原因。除了拥有并设置了它的组件,其他组件都无法访问。
组件可以选择把它的 state 作为 props 向下传递到它的子组件中:
<FormattedDate date={this.state.date} />
FormattedDate 组件会在其 props 中接收参数 date,但是组件本身无法知道它是来自于 Clock 的 state,或是 Clock 的 props,还是手动输入的:
function FormattedDate(props) {
return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
}
七.事件传递
7.1 事件的基本使用
React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
7.2 阻止默认行为
在 React 中另一个不同点是你不能通过返回 false 的方式阻止默认行为。
function Form() {
function handleSubmit(e) {
// e 是一个合成事件。React 根据 W3C 规范来定义这些合成事件,所以你不需要担心跨浏览器的兼容性问题。React 事件与原生事件不完全相同。
e.preventDefault();
console.log('You clicked submit.');
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}
7.3 添加事件处理函数
当你使用 ES6 class 语法定义一个组件的时候,通常的做法是将事件处理函数声明为 class 中的方法。
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
如果觉得使用 bind 很麻烦,这里有两种方式可以解决。如果你正在使用实验性的 public class fields 语法,你可以使用
class fields 正确的绑定回调函数:
class LoggingButton extends React.Component {
// 此语法确保 `handleClick` 内的 `this` 已被绑定。
// 注意: 这是 *实验性* 语法。
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
7.4 向事件处理程序传递参数
在循环中,通常我们会为事件处理函数传递额外的参数。例如,若 id 是你要删除那一行的 ID,以下两种方式都可以向事件处理函数传递参数:
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
在这两种情况下,React 的事件对象 e 会被作为第二个参数传递。如果通过箭头函数的方式,事件对象必须显式的进行传递,而通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。
八.条件渲染
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>React入门</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!--下面这个不能少,少了就会运行不了-->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="example"></div>
<div id="root"></div>
<script type="text/babel">
const Loading=false;
var show=()=>{
if(Loading){
return <h3>Loading.....</h3>
}
return <h3>加载完成,展示数据</h3>
}
const element=<div>{show()}</div>
ReactDOM.render(
element,
document.getElementById("root")
)
</script>
</body>
</html>
九、列表渲染
<div id="example"></div>
<div id="root"></div>
<script type="text/babel">
const songs=[
{id:1,name:'张杰'},
{id:2,name:'周杰伦'},
{id:3,name:'王菲'},
]
const element=<ul>
{songs.map(item=><li key={item.id}>{item.name}</li>)}
</ul>
ReactDOM.render(
element,
document.getElementById("root")
)
十、jsx的样式处理
1.style样式(行内样式)
如下:
{songs.map(item=><li key={item.id} style={{color:'red'}}>{item.name}</li>)}
2.类名的方式
如:
const element=<ul className='title'>
记得引入css文件或者直接在style中加上title类选择器
已看到第17集