什么是React
1.发送请求获取数据
- 处理数据(过滤、整理格式等)
3.操作DOM呈现页面
react 主要是负责第三部 操作dom 处理页面
数据渲染为HTML视图的开源js库。
好处
避免dom繁琐
组件化 提升复用率
特点
声明式编程: 简单
组件化编程: 服用
react native 可以通过js 进行移动端开发。
虚拟DOM + Diffing算法, 减少和真实DOM交互。
前提知识
this指向
class类
ES6语法: 箭头函数, 浏览字符串,解构赋值
npm包管理器
原型, 原型链
数组常用方法
模块化
什么是npm包管理工具
https://blog.csdn.net/qq_25502269/article/details/79346545
官网
https://reactjs.org/
核心库
react.development.js react核心库
react-dom.development.js 扩展库
babel.min.js 负责 jsx 转js
引用时,核心库 必须 在 扩展库 之前引入
虚拟DOM 和 真实DOM区别
真实DOM 实际结构
虚拟DOM 设计图
真实 DOM: 真实 DOM 相当于房子的实际结构,包括砖墙、木梁、水管、电线等。如果你想要更改房子的结构或者添加新的功能,你需要直接去建筑工地,这可能会涉及到大量的人力和时间。每次做出更改,都会影响整个房子的状态。
虚拟 DOM: 现在,假设你有一份精确的房屋设计图,上面显示了房子的每个房间的详细布局和所有的设计规格,但并不是实际的建筑物。这份设计图相当于虚拟 DOM。你可以在设计图上轻松地进行修改和实验,而不用实际动工。你可以添加新的房间、更改房间的布局,甚至尝试不同的颜色和装饰方案。
更新房子: 一旦你在设计图上满意地调整了房子的布局和设计,你可以将这份设计图交给建筑工人,让他们按照设计图来建造实际的房子。这相当于虚拟 DOM 更新到真实 DOM 的过程。与直接在建筑工地上进行修改相比,这种方法更加高效,因为你可以在设计图上进行多次修改,然后一次性应用到实际建筑中,而不必每次都动工。
XML 和 JSON 两种存储结构存储数据
JSON 两个核心方法 parse 和 stringfy
parse
{
"name": "John Doe",
"age": 30,
"city": "New York"
}
const jsonString = '{"name": "John Doe", "age": 30, "city": "New York"}';
const person = JSON.parse(jsonString);
console.log(person.name); // 输出 "John Doe"
console.log(person.age); // 输出 30
console.log(person.city); // 输出 "New York"
stringfy
const person = {
name: "John Doe",
age: 30,
city: "New York"
};
const jsonString = JSON.stringify(person);
console.log(jsonString);
// 输出 '{"name":"John Doe","age":30,"city":"New York"}'
hello world
JS 实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>hello_react</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<div id="demo"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">/* 此处一定要写babel */
//1.创建虚拟DOM
const VDOM = <h1>Hello,React</h1>/* 此处一定不要写引号,因为不是字符串 */
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM, document.getElementById('test'))
var TDOM = document.getElementById('demo');
console.log('虚拟DOM', VDOM)
console.log('真实DOM', TDOM)
debugger;
</script>
</body>
</html>
React实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>hello_react</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">/* 此处一定要写babel */
//1.创建虚拟DOM
const VDOM = <h1>Hello,React</h1>/* 此处一定不要写引号,因为不是字符串 */
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM, document.getElementById('test'))
</script>
</body>
</html>
JSX语法规则
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JSX syntax rules</title>
<style>
.title{
background-color: orange;
width: 200px;
}
</style>
</head>
<body>
<!-- container -->
<div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
const myId = "aTgUiGu"
const myData = 'HeLlo,rEacT'
// create virtual DOM
const VDOM = (
<div>
<h2 className="title" id={myId.toLowerCase()}>
<span style={{color:'white', fontSize:'29px'}}>{myData.toLowerCase()}</span>
</h2>
<input type="text"/>
</div>
)
// render the DOM to pagea
ReactDOM.render(VDOM, document.getElementById('test'))
/**
* Jsx syntax rules:
1. when define the virtual D0M, do not write quotation marks.
2. Use {} when mixing JS expressions into the label.
3. 样式的类名指定不要用class,要用className。
4. 内联样式,要用style={{key:value)}}的形式去写。
5. 只有一个根标签
6. 标签必须闭合
7.标签首字母
(1). 若小写字母开头,则将改标签转为htm1中同名元素,若html中无该标签对应的同名元素,则报错。
(2). 若大写字母开头,react就去渲染对应的组件, 若组件没有定义,则报错。
*/
</script>
</body>
</html>
模块化
模块化是按功能开发 组件是按区域开发
模块
向外提供特定功能的js 程序,一般就是一个js文件
组件
用来实现局部功能效果的代码和资源的集合(html/css/js/image 等等)
React面向组件编程
安装react调试工具
https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi
函数式组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
class Person{
constructor(name, age) {
this.name = name
this.age = age
}
speak(){
// 通过Person实例调用speak时,speak中的this就是Person实例
console.log(`I am ${this.name},I am ${this.age}`)
}
}
class Student extends Person{
constructor(name,age,grade){
super(name, age)
this.grade = grade
}
speak(){
console.log(`I am ${this.name},I am ${this.age}, I am ${this.grade}`)
}
study(){
console.log('I am study hard')
}
}
const p1 = new Person('TOM', 18)
const p2 = new Person('Jerry', 19)
const c1 = new Student('zs', 12, 'First year of high school')
console.log(p1);
console.log(p2);
console.log(c1);
p1.speak()
p2.speak()
c1.speak()
c1.study()
</script>
</body>
</html>
简单组件和复杂组件的区别 state
组件实例三大核心属性
state
state 是组件对象最重要的属性,值是对象(可以包含多个 key-value 的组合)
组件被称为“状态机“通过更新组件的state 来更新对应的页面显示(重新渲染组件)
-
组件中 render 方法中的 this 为组件实例对象
-
组件自定义的方法中 this 为 undefined,如何解决?
a. 强制绑定 this:通过函数对象的 bind()
b. 箭头函数 -
状态数据,不能直接修改 or 更新,必须借助 setState()实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Class-defined Component</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入React核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入React DOM,用于支持React操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入Babel,用于将JSX转为JS -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> /* 此处一定要写babel */
// 1. 创建类组件
class Weather extends React.Component {
constructor(props){
super(props)
this.state = {isHot:true, wind:"breeze"}
this.changeWeather = this.changeWeather.bind(this)
}
changeWeather(){
// 状态必须通过setstate进行更新,且更新是一种合并,不是替换。
const isHot = this.state.isHot
this.setState({isHot: !isHot})
this.state.isHot;
// console.log('title was clicked')
console.log(this.state)
}
//render调用几次? 1+n次 1是初始化的那次 n是状态更新的次数
render() {
// console.log(this)
const {isHot, wind} = this.state// read the state
return <h1 onClick={this.changeWeather}>Today is {isHot ? 'so hot' : "so cool"},{wind}</h1>;
}
}
// 渲染
ReactDOM.render(<Weather/>, document.getElementById('test'));
// alt + shift + a 多行注释
/* const title = document.getElementById('title')
title.addEventListener('click',()=>{
console.log('title was clicked')
}) */
/* const title = document.getElementById('title')
title.onclick = ()=>{
console.log('title was clicked')
} */
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Class-defined Component</title>
</head>
<body>
<div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 创建组件
class Weather extends React.Component {
constructor(props){
super(props)
// this.changeWeather = this.changeWeather.bind(this)
}
// 初始化状态
state = {isHot:true, wind:"breeze"}
// 自定义方法-----要用赋值语句形式 + 箭头函数
changeWeather = ()=>{
const isHot = this.state.isHot
this.setState({isHot: !isHot})
}
render() {
const {isHot, wind} = this.state
return <h1 onClick={this.changeWeather}>Today is {isHot ? 'so hot' : "so cool"},{wind}</h1>;
}
}
ReactDOM.render(<Weather/>, document.getElementById('test'));
</script>
</body>
</html>
prop
每个组件对象都会有 props(properties 的简写)属性
组件标签的所有属性都保存在 props 中
通过标签属性从组件外向组件内传递变化的数据注意:
组件内部不要修改 props 数据
使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>class-defined component</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 引入 prop-types, 用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">/* 此处一定要写babel */
class Person extends React.Component{
static propTypes = {
name:PropTypes.string.isRequired, // 限制为string类型
sex:PropTypes.string,
age:PropTypes.number,
speak:PropTypes.func, // 限制函数
}
static defaultProps = {
sex:"不男不女",
age:18
}
// state = {name: 'tom',age:18, sex:'female'}
render(){
const {name, age, sex} = this.props;
return (
<ul>
<li>name: {name}</li>
<li>gender: {sex}</li>
<li>age: {age + 100}</li>
</ul>
)
}
}
// Person.propTypes = {
// name:PropTypes.string.isRequired, // 限制为string类型
// sex:PropTypes.string,
// age:PropTypes.number,
// speak:PropTypes.func, // 限制函数
// }
// Person.defaultProps = {
// sex:"不男不女",
// age:18
// }
// 这里name不填会有警告
ReactDOM.render(<Person age={21} sex="female"/>,document.getElementById('test1'))
ReactDOM.render(<Person name="joe2" />,document.getElementById('test2'))
// ReactDOM.render(<Person name="joe3" age="23" sex="female"/>,document.getElementById('test3'))
const p = {name:'joe3', age:11, sex:'female'}
ReactDOM.render(<Person {...p}/>, document.getElementById("test3"))
</script>
</body>
</html>
拓展知识
展开运算符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
let arr1 = [1,3,5,7,9]
let arr2 = [2,4,6,8,10]
console.log(...arr1) // 展开数组
let arr3 = [...arr1, ...arr2] // 连接数组
console.log(...arr3)
// function sum(...numbers){
// console.log('@',numbers)
// return a + b + c
// }
// 在函数中使用
function sum(...numbers) {
return numbers.reduce((preValue, currentValue)=>{
return preValue + currentValue
})
}
console.log(sum(1,2,3,4))
let person = {name:'tom',age:18}
let person2 = {...person} // 复制一个对象,深度复制
// console.log(...person);//报错,展开运算符不能展开对象
let person3 = {...person,name:'jack',address:'us'}
console.log(person3) // 复制同时,修改对象
</script>
</body>
</html>
refs
最旧版本使用refs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ref string type</title>
</head>
<body>
<div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 创建组件
class Demo2 extends React.Component {
showData = ()=>{
// const input = document.getElementById('input1')
// alert(input.value)
const {input1} = this.refs
alert(input1.value)
// console.log(input1);
// debugger;
}
showData2 = ()=>{
const {input2} = this.refs
alert(input2.value)
}
render() {
return (
<div>
<input ref="input1"
type="text"
placeholder="prompt data" />
<button ref="123"
onClick={this.showData}>prompt data</button>
<input ref="input2"
onBlur={this.showData2}
type="text" placeholder="lose data" />
<button>lose prompt</button>
</div>
);
}
}
ReactDOM.render(<Demo2/>, document.getElementById('test'));
</script>
</body>
</html>
回调函数
1.你定义的函数
2.你没有调用
3.这个函数最终被别人调用了
新版本ref的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ref string type</title>
</head>
<body>
<div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
</script>
</body>
</html>
React官方推荐ref用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ref string type</title>
</head>
<body>
<div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class Demo extends React.Component{
state = {isHot:true}
myRef = React.createRef()
myRef2 = React.createRef()
showInfo = ()=>{
alert(this.myRef.current.data)
}
showData = ()=>{
alert(myRef2.current.value)
}
changeWeather = ()=>{
//get state
const {isHot} = this.state
this.setState({isHot:!isHot})
}
saveInput = (c)=>{
this.input1 = c;
console.log("@", c);
}
render(){
const {isHot} = this.state
return (
<div>
<h2>Today is {isHot ? "Hot" : "Cold"}</h2>
<input
ref={this.myRef}
type="text"
/>
<button
onClick={this.showInfo}
>click me</button>
<button
onClick={this.changeWeather}
>change weather</button>
<input
onBlur={this.showData}
ref={this.myRef2}
type="text"
palceholder="lose focus"
/>
</div>
);
}
}
ReactDOM.render(<Demo/>, document.getElementById('test'));
</script>
</body>
</html>