一、react基本应用
一、helloworld(可直接用浏览器打开文件即可)
cdn:bootcdn有各种js 的cdn; 一般提供开发版(js未压缩)和生产版(js压缩过了)
需要引入3个js

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>Add React in One Minute</title> 6 </head> 7 <body> 8 9 10 <!-- Load React. --> 11 <!-- Note: when deploying, replace "development.js" with "production.min.js". --> 12 <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> 13 <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> 14 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 15 <div id="example"></div> 16 <script type="text/babel"> 17 //1.创建虚拟DOM元素对象 18 var vDOM=<h1> HELLO WORLD</h1> 19 20 //2.将虚拟DOM渲染到真是的ROM容器中 21 ReactDOM.render(vDOM,document.getElementById("example")); 22 </script> 23 24 25 </body> 26 </html>
页面显示 HELLO WORLD
两种方式,实现react hello world;
jsx写法:const vDom2 = <h3 id={id.toLocaleUpperCase()}>{msg.toLocaleLowerCase()}</h3>;
- "<"代表标签开始
- “{”代表js代码开始
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>Add React in One Minute</title> 6 </head> 7 <body> 8 9 <h2>Add React in One Minute</h2> 10 11 <div id="test"></div> 12 <div id="test2"></div> 13 <!-- Load React. --> 14 <!-- Note: when deploying, replace "development.js" with "production.min.js". --> 15 <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> 16 <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> 17 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 18 19 20 <script> 21 const msg = "AAAA BBBB VVV DD!"; 22 const id = "xsdfsdf" 23 //1.创建虚拟DOM ;参数:标签名,标签属性(键值对);标签内容 24 const vDom1 = React.createElement("h2",{id:id.toLowerCase()},msg.toUpperCase()); 25 //2.渲染虚拟DOM 参数:虚拟对象 ,DOM容器 26 ReactDOM.render(vDom1,document.getElementById("test")); 27 </script> 28 29 <script type="text/babel"> 30 //1.创建虚拟DOM 31 const vDom2 = <h3 id={id.toLocaleUpperCase()}>{msg.toLocaleLowerCase()}</h3>; 32 //2.渲染虚拟DOM 参数:虚拟对象 ,DOM容器 33 ReactDOM.render(vDom2,document.getElementById("test2")); 34 </script> 35 </body> 36 </html>
数组用列表形式显示:

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>Add React in One Minute</title> 6 </head> 7 <body> 8 <div id="example"></div> 9 <!-- Load React. --> 10 <!-- Note: when deploying, replace "development.js" with "production.min.js". --> 11 <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> 12 <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> 13 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 14 15 16 17 <script type="text/babel"> 18 //需求:数组用列表显示 19 //问题:如何将一个数据的数字转换为一个标签的数组 20 //利用数组的map函数 21 const names=["jqyer","react","vue"]; 22 //1.创建虚拟DOM 23 const vDom2 = <ul>{ 24 names.map((name,index)=><li key={index}>{name}</li>) 25 }</ul> 26 //2.渲染虚拟DOM 参数:虚拟对象 ,DOM容器 27 ReactDOM.render(vDom2,document.getElementById("example")); 28 </script> 29 </body> 30 </html>
组件编程的基本定义和使用:
简单组件(组件无状态)和复杂组件(组件有状态)

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>Add React in One Minute</title> 6 </head> 7 <body> 8 <div id="example"></div> 9 <div id="example2"></div> 10 <!-- Load React. --> 11 <!-- Note: when deploying, replace "development.js" with "production.min.js". --> 12 <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> 13 <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> 14 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 15 16 17 18 <script type="text/babel"> 19 20 //1.定义组件 组件名称大写 21 //方式1:工厂函数组件(简单组件) 必须要return; 22 function MyComponent(){ 23 return <h2>工厂函数组件(简单组件)</h2> 24 } 25 //方式2:ES6类组件(复杂组件) 26 class MyComponent2 extends React.Component{ 27 render(){ 28 return <h2>ES6类组件(复杂组件)</h2> 29 } 30 } 31 //2.渲染组件,容器DOM 32 ReactDOM.render(<MyComponent/>,document.getElementById('example')); 33 ReactDOM.render(<MyComponent2/>,document.getElementById('example2')); 34 </script> 35 </body> 36 </html>
简单组件实现结合props的相关说明

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>Add React in One Minute</title> 6 </head> 7 <body> 8 <div id="like"></div> 9 <div id="like2"></div> 10 <!-- Load React. --> 11 <!-- Note: when deploying, replace "development.js" with "production.min.js". --> 12 <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> 13 <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> 14 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 15 <script src="/my-app/node_modules/prop-types/prop-types.min.js"></script> 16 17 18 19 <script type="text/babel"> 20 21 //1.定义组件 组件名称大写 22 //方式1: 23 function PersonInfo(props){ 24 return <ul><li>姓名:{props.name}</li><li>年龄:{props.age}</li><li>性别:{props.sex}</li></ul> 25 } 26 27 //指定属性默认值 28 PersonInfo.defaultProps={ 29 sex:"男", 30 age:18 31 } 32 //对props中的属性今昔类型限制和必要性限制 33 // PersonInfo.propTypes = { 34 // name: PropTypes.string 35 // } 36 //2.渲染组件标签,容器DOM 37 const p1={ 38 name:"TOM", 39 age:12, 40 sex:"女" 41 } 42 43 const p2={ 44 name:"TOM" 45 } 46 47 //传值也可使用...p1 48 //...的作用:1.打包,2.解包 49 //1.打包 function fn(...as){} fn(1,2,3) 参数放到数组as中 50 //2.解包 const arr1=[1,2,3] const arr2=[6,...arr1,9] 即[6,1,2,3,9] 51 52 // ReactDOM.render(<PersonInfo name={p1.name} age={p1.age} sex={p1.sex}/>,document.getElementById('like')); 53 ReactDOM.render(<PersonInfo{...p1}/>,document.getElementById('like')); 54 ReactDOM.render(<PersonInfo name={p2.name}/>,document.getElementById('like2')); 55 56 </script> 57 </body> 58 </html>
复杂组件的相关说明:state的状态和将新增的方法强制绑定为组件对象;
state:初始化状态,读取状态,更新状态;
注意:
- return 只能有一个根标签;
- 将新增方法中的this强制绑定为组件对象,需要在构造器中加入t额外加入his.handleClick = this.handleClick.bind(this);如果不想在构造器中加入绑定,那么方法可以直接用箭头函数;否则一定要在构造器中绑定对象;

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>Add React in One Minute</title> 6 </head> 7 <body> 8 <div id="like"></div> 9 <!-- Load React. --> 10 <!-- Note: when deploying, replace "development.js" with "production.min.js". --> 11 <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> 12 <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> 13 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 14 15 16 17 <script type="text/babel"> 18 19 //1.定义组件 组件名称大写 20 //方式2:ES6类组件(复杂组件) 21 class Like extends React.Component{ 22 constructor(prop){ 23 super(prop) 24 //初始化状态 25 this.state={ 26 isOpen:false 27 } 28 //将新增方法中的this强制绑定为组件对象 29 this.handleClick = this.handleClick.bind(this) 30 } 31 //新添加方法:内部的this默认是undefined 不是组件对象 32 handleClick(){ 33 const isOpen = !this.state.isOpen 34 //更新状态 35 //this.setState({isOpen:isOpen}) 等同于this.setState({isOpen}) ! 36 this.setState({isOpen}) 37 } 38 //重写组件方法 39 render(){ 40 console.log(this);//组件实例对象 41 //读取状态 42 const {isOpen} = this.state 43 return <h2 onClick={this.handleClick}>{isOpen?"关":"开"}</h2> 44 } 45 } 46 //2.渲染组件标签,容器DOM 47 ReactDOM.render(<Like/>,document.getElementById('like')); 48 </script> 49 </body> 50 </html>
ref、事件event获取元素的值

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>Add React in One Minute</title> 6 </head> 7 <body> 8 <div id="example"></div> 9 <!-- Load React. --> 10 <!-- Note: when deploying, replace "development.js" with "production.min.js". --> 11 <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> 12 <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> 13 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 14 <script src="/my-app/node_modules/prop-types/prop-types.min.js"></script> 15 16 17 18 <script type="text/babel"> 19 20 //1.定义组件 组件名称大写 21 class LearnRef extends React.Component{ 22 constructor(props){ 23 super(props); 24 this.showInput = this.showInput.bind(this); 25 this.handleBlur = this.handleBlur.bind(this); 26 } 27 showInput(){ 28 alert("方式二:"+this.elementKey.value); 29 } 30 handleBlur(event){ 31 alert(event.target.value); 32 } 33 // ref={input=>this.elementKey=input} input表示当前input元素 elementKey 表示对象的键值对的键值 34 render(){ 35 return <div> 36 <input type="text" ref={input=>this.elementKey=input}/><br/> 37 <input type="text" placeholder="失去焦点提示内容" onBlur={this.handleBlur}/><br/> 38 <button onClick={this.showInput}>输入提示</button> 39 </div> 40 } 41 } 42 //2.渲染组件 43 ReactDOM.render(<LearnRef/>,document.getElementById('example')); 44 45 </script> 46 </body> 47 </html>
组件化编程
流程:
1.拆分组件
2.实现静态组件(只有静态页面,没有动态数据和交互)
3.实现动态组件:1)。实现初始化数据动态显示;2).实现交互功能:
demo实现功能如下:

1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="UTF-8" /> 6 <title>Add React in One Minute</title> 7 8 </head> 9 10 <body> 11 <div id="example"></div> 12 <!-- Load React. --> 13 <!-- Note: when deploying, replace "development.js" with "production.min.js". --> 14 <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> 15 <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> 16 <script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.min.js"></script> 17 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 18 19 20 21 <!-- <script src="learn.js"></script> --> 22 <script type="text/babel"> 23 //1.定义组件 组件名称大写 24 class App extends React.Component { 25 constructor(props) { 26 super(props); 27 this.state={ 28 todos:["eat","sleep","coding"] 29 } 30 this.addTodo = this.addTodo.bind(this); 31 } 32 33 addTodo(todo){ 34 // this.state.todos.unshift(todo); 不可以这么写 35 const {todos}=this.state; 36 todos.unshift(todo); 37 //跟新状态 38 this.setState({todos}); 39 40 } 41 render() { 42 43 return ( 44 <div> 45 <h1>simple todo list</h1> 46 <Add count={this.state.todos.length} addTodo={this.addTodo}/> 47 <List todos={this.state.todos}/> 48 </div> 49 50 ) 51 } 52 } 53 54 class Add extends React.Component { 55 constructor(props) { 56 super(props); 57 this.add=this.add.bind(this); 58 } 59 add(){ 60 const todo = this.todoItem.value.trim(); 61 if(!todo){ 62 return; 63 } 64 this.props.addTodo(todo); 65 } 66 render(){ 67 return ( 68 <div> 69 <input type="text" ref={input=>this.todoItem=input}/><button onClick={this.add}>添加#{this.props.count+1}</button> 70 </div> 71 ) 72 } 73 } 74 class List extends React.Component { 75 constructor(props) { 76 super(props); 77 } 78 render(){ 79 return ( 80 <ul> 81 {this.props.todos.map((todo,index)=><li key={index}>{todo}</li>)} 82 </ul> 83 ) 84 } 85 } 86 //参数设置限制 87 List.propTypes = { 88 todos: PropTypes.array.isRequired 89 }; 90 Add.propTypes = { 91 count: PropTypes.number.isRequired, 92 addTodo:PropTypes.func.isRequired 93 }; 94 //2.渲染组件 95 ReactDOM.render(<App />, document.getElementById('example')); 96 97 </script> 98 </body> 99 100 </html>
关于限制项的另外一种写法:必须要写在组件内。表示该组件类的限制
static propTypes = {
todos: PropTypes.array.isRequired
};

1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="UTF-8" /> 6 <title>Add React in One Minute</title> 7 8 </head> 9 10 <body> 11 <div id="example"></div> 12 <!-- Load React. --> 13 <!-- Note: when deploying, replace "development.js" with "production.min.js". --> 14 <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> 15 <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> 16 <script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.min.js"></script> 17 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 18 19 20 21 <!-- <script src="learn.js"></script> --> 22 <script type="text/babel"> 23 //1.定义组件 组件名称大写 24 class App extends React.Component { 25 constructor(props) { 26 super(props); 27 this.state={ 28 todos:["eat","sleep","coding"] 29 } 30 this.addTodo = this.addTodo.bind(this); 31 } 32 33 addTodo(todo){ 34 // this.state.todos.unshift(todo); 不可以这么写 35 const {todos}=this.state; 36 todos.unshift(todo); 37 //跟新状态 38 this.setState({todos}); 39 40 } 41 render() { 42 43 return ( 44 <div> 45 <h1>simple todo list</h1> 46 <Add count={this.state.todos.length} addTodo={this.addTodo}/> 47 <List todos={this.state.todos}/> 48 </div> 49 50 ) 51 } 52 } 53 54 class Add extends React.Component { 55 constructor(props) { 56 super(props); 57 this.add=this.add.bind(this); 58 } 59 add(){ 60 const todo = this.todoItem.value.trim(); 61 if(!todo){ 62 return; 63 } 64 this.props.addTodo(todo); 65 } 66 render(){ 67 return ( 68 <div> 69 <input type="text" ref={input=>this.todoItem=input}/><button onClick={this.add}>添加#{this.props.count+1}</button> 70 </div> 71 ) 72 } 73 } 74 class List extends React.Component { 75 //参数设置限制的另外一种写法 76 static propTypes = { 77 todos: PropTypes.array.isRequired 78 }; 79 constructor(props) { 80 super(props); 81 } 82 render(){ 83 return ( 84 <ul> 85 {this.props.todos.map((todo,index)=><li key={index}>{todo}</li>)} 86 </ul> 87 ) 88 } 89 } 90 //参数设置限制 91 Add.propTypes = { 92 count: PropTypes.number.isRequired, 93 addTodo:PropTypes.func.isRequired 94 }; 95 //2.渲染组件 96 ReactDOM.render(<App />, document.getElementById('example')); 97 98 </script> 99 </body> 100 101 </html>
获取表单数据:
获取组件值的方式有两种:1.受控组件方式(表单输入数据能自动收集成状态:可以理解为onChange方式) ;2.非受控组件方式(r需要时,才手动读取输入框中的值,可以理解为ef方式)

1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="UTF-8" /> 6 <title>Add React in One Minute</title> 7 8 </head> 9 10 <body> 11 <div id="example"></div> 12 <!-- Load React. --> 13 <!-- Note: when deploying, replace "development.js" with "production.min.js". --> 14 <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> 15 <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> 16 <script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.min.js"></script> 17 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 18 19 20 21 <!-- <script src="learn.js"></script> --> 22 <script type="text/babel"> 23 //1.定义组件 组件名称大写 24 class GetFormInfo extends React.Component { 25 constructor(props) { 26 super(props); 27 this.handleChange=this.handleChange.bind(this); 28 this.handleSubmit = this.handleSubmit.bind(this); 29 this.state={ 30 pwd:'' 31 } 32 } 33 34 handleChange(event){ 35 const pwd = event.target.value; 36 //更新状态 37 this.setState({pwd}); 38 } 39 handleSubmit(){ 40 const name = this.name.value; 41 const {pwd}=this.state; 42 alert("当前填写的表单信息为:用户名:"+name+",密码:"+pwd); 43 } 44 render() { 45 46 return ( 47 <form onSubmit={this.handleSubmit}> 48 用户名:<input type="text" ref={input=>this.name = input}/> 49 密码:<input type="password" onChange={this.handleChange} value={this.state.pwd}/> 50 <input type="submit" value="显示表单信息"/> 51 </form> 52 53 ) 54 } 55 } 56 //2.渲染组件 57 ReactDOM.render(<GetFormInfo />, document.getElementById('example')); 58 59 </script> 60 </body> 61 62 </html>
组件的生命周期
1. 组件的三个生命周期状态:
- Mount:插入真实 DOM
- Update:被重新渲染
- Unmount:被移出真实 DOM
2. 生命周期流程:
* 第一次初始化显示: ReactDOM.render(<Xxx/>, containDom)
- constructor()
- componentWillMount() : 将要插入回调
- render() : 用于插入虚拟DOM回调
- componentDidMount() : 已经插入回调
* 每次更新state: this.setState({})
- componentWillReceiveProps(): 接收父组件新的属性
- componentWillUpdate() : 将要更新回调
- render() : 更新(重新渲染)
- componentDidUpdate() : 已经更新回调
* 删除组件: ReactDOM.unmountComponentAtNode(div): 移除组件
- componentWillUnmount() : 组件将要被移除回调
3. 常用的方法
- render(): 必须重写, 返回一个自定义的虚拟DOM
- constructor(): 初始化状态, 绑定this(可以箭头函数代替)
- componentDidMount() : 只执行一次, 已经在dom树中, 适合启动/设置一些监听!
demo 效果图:

1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="UTF-8" /> 6 <title>Add React in One Minute</title> 7 8 </head> 9 10 <body> 11 <div id="example"></div> 12 <!-- Load React. --> 13 <!-- Note: when deploying, replace "development.js" with "production.min.js". --> 14 <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> 15 <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> 16 <script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.min.js"></script> 17 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> 18 19 20 21 <!-- <script src="learn.js"></script> --> 22 <script type="text/babel"> 23 //1.定义组件 组件名称大写 24 class Life extends React.Component { 25 constructor(props) { 26 super(props); 27 28 this.state={ 29 opcity:1 30 } 31 this.handleClick = this.handleClick.bind(this); 32 } 33 34 componentDidMount(){ 35 this.intervalId =setInterval(function(){ 36 let {opcity}= this.state; 37 opcity -= 0.1; 38 if(opcity<0){ 39 opcity = 1; 40 } 41 this.setState({opcity}) 42 }.bind(this),500) 43 } 44 componentWillUnmount(){ 45 clearInterval(this.intervalId); 46 } 47 handleClick(){ 48 ReactDOM.unmountComponentAtNode(document.getElementById('example')); 49 } 50 render() { 51 const {opcity}=this.state 52 return ( 53 <div> 54 <h2 style={{opacity:opcity}}> react 太难了</h2> 55 <button onClick={this.handleClick}>不活了</button> 56 </div> 57 58 ) 59 } 60 } 61 //2.渲染组件 62 ReactDOM.render(<Life />, document.getElementById('example')); 63 64 </script> 65 </body> 66 67 </html>
组件模板:
一般写组件可以在这个模板里面写:

1 import React, { Component } from 'react'; 2 export default class defalutApp extends Component { 3 constructor(props) { 4 super(props); 5 this.state = { 6 } 7 } 8 render() { 9 10 return ( 11 <div> 12 </div> 13 14 ) 15 } 16 }
axios 请求

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>11_ajax</title> 6 </head> 7 <body> 8 <div id="example"></div> 9 10 <script type="text/javascript" src="../js/react.development.js"></script> 11 <script type="text/javascript" src="../js/react-dom.development.js"></script> 12 <script type="text/javascript" src="../js/babel.min.js"></script> 13 <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.js"></script> 14 <script type="text/babel"> 15 /* 16 需求: 17 1. 界面效果如下 18 2. 根据指定的关键字在github上搜索匹配的最受关注的库 19 3. 显示库名, 点击链接查看库 20 4. 测试接口: https://api.github.com/search/repositories?q=r&sort=stars 21 */ 22 class AxiosComponent extends React.Component{ 23 state={ 24 repoName:"", 25 repoUrl:"" 26 } 27 componentDidMount(){ 28 const url = "https://api.github.com/search/repositories?q=r&sort=stars"; 29 axios.get(url).then(response=>{ 30 console.log(response.data); 31 const result = response.data 32 this.setState({ 33 repoName:result.items[0].name,repoUrl:result.items[0].html_url 34 }) 35 }) 36 } 37 render(){ 38 const {repoName,repoUrl} = this.state; 39 if(!repoName){ 40 return( 41 <h2>Loading...</h2> 42 ) 43 }else{ 44 return <h2>最受欢迎的组件是<a href={repoUrl}>{repoName}</a></h2> 45 } 46 return( 47 <div></div> 48 ) 49 } 50 } 51 ReactDOM.render(<AxiosComponent/>,document.getElementById("example")) 52 </script> 53 </body> 54 </html>
组件之间的参数传递:
1.props传递;以上例子都是使用props传递,不再赘述
2.使用消息订阅(subscribe)-发布(publish)机制;
- 在当前项目安装pubsub-js:npm install --save pubsub-js
- github地址:https://github.com/mroderick/PubSubJS
-
发布消息:PubSub.publish('MY TOPIC', 'hello world!');
-
订阅消息:var token = PubSub.subscribe('MY TOPIC', mySubscriber);
订阅消息的说明:
var token = PubSub.subscribe('MY TOPIC', mySubscriber);
var mySubscriber = function (msg, data) { console.log(msg, data); };
订阅位置:一般是在componentDidMount() 里面设置订阅;
3.redux
react-router:
说明react v5到v6:- Switch 重命名为 Routes
- Route 的新特性变更 ,component/render被element替代
- react-router-dom 6版本移除了 Redirect,用 Navigate 代替
创建:npx create-react-app react-app
1.下载 npm install --save react-router-dom
2.helloword代码:
index.html:

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="utf-8" /> 5 <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1" /> 7 <meta name="theme-color" content="#000000" /> 8 <meta 9 name="description" 10 content="Web site created using create-react-app" 11 /> 12 <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> 13 <link rel="stylesheet" href="css/bootstrap.css" /> 14 <title>React App</title> 15 </head> 16 <body> 17 <noscript>You need to enable JavaScript to run this app.</noscript> 18 <div id="root"></div> 19 </body> 20 </html>
app.jsx:

1 import React, { Component } from 'react'; 2 import {Route, Switch, Redirect,NavLink} from 'react-router-dom' 3 import Home from '../views/home.jsx'; 4 import About from '../views/about.jsx'; 5 export default class App extends Component { 6 constructor(props) { 7 super(props); 8 this.state = { 9 } 10 } 11 render() { 12 return ( 13 <div> 14 <div className="row"> 15 <div className="col-xs-offset-2 col-xs-8"> 16 <div className="page-header"> 17 <h2>React Router Demo</h2> 18 </div> 19 </div> 20 </div> 21 22 <div className="row"> 23 <div className="col-xs-2 col-xs-offset-2"> 24 <div className="list-group"> 25 {/*导航路由链接*/} 26 <NavLink className="list-group-item" activeClassName="activeClass" to='/about'>About</NavLink> 27 <NavLink className="list-group-item" activeClassName="activeClass" to='/home'>Home</NavLink> 28 </div> 29 </div> 30 <div className="col-xs-6"> 31 <div className="panel"> 32 <div className="panel-body"> 33 {/*可切换的路由组件*/} 34 <Switch> 35 <Route path='/about' component={About}/> 36 <Route path='/home' component={Home}/> 37 {/*可切换的路由组件 默认显示about*/} 38 <Redirect to='/about'/> 39 </Switch> 40 </div> 41 </div> 42 </div> 43 </div> 44 </div> 45 ) 46 } 47 }
home.jsx:

1 import React, { Component } from 'react'; 2 export default class Home extends Component { 3 constructor(props) { 4 super(props); 5 this.state = { 6 } 7 } 8 render() { 9 10 return ( 11 <div> 12 HOME 13 </div> 14 15 ) 16 } 17 }
about.jsx:

1 import React, { Component } from 'react'; 2 export default class About extends Component { 3 constructor(props) { 4 super(props); 5 this.state = { 6 } 7 } 8 render() { 9 10 return ( 11 <div> 12 ABOUT 13 </div> 14 15 ) 16 } 17 }
index.css:

1 .activeClass { 2 color: red !important; 3 }
index.js:

1 import React from 'react'; 2 import ReactDOM from 'react-dom/client'; 3 import APP from './component/app.jsx'; 4 import { BrowserRouter, HashRouter } from 'react-router-dom'; 5 import './index.css' 6 const root = ReactDOM.createRoot(document.getElementById('root')); 7 root.render( 8 9 //需要用路由包裹整个应用 ,意思就是路由管理整个应用 10 <BrowserRouter> 11 <React.StrictMode> 12 <APP /> 13 </React.StrictMode> 14 </BrowserRouter> 15 ); 16 17 // If you want to start measuring performance in your app, pass a function 18 // to log results (for example: reportWebVitals(console.log)) 19 // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
包装组件:
1 import React, { Component } from 'react'; 2 import {NavLink} from 'react-router-dom'; 3 export default function MyNavLink(props) { 4 return <NavLink {...props} activeClassName="activeClass"/> 5 }
包装组件的使用:

1 import React, { Component } from 'react'; 2 import {Route, Switch, Redirect,NavLink} from 'react-router-dom' 3 import Home from '../views/home.jsx'; 4 import About from '../views/about.jsx'; 5 import MyNavLink from './myNavLink.jsx'; 6 export default class App extends Component { 7 constructor(props) { 8 super(props); 9 this.state = { 10 } 11 } 12 render() { 13 return ( 14 <div> 15 <div className="row"> 16 <div className="col-xs-offset-2 col-xs-8"> 17 <div className="page-header"> 18 <h2>React Router Demo</h2> 19 </div> 20 </div> 21 </div> 22 23 <div className="row"> 24 <div className="col-xs-2 col-xs-offset-2"> 25 <div className="list-group"> 26 {/*导航路由链接*/} 27 <MyNavLink className="list-group-item" to='/about'>About</MyNavLink> 28 <MyNavLink className="list-group-item" to='/home'>Home</MyNavLink> 29 </div> 30 </div> 31 <div className="col-xs-6"> 32 <div className="panel"> 33 <div className="panel-body"> 34 {/*可切换的路由组件*/} 35 <Switch> 36 <Route path='/about' component={About}/> 37 <Route path='/home' component={Home}/> 38 {/*可切换的路由组件 默认显示about*/} 39 <Redirect to='/about'/> 40 </Switch> 41 </div> 42 </div> 43 </div> 44 </div> 45 </div> 46 ) 47 } 48 }
嵌套路由:
/home 那么/home/news 就是嵌套路由;
demo修改:
效果:
步骤一:在views中添加路由组件news 和message
news:

1 import React, { Component } from 'react'; 2 export default class News extends Component { 3 constructor(props) { 4 super(props); 5 this.state = { 6 newsArray:[ 7 "news001", 8 "news002", 9 "news003" 10 ] 11 } 12 } 13 render() { 14 15 return ( 16 <ul>{this.state.newsArray.map((item,index)=><li key={index}>{item}</li>)}</ul> 17 ) 18 } 19 }
message:

1 import React, { Component } from 'react'; 2 export default class Message extends Component { 3 constructor(props) { 4 super(props); 5 this.state = { 6 msgArray:[ 7 ] 8 } 9 } 10 componentDidMount(){ 11 //模拟发送ajax请求异步获取数据 12 setTimeout(()=>{ 13 const msgArray = [ 14 {"id":1,"title":"msgArray001"}, 15 {"id":2,"title":"msgArray0012"}, 16 {"id":3,"title":"msgArray0013"} 17 ] 18 this.setState({msgArray}) 19 },1000) 20 } 21 render() { 22 23 return ( 24 <ul>{this.state.msgArray.map((item,index)=>(<li key={index}><a href='???'>{item.title}</a></li>))}</ul> 25 ) 26 } 27 }
步骤二:修改home.jsx:

1 import React, { Component } from 'react'; 2 import MyNavLink from '../component/myNavLink'; 3 import {Route, Switch,Redirect} from 'react-router-dom'; 4 import News from './news.jsx'; 5 import Message from './message.jsx'; 6 export default class Home extends Component { 7 constructor(props) { 8 super(props); 9 this.state = { 10 } 11 } 12 render() { 13 14 return ( 15 <div> 16 <h2>HOME ROUTE COMPONET </h2> 17 <div> 18 <ul className='nav nav-tabs'> 19 <li> 20 <MyNavLink to="/home/news">news</MyNavLink> 21 </li> 22 <li> 23 <MyNavLink to="/home/message">message</MyNavLink> 24 </li> 25 </ul> 26 <div> 27 <Switch> 28 <Route path="/home/news" component={News}/> 29 <Route path="/home/message" component={Message}/> 30 <Redirect to='/home/news'/> 31 </Switch> 32 </div> 33 </div> 34 </div> 35 36 ) 37 } 38 }
传参:
效果图:
添加一个message-detail:

1 import React from 'react' 2 3 const messageDetails = [ 4 {id: 1, title: 'Message001', content: '我爱你, 中国'}, 5 {id: 3, title: 'Message003', content: '我爱你, 老婆'}, 6 {id: 6, title: 'Message006', content: '我爱你, 孩子'}, 7 ] 8 9 export default function MessageDetail(props) { 10 11 const id = props.match.params.id 12 const md = messageDetails.find(md => md.id===id*1) 13 return ( 14 <ul> 15 <li>ID:{id}</li> 16 <li>TITLE: 3333</li> 17 <li>CONTENT: 444</li> 18 </ul> 19 ) 20 }
message.jsx,添加点击功能,动态显示详情

1 import React from 'react' 2 import {Link, Route} from 'react-router-dom' 3 import MessageDetail from "./message-detail" 4 5 export default class Message extends React.Component { 6 state = { 7 messages: [] 8 } 9 10 componentDidMount () { 11 // 模拟发送ajax请求 12 setTimeout(() => { 13 const data = [ 14 {id: 1, title: 'Message001'}, 15 {id: 3, title: 'Message003'}, 16 {id: 6, title: 'Message006'}, 17 ] 18 this.setState({ 19 messages: data 20 }) 21 }, 1000) 22 } 23 24 ShowDetail = (id) => { 25 this.props.history.push(`/home/message/${id}`) 26 } 27 28 ShowDetail2 = (id) => { 29 this.props.history.replace(`/home/message/${id}`) 30 } 31 32 back = () => { 33 this.props.history.goBack() 34 } 35 36 forward = () => { 37 this.props.history.goForward() 38 } 39 40 render () { 41 const path = this.props.match.path 42 43 return ( 44 <div> 45 <ul> 46 { 47 this.state.messages.map((m, index) => { 48 return ( 49 <li key={index}> 50 <Link to={`${path}/${m.id}`}>{m.title}</Link> 51 52 <button onClick={() => this.ShowDetail(m.id)}>查看详情(push)</button> 53 <button onClick={() => this.ShowDetail2(m.id)}>查看详情(replace)</button> 54 </li> 55 ) 56 }) 57 } 58 </ul> 59 <p> 60 <button onClick={this.back}>返回</button> 61 <button onClick={this.forward}>前进</button> 62 </p> 63 <hr/> 64 <Route path={`${path}/:id`} component={MessageDetail}></Route> 65 </div> 66 ) 67 } 68 }
路由点击刷新页面 直接刷新页面 页面跳转
1 //直接刷新 2 showDetail1(id){ 3 this.props.history.push("/home/message/messagedetail/"+id); 4 } 5 //直接刷新 6 showDetail2(id){ 7 this.props.history.replace("/home/message/messagedetail/"+id); 8 } 9 //前进 10 goForward(){ 11 this.props.history.goForward(); 12 } 13 //前进 14 goback(){ 15 this.props.history.goBack(); 16 } 17 //页面跳转 18 reqPage(){ 19 window.location='http://www.baidu.com'; 20 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!