React01
React属于前端 三大框架: Vue Angular React
- vue: 开源社区
- react: Facebook
- angular: Google
React编写 分两种方式:
- 脚本方式
- 适合入门: 类似于 jQuery的使用
- 脚手架方式
- 适合实际工作. 类似于 vue angular 的使用
React
官方: https://react.docschina.org/
官方脚本:
有些地区网络 可能无法访问
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
国内脚本地址:
<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>
本地js文件: 到FTP获取
JSX
在原生 JS 的语法上, 只能利用函数封装实现简化操作: 然而这种语法并不够简单
Facebook工程师, 设计了新的语法糖, 来简化代码 – JSX
JSX: 就是能够在 脚本中 书写 的 XML 代码
但是这种写法 浏览器不能识别, 必须进行转化: babel
https://www.babeljs.cn/
脚本地址:
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
发展过程
- 原生DOM操作
- 需要一步一步一步…来写
- 创建元素->设置各种属性->设置内容 -> 找到要添加到哪里-> 添加上
- 需要一步一步一步…来写
- React操作
- 利用函数封装语法, 对创建元素过程进行了简化
- 发现: 语法不够简单
- 利用函数封装语法, 对创建元素过程进行了简化
- JSX
- 创建新的语法: JSX 在 脚本中书写 XML 代码
- 真正运行时, 需要babel 编译回 原生的JS代码
组件
React项目 也是 SPA: Single web Page Application 单页应用
组件: 组成页面的零件 – 复用性特征
- 函数: 简单组件
- 类: 复杂组件
事件
只有能够支持复杂操作的 类方式 组件才可以
<标签 on事件名={} />
脚手架方式
实际开发时常用
-
安装脚手架
-
确保npm的中国镜像
# 查看镜像: 有taobao字样就OK npm config get registry # 设置镜像 npm config set registry http://registry.npm.taobao.org/
-
安装脚手架
npm i -g create-react-app
常见错误: Error: File Exists 说明已经安装过, 直接使用即可!
或者参考 angular01 的笔记, 删除旧的 再安装新的
-
-
生成项目包: 注意执行cmd所在的目录下生成
create-react-app 包名 例如: create-react-app react_pro
-
启动项目: 在项目下执行
npm start
启动流程
- 启动服务器:
npm start
- 启动了唯一标识 是
3000
端口的服务器
- 启动了唯一标识 是
- 在浏览器中访问:
localhost:3000
- 服务器默认设定: 自动提供
index.html
给来访用户 -
index.html
: 存在<div id="root"></div>
标签 - webpack: 脚手架自带 webpack 打包工具, 默认设定: 把 index.js 文件打包到 index.html 中
- index.js: 使用 ReactDOM.render() 挂载了App.js 到 id=‘root’ 的标签中
- App.js 就是根组件
State状态值
微信小程序中的 data 和 setData() 就是模仿的 React 的状态值机制.
React中:
- state: 保存的值 可以显示到页面上
- setState: 配合此方法, 更新数据同时 可以更新UI
// 状态值 state
// rcc
import React, { Component } from "react";
export default class App extends Component {
// state 负责存储 界面上变化的值. 配合 setState 实现变化
state = { num: 1 };
doAdd = () => {
this.setState({ num: this.state.num + 1 });
};
doMinus = () => {
this.setState({ num: this.state.num - 1 });
};
render() {
return (
<div>
<button onClick={this.doMinus}>-</button>
<div>{this.state.num}</div>
<button onClick={this.doAdd}>+</button>
</div>
);
}
}
// 详说:事件中的this指向
// rcc
import React, { Component } from "react";
export default class App extends Component {
state = { num: 1 };
/**
* 函数中的this指向:
* 普通函数: xxx.show(); show()中的this 就是 xxx; this指向函数的调用者.
* 墙头草 随风倒
* 箭头函数: => xxx.show(); 箭头函数中的this与声明时所在位置一样, 和调用者无关;
* 忠贞. 身在曹营心在汉
*/
doAdd() {
this.setState({ num: this.state.num + 1 });
}
render() {
return (
<div>
{/* 点击时: 打 然然的媳妇; 谁打的? */}
{/* 点击时: 调用 当前对象的 doAdd 方法 -- 事件是 window 触发的.
window触发的函数 其this指向就是undefined */}
{/* 解决办法1: 指定 doAdd 中的this --- bind */}
<button onClick={this.doAdd.bind(this)}>{this.state.num}</button>
{/* 解决办法2: 利用箭头函数的 this 保存机制 */}
{/* 语法糖: ()=> { return this.doAdd() } 简化成 ()=> this.doAdd() */}
{/* 原理: 点击时 执行的箭头函数, 箭头函数再执行方法 */}
<button onClick={() => this.doAdd()}>{this.state.num}</button>
</div>
);
}
}
State的异步性
// 详说: setState
// rcc
import React, { Component } from "react";
export default class App extends Component {
state = { num: 1 };
doAdd() {
// 1. 黄色警告: 不要直接修改 state 中的值, 必须用 setState来改
// 2. a = 5; b = a++; b是5 a是6
// 3. setState 是异步的
this.setState({ num: this.state.num++ }, () => {
//参数2: 回调函数: 刷新UI完毕后自动触发
console.log("UI更新操作结束: 数据num:", this.state.num);
});
// setState()要做两件事
// 1. 更新数据
// 2. 刷新UI -- 慢 cpu->GPU显卡->重绘...
console.log(this.state.num);
}
render() {
return (
<div>
<button onClick={this.doAdd.bind(this)}>{this.state.num}</button>
</div>
);
}
}
State的更新作用
// setState 特殊用法
// rcc
import React, { Component } from "react";
export default class App extends Component {
//setState()做两件事: 更新UI 和 更新数据
num = 1; //实际使用时, 数据不放state 也可以利用 setState() 刷新页面
doAdd() {
this.num++;
this.setState({}); //更新UI 不更新数据: 参数必须填, 空对象即可!
console.log(this.num);
}
render() {
return (
<div>
<button onClick={this.doAdd.bind(this)}>更新 {this.num}</button>
</div>
);
}
}
动态样式
vue中: :style="{属性名:值}"
angular中: [ngStyle]="{属性名:值}"
// 动态样式:
// 内联 和 外部
// rcc
import React, { Component } from "react";
export default class App extends Component {
state = { size: 18 };
render() {
return (
<div>
<button onClick={() => this.setState({ size: this.state.size + 2 })}>
变大
</button>
{/* 内联样式的值: 对象类型 */}
<span
style={{
color: "red",
fontSize: this.state.size + "px",
backgroundColor: "lightgray",
padding: "10px",
borderRadius: "4px",
margin: "4px",
display: "inline-block",
}}
>
成功
</span>
</div>
);
}
}
外部class
// 外部样式
// rcc
import React, { Component } from "react";
/**
* 外部css文件的引入
*
* html引入: <link ...
* css 引入: @import 'css路径'
* js 引入: import 'css文件'
* 注意: 必须带有 路径标识 ./ / ../ 否则会识别为模块; 带路径标识才会识别为文件
*/
import "./App.css";
export default class App extends Component {
render() {
return (
<div>
{/* JSX是 DOM 的语法糖: DOM原生操作中 就是 className 属性名 */}
<span className="danger">DANGER</span>
</div>
);
}
}
双向数据绑定
vue: v-model
angular: [(ngModel)]
// 双向数据绑定
// rcc
import React, { Component } from "react";
export default class App extends Component {
// 变化的数据 && 影响UI -- 必须放state
state = { word: "123456" };
// 约定俗成的规范: 事件触发的函数 带有_开头; 这样读代码时 就能看出来哪些方法是事件触发的
_onChange(event) {
// 事件触发的函数, 都会自动接收事件作为 最后的参数
// console.log(event);
let word = event.target.value;
console.log(word);
//更新给数据 && 刷新UI
// this.setState({ word: value });
// 语法糖: { aaa: aaa } => { aaa }
this.setState({ word });
}
render() {
return (
<div>
{/* 报错: 绑定了变量给value属性, 导致输入框不能变动 -- 此时要选 这个输入框是 只读的 readOnly 还是 双向绑定 onChange */}
<input type="text" value={this.state.word} readOnly />
<br />
{/* onChange: 双向绑定的方向2 -- 数据变化时 */}
<input
type="text"
value={this.state.word}
onChange={this._onChange.bind(this)}
/>
<hr />
{/* 懒: 懒得声明函数 可以直接箭头函数写到JSX里 */}
<input
type="text"
value={this.state.word}
onChange={(event) => this.setState({ word: event.target.value })}
/>
<p>{this.state.word}</p>
</div>
);
}
}
事件传参
// 事件传参
// rcc
import React, { Component } from "react";
export default class App extends Component {
state = { item: "" };
_chooseItem(item) {
// 故意参数名item 和 state.item 同名, 凑语法糖
this.setState({ item });
}
render() {
return (
<div>
<span>然然最喜欢的项目: {this.state.item}</span>
<hr />
{/* 解决方案1: bind提前绑定参数, 点击后自动传入 */}
<button onClick={this._chooseItem.bind(this, "吃饭")}>吃饭</button>
{/* 解决方案2: 点击时执行箭头函数, 箭头函数再执行内部的方法 */}
<button onClick={() => this._chooseItem("睡觉")}>睡觉</button>
<button onClick={() => this._chooseItem("打亮亮")}>打亮亮</button>
</div>
);
}
}
回顾
React 作为三大框架之一: vue angular react
- vue, angular
- 属于一套思路: 在HTML中写 JS
{{}} v-html v-model ...
- React
- 在 JS 中 写 HTML
JSX语法:
- 是一个语法糖写法: 需要babel工具编译才能执行
- 在JS原生语法下: 函数封装特征无法 达到简化 DOM 操作的目的
组件: 组成页面的零件, 最大特征: 复用
- 函数
- 必须大驼峰的函数名: 为了区分普通函数
- 类
- 必须继承父类, 才会有强大的功能
事件:
- 事件写法: on事件名
- 重点: 触发函数的 this 指向问题
思路: 在HTML中写 JS
{{}} v-html v-model ...
- React
- 在 JS 中 写 HTML
JSX语法:
- 是一个语法糖写法: 需要babel工具编译才能执行
- 在JS原生语法下: 函数封装特征无法 达到简化 DOM 操作的目的
组件: 组成页面的零件, 最大特征: 复用
- 函数
- 必须大驼峰的函数名: 为了区分普通函数
- 类
- 必须继承父类, 才会有强大的功能
事件:
- 事件写法: on事件名
- 重点: 触发函数的 this 指向问题