当前位置: 首页 > news >正文

react笔记基础部分(组件生命周期路由)

注意点:

class是一个关键字, 类。 所以react 写class, 用classname ,会自动编译替换class

点击方法:

 <button onClick = {this.sendData}>给父元素传值</button>

常用的插件:

需要引入才能使用的:

 路由五兄弟import {BrowserRouter as Router, Link, Route, Redirect, Switch} from 'react-router-dom'

react-redux

npm install react-redux --save

初始配置 app页面

import React from 'react';
import logo from './logo.svg';
import './App.css';function App() {return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><p>Edit <code>src/App.js</code> and save to reload.</p><aclassName="App-link"href="https://reactjs.org"target="_blank"rel="noopener noreferrer">Learn React</a></header></div>);
}export default App;

1.react简介:

简介:React 构建用户界面的javascript库,主要用于构建按ui界面。 instagram,2013年开源。

特点:

  • 声明式的设计
  • 高效,采用虚拟DOM来实现DOM的渲染,最大限度的减少DOM的操作
  • 灵活,跟其他库灵活搭配使用
  • jsx, 俗称给你JS 里面写HTML, JavaSxript 语法的扩展。
  • 组件化,模块化。代码容易复用,大型项目非常喜欢react.(2016年前,vue还没有火之前)
  • 单项数据流/没有实现数据的双向绑定。 数据 --> 视图 --> 事件 --> 数据

2 使用 引入react

2.1 CDN:

只用于本地的学习和使用。 线上形目不能这样啊

可以通过 CDN 获得 React 和 ReactDOM 的 UMD 版本。

<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

2.2 脚手架

cnpm install -g create-React-app

# 全局安装"create-react-app"架构
$ npm install -g create-react-app# 创建脚手架项目
$ create-react-app my-app# 进入项目目录
$ cd my-app# 启动项目
$ npm starthttp://localhost:3000/执行npm start 时, 会自动编译dom,插入到src中的index.html,因为浏览器才不管你用了什么插件,他只会显示解析html正常的dom。

3. npm start 发生了什么 代码原理

入口文件:
1.网页入口文件放在 dist/index.html
2. react入口文件放在 src/index.js在package.json的script中新增命令
"scripts": {"dev": "cross-env NODE=dev"
}$ npm run build
# 等同于执行
$ node build.jsnpm start是npm run start  简写形式也就是说npm start=  node start.js 执行文件
npm run 查看当前项目的所有的https://blog.csdn.net/cuipengchong/article/details/73044737?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159479718919724811836533%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=159479718919724811836533&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v3~pc_rank_v3-1-73044737.pc_ecpm_v3_pc_rank_v3&utm_term=npm%E8%84%9A%E6%9C%AC+npm+scripts

npm脚本 npm scripts
概念: npm脚本指的是package.json中的scripts字段
npm允许在package.json文件里面,使用scripts字段定义脚本命令。
就像 node 中执行1.js 可以写成 node 1  一样"scripts": {"start": "react-scripts start","build": "react-scripts build","test": "react-scripts test","eject": "react-scripts eject"},scripts:{
"build":'node build.js'
}

----------------------分割线--------------------------

https://blog.csdn.net/qq_39956624/article/details/89352115?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159479854019195264540861%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=159479854019195264540861&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v3~pc_rank_v3-1-89352115.pc_ecpm_v3_pc_rank_v3&utm_term=react-scripts+start

在命令窗口输入的是npm start,而start调用的是

 package.json 中的"start": "react-scripts start",

代码会找到 node_modules里面的react-scripts 插件。查找 bin 文件 点开bin\react-scripts.js文件内容

 .concat(require.resolve('../scripts/' + script))从上面这话可以看出调用start时需要调用scripts/start.js,点开该文件:
  1. 打开config/paths.js,发现其实里面好多默认的配置都是写在该文件,可以通过修改改文件来实现自己文件的存放配置
  2. 点开webpack.config.dev.js,也会发现大量是曾相识的代码:
  3. 所以说我们以前通过手动配置的webpack.config.js的内容,react-scripts都已经帮我们做了,大大方便了我们的使用。

----------------------分割线--------------------------

npm的原理

npm 脚本的原理非常简单。每当执行npm run,就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令。因此,只要是 Shell(一般是 Bash)可以运行的命令,就可以写在 npm 脚本里面。

比较特别的是,npm run新建的这个 Shell,会将当前目录的node_modules/.bin子目录加入PATH变量,执行结束后,再将PATH变量恢复原样。

这意味着,当前目录的node_modules/.bin子目录里面的所有脚本,都可以直接用脚本名调用,而不必加上路径。比如,当前项目的依赖里面有 Mocha,只要直接写mocha test就可以了。

例如

“test”: “mocha test”
1
而不用写成下面这样。

“test”: “./node_modules/.bin/mocha test”

npm传参

向 npm 脚本传入参数,要使用–标明。

“lint”: “jshint **.js”
1
向上面的npm run lint命令传入参数,必须写成下面这样。

$ npm run lint – --reporter checkstyle > checkstyle.xml

  "scripts": {"start": "react-scripts start","build": "react-scripts build","test": "react-scripts test --env=jsdom","eject": "react-scripts eject"}里面是一个个键值对,eject对应react-scripts eject,当我们执行 npm eject的命令是,npm会找到 package.json中的scripts对象中eject对相应值,然后在执行。

react文档结构

myreact |--node_modules   项目依赖包|-- public       公共开放资源  静态资源|     |--favicon.ico |     | --index.html      相当于vue的 id ='app',等待放置编译好的dom|     | --logo.png         react图表|     | --mainifest.json  chrome扩展文件|     | --robots.txt       告诉爬虫,不要爬我的网页。一般没用。||-- src|     |--App.css|     | --APP.js    app组件|     | --App.test.js|     | --index.css|     | --index.js   入口文件|     | --logo.svg|     | --servceWorker.js|     | --setupTests.js|| --.gittignore    git 忽略配置文件| --package.json    包配置信息| --package-lock.json  包配置信息版本固定| --README.md         文档说明   webpack.config.js -  node_modules 

关于import…form…

index.js主文件为例

import '../gen'  // 不支持根目录下的相对引入文件import './1.js'
// require ('./1.js')  这两种引入方式,都可以打包进去。自己的静态图片,官方希望你都放在src中,不要访问外边的资源。img js 新建目录存放。

4 react 组件原理

这是一个组件

App.js

function App() {return (<div className="App">我是内容</div>);
}

这是

index.js 引用的页面

import App from './App';  1.引入ReactDOM.render(  2.  调用一个方法// <React.StrictMode>  严格模式<App />,// </React.StrictMode>,document.getElementById('root')
);

测试1:函数式组件渲染

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';// ReactDOM.render(
//     <App />,
//   document.getElementById('root')
// );// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister(); //缓存页面生成时间,1s刷线一次。
function clock(){let time = new Date().toLocaleTimeString();
let element = <div>{time}</div>;
let root =  document.getElementById('root');
ReactDOM.render(element,root);
}setInterval(clock,1000 )

测试2:组件传参

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';function Clock(props) {console.log(props);  //2.props  { data1:4,data2:40 }传入的值,会放到形参中。return ( <div > {  props.data1}</div>)}function run(){ReactDOM.render(<Clock data1 = { 4} data2 = { 40}/>, //1. 标签首位字母大写document.getElementById('root'));}setInterval(run, 1000)// let time = new Date().toLocaleTimeString(); //不同点: props

5 Jsx 表达式

优点:

  • JSX执行更快,编辑为JavsScript 代码是进行优化。

  • 类型更安全,编译过程如果出错就不能编译,及时发现错误。

  • JSX编写模板更加简单快速(不要更vue比,当时VUE还没出来)

    注意点:*

    1. jsx必须要有根节点
    2. 正常的普通HTML元素要小写,如果是大写,默认认为是组件。

    jsx表达式:

    1. 有HTML元素构成
    2. 中间使用变量 用 { }
    3. {} 中可以使用表达式 可以使用 jsx对象,
    4. 属性和html内容一样都是用{} 来插入内容。
    5. {} 一个只能放一个表达式 但可以放入嵌套数据结构

{ }

1.里放置表达式
案例1var msg = '姓名';
var time = '00:00'var dom = (<div><div> {msg + time}</div></div>)ReactDOM.render(dom,document.getElementById('root'))
2.案例2 :三元运算法

{ } 里面可以放标签和单元判断

var msg = '发烧';
var dom = (<div><div> {msg == '发烧'?  <button>隔离</button> :'没事啊'}</div></div>)ReactDOM.render(dom,document.getElementById('root'))
3. 混搭

{插值中放入标签,三元判断等}

var element4 = '我是混搭';
orvar element4 =<div><span> 我是模板混搭 <sapn/> </div><div> {msg == '发烧'?  <button>隔离</button> :element4}</div>dom变成了什么:     
element4:  dom,在这里已经变成了 一个对象。有属性和  _proto_       

4 引入css

App.css

.lyx{color: red;
}
import引入 css 文件

比如当前页 index.js

直接引入
import './App.css';注意点: 
<div> {msg == '发烧'?  <div className='lyx'>隔离</div> :'没事啊'}</div>
加clsss  写法注意 className,
测试: 直接写 calss='lyx' 也可以。但是浏览器里会提示错误。
变量js方式 css
let  styledemo = {background:"skyblue",borderBottom:"4px solid red",  //需要驼峰"fontsize":'40px'    //要么加引号,不用驼峰
}let element = (
<div><h1 style = { styledemo} >我是 react style 的jsx变量写法</h1>
</div>
)ReactDOM.render(element,document.getElementById('root'))* 不能写行内样式,报错

添加 自定义 class

let classstr = 'redbg'let element = (
<div><h1 style = { styledemo} className = {'abc '+ classstr}>我是 react style 的jsx变量写法</h1>
</div>
)变量类名 和自定义类名, abc 字符串类型,记得一定留出空格。否则编译出来会合并
className = {'abc '+ classstr} 
1. 同时添加多个class

jsx标签中,不能加多个class, 需要处理一下,把class合并在写入。

let classstr = ["redbg","redbg2"].join(" ") //合并字符串当成一个变量放入插值中let element = (
<div><h1 style = { styledemo} className = {classstr}>我是 react style 的jsx变量写法</h1>
</div>
)

5. jsx中加注释

let element = (
<div>{/* jsx的注释写法*/}<h1 style = { styledemo} className = {classstr}>我是 react style </h1>
</div>
)

6. 组件的两种方式

6.1编程式 函数里(静态组件)

function Childdom(){let title = <h2> 我是副标题</h2>let weather = '下雨'
//条件判断let isgo = weather === '下雨' ? "下雨不出门" : "不下雨了,不出门" return(<div>  {title} <span>天气怎么样:{isgo}</span></div>)}ReactDOM.render(<Childdom/>,document.getElementById('root'))

另一种传值形式,也是编程式 (组件传值)

function Childdom(props){let title = <h2> 我是副标题</h2>
console.log(props);  // props接受传值return(<div>  {title} <span>天气怎么样:{props.weather}    // 使用传值</span></div>)}ReactDOM.render(<Childdom weather = '来自组件标签'/>,   //标签传值document.getElementById('root'))

6.2 类组件 class声明(动态组件)

index.js

class HelloWorld extends React.Component{render() {                //render这个名字不能动。不是随意取得。是一个规定的方法return(<div>  我是类组件定义</div>)}
}ReactDOM.render(<HelloWorld/>,document.getElementById('root'))

组件

类组件传参-见序号8

  class Ant extends React.Component {constructor(props) {super(props)this.state = {}}render() {return ( <div > </div>)}onChange(page,pagesize){}}export default Ant

6.3组件嵌套(复合组件)

class Children extends React.Component{render() {               return(<div>  <div> 我是Children</div></div>)}}class HelloWorld extends React.Component{render() {              return(<div>  <div> 我是HelloWorld</div><Children/>    //helloworld组件中,引入children组件</div>)}}ReactDOM.render(<HelloWorld  weather = '出太阳'/>,document.getElementById('root'))

结论:两种组件适用场景

函数式: 如果静态,或者就 传一个值,使用函数式

类组件:有触发事件,交互和操作

7. 关键方法:ReactDOM.rende

ReactDOM.render(组件, 挂载点root)

组件这一块,样式可以多种。

第一种 : function ( ) 函数形式

function Childdom(){let title = <h2> 我是副标题</h2>let weather = '下雨'
//条件判断let isgo = weather === '下雨' ? "下雨不出门" : "不下雨了,不出门" return(<div>  {title} <span>天气怎么样:{isgo}</span></div>)}ReactDOM.render(<Childdom/>,document.getElementById('root'))

第二种 : dom形式

其实实质一样,和return() 函数式一样。let element = (
<div><h1 style = { styledemo} >我是 react style 的jsx变量写法</h1>
</div>
)ReactDOM.render(element,document.getElementById('root'))

8 传值

function Childdom(props){let title = <h2> 我是副标题</h2>
console.log(props);  // props接受传值return(<div>  {title} <span>天气怎么样:{props.weather}    // 使用传值</span></div>)}ReactDOM.render(<Childdom weather = '来自组件标签'/>,   //标签传值document.getElementById('root'))

8 传值(类组件传参)

8.1 自己的标签 ——> 传向自己的组件

class Children extends React.Component{render() {     console.log(this);   //这里的this指的是Children组件 this里propos里有标签传值return(<div>  <div> 我是Children</div></div>)}}class HelloWorld extends React.Component{render() {       console.log(this);   //这里的this指的是HelloWorld组件 this里propos里有标签传值return(<div>  <div> 我是HelloWorld</div><Children name = '我是children的数据' />   </div>)}}ReactDOM.render(<HelloWorld  weather = '我是父组件穿的值'/>,document.getElementById('root'))

8.2 父组件 标签的数据–> 子组件 传递

class Children extends React.Component{render() {     // console.log(this);   //这里的this指的是Children组件 this里propos里有标签传值return(<div>  <div> 我是Children</div></div>)}}class HelloWorld extends React.Component{render() {       console.log(this);   //这里的this指的是HelloWorld组件 this里propos里有标签传值return(<div>  <div> 我是HelloWorld</div><Children name = '我是children的数据' weather = {this.props.weather}/>   </div>)}}ReactDOM.render(<HelloWorld  weather = '我是父组件穿的值'/>,document.getElementById('root'))

9 react状态 管理(修改数据)

9.1 引入例子

class Clock extends React.Component {constructor(props) {super(props)this.state = {time: new Date().toLocaleTimeString()}}render() {// console.log(1);  变了return ( <div ><h1> 当前时间: {this.state.time}</h1></div>)}
}setInterval(()=>{// console.log(0);  变了
ReactDOM.render(<Clock/> ,document.getElementById('root')
);},1000)计时器1s渲染一次,我们发现页面没动。手动刷新才会变。
通过打印我们发现,render, 计时器都在变,就是页面不变。
原因是: render方法 每隔1s渲染, <Clock/> 直接加载缓存。所以没变。

既然render变了,那就直接修改state.time的值。

 做如下修改
render() {// console.log(0);this.state.time = new Date().toLocaleTimeString()return ( <div ><h1> 当前时间: {this.state.time}</h1></div>)}保存后,页面动了。 

但是这不是官方推荐的方法。

9.2 正确修改方法 setState( )

class Clock extends React.Component {平级1constructor(props) {super(props)this.state = {time: new Date().toLocaleTimeString()}}平级2render() {return ( <div ><h1> 当前时间: {this.state.time}</h1></div>)}平级3componentDidMount(){   componentDidMount是声明周期函数,加载完页面开始执行。setInterval(() => {this.setState({time : new Date().toLocaleTimeString()})}, 1000);}
}渲染函数
ReactDOM.render(<Clock/> ,document.getElementById('root')
);1.采用官方方法的作用: 修改数据,并自动渲染页面;
2. setstate方法,修改数据后,不会立即更改dom,而是等函数执行完了以后,统一对比虚拟dom,再做修改,提升性能。 小程序也是借鉴这样。

总结: react 类组件中,自己的state数据,和点击事件,和渲染dom,都放到自己的内部,this下挂载。

9.3 案例:

实现两个按钮接环内容
import React from 'react';
import ReactDOM from 'react-dom';class Clock extends React.Component {constructor(props) {super(props)this.state = {c1:"content active",c2:"content "}this.clickEvent = this.clickEvent.bind(this)// 把方法挂载到this组件下}clickEvent(e){console.log(this);// console.log(e.target.dataset);// console.log(e.target.dataset.index);let index = e.target.dataset.indexif(index == '1'){this.setState({c1:"content active",c2:"content "})}else{this.setState({c1:"content ",c2:"content  active"})}}render() {return ( <div ><button data-index = '1' onClick = {this. clickEvent }>内容一</button>  <button data-index = '2' onClick = {this. clickEvent }>内容二</button>  <div className = {this.state.c1}><h1>内容一</h1>   </div><div className = {this.state.c2}><h1>内容二</h1>   </div></div>)}}ReactDOM.render(<Clock/> ,document.getElementById('root')
);案例里:用到了几个点
e 事件对象
DOM data自定义属性和使用
bing(this) 改变this指向

10 传值

10.1 父传子

父传子数据,单向流动,不能子传父。 props的传值,可以是任意的类型。

props可以设置默认值。

HelloMessage.dafaultProps = { name:‘tom’ ,msg:‘hellowlorld’ }

注意:prop可以传递函数,可以传递父元素的函数。也就是说,可以修改父元素的state数据,从而道道传递 数据 的效果和目的。

import React from 'react';
import ReactDOM from 'react-dom';class Clock extends React.Component {constructor(props) {super(props)this.state = {isshow:true}this.changeshow = this.changeshow.bind(this)}changeshow(){this.setState({isshow:!this.state.isshow})}render() {return ( <div ><button onClick = {this.changeshow}>控制子元素显示</button><Children  isactive = {this.state.isshow}/></div>)}}class Children extends React.Component {constructor(props) {super(props)this.state = {}}render() {let strclass = null;if(this.props.isactive){strclass = 'active'}else{strclass = ""}return ( <div ><span className = {'content '+ strclass}>i is children</span></div>)}}ReactDOM.render(<Clock/> ,document.getElementById('root')
);总结: 父元素states准备一个变量,在自己函数内,子组件标签,输入值, 子组件接受props接受使用。

10 2 子传父

方法: 调用父元素的函数,从而操作元素的数据。

import React from 'react';
import ReactDOM from 'react-dom';class Clock extends React.Component {constructor(props) {super(props)this.state = {childData:null  //默认是null页面不会显示,只有 有数据才会显示}}render() {return ( <div ><h1>子元素传递给复原的数据 {this.state.childData} </h1><Children setChildDate = {this.setChildDate} />       //1. 变量也可以是个方法</div>)}setChildDate = (a)=>{  //3.传递形参,进行修改this.setState({childData:a})}
}class Children extends React.Component {constructor(props) {super(props)this.state = {msg:'helloworld'}}sendData = ()=>{this.props.setChildDate(this.state.msg) // 2. 你要记住,标签传参,实例中props中就会有值。}render() {return ( <div ><button onClick = {this.sendData}>给父元素传值</button></div>)}
}ReactDOM.render(<Clock/> ,document.getElementById('root'));简写形式: 既然children标签传入, children的props中就会挂载。那么就可以这样写:<button onClick = {()=> {this.props.setChildDate('我是子组件调用props')}}>给父元素传值</button> ,这样也是可以调用的。   匿名的箭头函数,this.不变。

11 reach 事件语法

特点:
  1. 事件的 click 写法,驼峰命名法。2. { } 传入一个函数,而不是一个字符串.
<button onClick = {this.sendData}>给父元素传值</button>
处理过的事件对象e 和 阻止默认
import React from 'react';
import ReactDOM from 'react-dom';class Clock extends React.Component {constructor(props) {super(props)this.state = {}}render() {return ( <div ><div onClick = { this.parentEvent } data-index = 'lyx'>查看事件对象e</div></div>)}parentEvent = (e)=>{console.log( e) //注意:这个事件都想是react 处理过的。如果想拿到具体值,直接输出 e.target.dataset.index}
}ReactDOM.render(<Clock/> ,document.getElementById('root'));

阻止默认

  组件: 
form 有默认提交事件,同步的。如果想自定义ajax异步请求,就阻止默认。
render() {return ( <div ><form action="https://www.baidu.com" method="get"><button onClick = {this.parentEvent}>提交</button></form></div>)}方法1parentEvent = (e)=>{console.log(e ) //注意:想知道e中有什么方法,打印出来一个一个查一下。 e.preventDefault()}方法2form中的提交按钮,submit修改为button , 不设置默认submit.<button onClick = {this.parentEvent} type = 'submit'>提交</button>
传参,同时保留事件对象
  render() {return ( <div ><form action="https://www.baidu.com" method="get"><button onClick = {(e)=>{this.parentEvent(e, "0")}} type = 'button'>提交</button></form></div>)}parentEvent = (e,a)=>{console.log(e ,a) //注意:想知道e中有什么方法,打印出来一个一个查一下。 // e.preventDefault()}
注意:
<button onClick = {()=>{this.parentEvent("0")}} type = 'button'>提交这样的话,传值,会把e替换。
不适用箭头函数传递多个参数

箭头函数与function函数的区别,就是this. 所以bind,修改一下this.指向。

function, 内部的this,就是它自己,谁调用,指向谁。

使用箭头函数
<button onClick = {()=>{this.parentEvent("0")}} type = 'button'>提交</button>
不适用箭头函数<button onClick = {function(e){this.parentEvent('msg:helloworld',e)}.bind(this)} type = 'button'>提交</button>parentEvent = (e,a)=>{console.log(e ,a)  //形参,按位置传递 }

12 条件渲染

React 中条件渲染即和JavaScript 中,条件运算,如if else 三元运算符等等。

1 直接通过条件渲染你返回要渲染的jsx对象。

2 通过条件运算得出jsx对象,在将jsx对象渲染到模板中。

第一种
import React from 'react';
import ReactDOM from 'react-dom';function User(props){return ( <h1>我登陆了</h1>)
}function UserNologin(props){return ( <h1>请登录</h1>)
}class Clock extends React.Component {constructor(props) {super(props)this.state = {islogin:false}}render() {if(this.state.islogin){return(<User></User>)}else{return(<UserNologin></UserNologin>)}}
}ReactDOM.render(<Clock/> ,document.getElementById('root'));
通过控制islogin, 达到页面变化。
第二种
import React from 'react';
import ReactDOM from 'react-dom';function User(props){return ( <h1>我登陆了</h1>)
}function UserNologin(props){return ( <h1>请登录</h1>)
}class Clock extends React.Component {constructor(props) {super(props)this.state = {islogin:false}}render() {let element = nullif(this.state.islogin){element =( <User></User> )}else{element =  (<UserNologin></UserNologin>)}return(  <div> <div>这是头部</div>{element}<div>这是尾部</div></div>)}
}ReactDOM.render(<Clock/> ,document.getElementById('root'));//可以发现, react 就是你想要什么样的逻辑,自己动手。
第三种: 三元运算符形式
render() {return(  <div> <div>这是头部</div>{this.state.islogin ?( <User></User> ):  (<UserNologin></UserNologin>)}<div>这是尾部</div></div>)}

13 列表渲染

将列表内容拼装成数组放置到模板中。

将数据封装成数组的JSX对象。

import React from 'react';
import ReactDOM from 'react-dom';let arr = ['小明','小黑','小白']class Clock extends React.Component {constructor(props) {super(props)this.state = {islogin:true}}render() {return(  <div> <ul>{arr}</ul></div>)}
}ReactDOM.render(<Clock/> ,document.getElementById('root'));渲染结果:
<ul>小明
小黑
小白
</ul>

改造:

let arr = ['小明','小黑','小白']我们设置一个jsx数组let arrhtml = [<li>小明</li>,<li>小黑</li>,<li>小白</li>]render() {return(  <div> <ul>{arrhtml}</ul></div>)}渲染结果: 完美
<ul><li>小明</li><li>小黑</li><li>小白</li></ul>

列表循环jsx。

import React from 'react';
import ReactDOM from 'react-dom';class Clock extends React.Component {constructor(props) {super(props)this.state = {listarr : [{title:'第一个标题1',cont:'我是内容1'},{title:'第一个标题2',cont:'我是内容2'}]}}render() {let listArr = []console.log(0);for(let i = 0 ;i < this.state.listarr.length;i++){var  item =  (<li><h3>{this.state.listarr[i].title}</h3><p>{this.state.listarr[i].cont}</p></li>)listArr.push(item) }return(  <div> <ul>{listArr}</ul></div>)}
}ReactDOM.render(<Clock/> ,document.getElementById('root'));

代码简化 map循环

使用数组的map方法,对每一项数据按照JSX的形式加工,最终得到,每一项都是JSX对象的数组,在将数组渲染到模板中去。

  render() {let listArr = this.state.listarr.map((itme,index)=>{return(<div key = {index} className = {'item'+index}><li>{itme.title}</li><p>{itme.cont}</p></div>)})return(  <div> <ul>{listArr}</ul></div>)}

14 肺炎列表渲染案例

总结: render里面可以写js逻辑,完全就是原生js写的。

这个暂用:

import React from 'react';
import ReactDOM from 'react-dom';var data = require('./1.json')
console.log(data);class Clock extends React.Component {constructor(props) {super(props)this.state = {listarr : [{title:'第一个标题1',cont:'我是内容1'},{title:'第一个标题2',cont:'我是内容2'}]}}render() {let listArr = this.state.listarr.map((itme,index)=>{return(<div key = {index} className = {'item'+index}><li>{itme.title}</li><p>{itme.cont}</p></div>)})return(  <div> <ul>{listArr}</ul></div>)}
}ReactDOM.render(<Clock/> ,document.getElementById('root'));

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

15 生命周期函数

https://blog.csdn.net/qq_38719039/article/details/82378434

img

生命周期: 针对组件总渲染到销毁的过程。期间有可以调用的函数,又叫钩子函数

生命周期的3个状态。

Mounting: 将组件插入到dom中。

Updating: 将数据更新到dom中。

Unmounting: 将组件移除Dom中。

生命周期中的钩子函数(方法,事件)

componentWillMount: 组件将要渲染 -> AJAX,添加动画前的类

componentDidMount : 组件渲染完毕 -> 添加动画 添加echart 就在这里 获取windown

compontWillReceiveProps:组件将要接受props数据 ->查看props的数据是什么

componentWillReceiveProps: 组件接收到新的state或者props ->判断是否更新。 返回布尔值。

CompontWillUpdate : 组件将要更新

componentDidUpdate :组件已经更新

componentWillUnmount : 组件 将要卸载

// 已经更正

1.constructor(props, context)

  • 构造函数,在创建组件的时候调用一次。

2.componentWillMount()

  • 在组件render之前立即调用

Tip1: 不建议在此请求数据,由于请求数据接口一般都是异步,这时候render已经被执行,建议在componentDidMount 数据

Tip2: 如果在服务端渲染,该钩子函数将被调用两次,一次服务端,一次浏览器端,而componentDidMount函数只会在浏览器端请求一次

Tip3: 在taro构建的小程序里对应的生命周期是 onLoad。

3…componentDidMount()

  • 所有的组件(包括子组件)在render执行完之后立即调用,并且只会被调用一次。

Tip: 建议在此请求数据

4. componentWillReceiveProps(nextProps)

  • 在props被改变时被触发,初始化render时不调用。
  • 旧的属性还是可以通过this.props来获取,在这里通过调用this.setState()来更新你的组件状态。

Tip1: 某些情况下,props没变也会触发该钩子函数,需要在方法里手动判断一下this.props和nextProps是否相同,不相同了才执行我的更新方法。

Tip2:该函数一般用来更新依赖props的状态

5. shouldComponentUpdate(nextProps, nextState)

  • 发生重渲染时,在render()函数调用前被调用的函数,当函数返回false时候,阻止接下来的render()函数的调用,阻止组件重渲染,而返回true时,组件照常重渲染。
  • 该方法并不会在初始化渲染或当使用forceUpdate()时被调用。

6.componentWillUpdate(nextProps, nextState)

  • shouldComponentUpdate返回true或者调用forceUpdate之后,componentWillUpdate会被调用。

7. getSnapshotBeforeUpdate(prevProps, prevState)

  • 该函数在最新的渲染输出提交给DOM前将会立即调用。它让你的组件能在当前的值可能要改变前获得它们。这一生命周期返回的任何值将会 作为参数被传递给componentDidUpdate()。

8. componentDidUpdate(prevProps, prevState)

  • 除了首次render之后调用componentDidMount,其它render结束之后都是调用componentDidUpdate。

9.componentWillUnmount()

  • 在组件被卸载和销毁之前立刻调用。可以在该方法里处理任何必要的清理工作,例如解绑定时器,取消网络请求,清理任何在componentDidMount环节创建的DOM元素。

10.componentDidCatch(error, info)

  • 该函数称为错误边界,捕捉发生在子组件树中任意地方的JavaScript错误,打印错误日志,并且显示回退的用户界面。

Tip:错误边界只捕捉树中发生在它们之下组件里的错误。一个错误边界并不能捕捉它自己内部的错误。

11.render()

  • render是一个React组件所必不可少的核心函数(上面的其它函数都不是必须的)。

Tip:记住,不要在render里面修改state。

12.React组件更新路径

在线测试:http://wximg.gtimg.com/shake_tv/test/lifeCycle2113.html

钩子函数位置 ( 完整code)

import React from 'react';
import ReactDOM from 'react-dom';class Clock extends React.Component {constructor(props) {super(props)this.state = {msg:'hello world'}}// componentWillMount   组件将要渲染
componentWillMount(){console.log(' CompontWillMount: 组件将要渲染')
}// CompontDidMount: 组件渲染完毕
CompontDidMount(){console.log(' CompontDidMount: 组件渲染完毕')
}
// compontWillReceiveProps:组件将要接受props数据
compontWillReceiveProps(){console.log(' compontWillReceiveProps:组件将要接受props数据')
}
// componentWillReceiveProps : 组件接收到新的state或者props,判断是否更新。 返回布尔值。
componentWillReceiveProps(){console.log(' componentWillReceiveProps: 组件接收到新的state或者props')
}// CompontWillUpdate: 组件将要更新
CompontWillUpdate(){console.log(' CompontWillUpdate: 组件将要更新')
}// componentDidUpdate组件已经更新componentDidUpdate(){console.log(' ComponentDidUpdate:组件已经更新')
}// componentWillUnmount : 组件 将要卸载componentWillUnmount(){console.log(' componentWillUnmount : 组件 将要卸载')
}render(){return(  <div> </div>)}
}ReactDOM.render(<Clock/>,document.getElementById('root'));总结: 钩子函数在构造函数内,

测试:使用上面的code, 测试,页面打开的时候:显示 CompontWillMount:组件将要渲染

点击修改数据的时候: ComponentDidUpdate:组件已经更新。 其他的等待测试。


补充: 组件的成员和他们的this

import React from 'react';
import ReactDOM from 'react-dom';class Clock extends React.Component {// ----------------------分割线----------------------------------------------constructor(props) {super(props)this.state = {msg:'hello world'}console.log(this);// this指向实例this.clickEvent = this.clickEvent.bind(this)// 把方法挂载到this组件下}// ----------------------分割线----------------------------------------------render(){console.log(this); // this指向实例return(  <div> {/* <button onClick = {this.clickEvent}>点击修改数据</button> */}<button onClick = {this.clickEvent.bind(this)}>点击修改数据</button><span>{this.state.msg}</span></div>)}// ----------------------分割线----------------------------------------------clickEvent(e){
//没有bing,this= undefind ;加上bing现在this已经指向实例.才能使用实例上的方法。this.setstateconsole.log(this); // this.setState({//   msg:'修改内容'// })}
// ----------------------分割线----------------------------------------------} // 组件的下括号//  上图表明: 组建中三个部分: constructor   render   dom的clickEvent  三个是并列。
// 正由于是并列的,所以this不统一。  
//  所以只要保证this是统一实例。 button可以这两中写法。看上图ReactDOM.render(<Clock/>,document.getElementById('root'));

案例: 疫情 中国地图 引入echart

npm install echartsimport React from 'react';
import ReactDOM from 'react-dom'; //var echarts = require('echarts');//该中引入方式默认实在node_modules 中 npm安装class Clock extends React.Component {
// -----------------分割线---------------------------constructor(props) {super(props)this.state = {msg:'hello world',my_series_data:[5, 20, 36, 10],my_xAxis_data:["衬衫", "羊毛衫", "雪纺衫", "没有裤子"]}}
// -----------------分割线---------------------------componentDidMount() {console.log(this); //指向实例// 基于准备好的dom,初始化echarts实例var myChart = echarts.init(document.getElementById('main'));// 绘制图表let shuju ={title: { text: 'ECharts 入门示例' },tooltip: {},xAxis: {data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]},yAxis: {},series: [{name: '销量',type: 'bar',data: [5, 20, 36, 10, 10, 20]}]}//  拦截原始数据,用自己的数据替换一下console.log(shuju);shuju.series[0].data = this.state.my_series_datashuju.xAxis.data = this.state.my_xAxis_datamyChart.setOption(shuju);  //渲染图表}
// -----------------分割线---------------------------render(){return(  <div className="myecahrt"> <h1>我的creact 图表</h1><div id="main" style={{ width: 400, height: 400 }}></div></div>)}
// -----------------分割线---------------------------
} ReactDOM.render(<Clock/>,document.getElementById('root'));// 总结: npm 引入 js  ;data中准备好自己的数据; render中准备好挂载点,// ;钩子函数,组件dom渲染上后,寻找dom,初始化echart方法,在渲染前替换自己的的数据。

引入echar map地图

import React from 'react';
import ReactDOM from 'react-dom'; import echarts from 'echarts'import 'echarts/map/js/china';// require ('echarts/map/js/china')// import ('echarts/map/js/china');  采用该种方法引入 报错 如下:
// Expected an assignment or function call and instead 
// saw an expression  no-unused-expressionsclass App extends React.Component {// export class App extends Component {constructor(props) {super(props);this.state = {data:[{name: "南海诸岛",value: 0},{name: '北京',value: 20},{name: '天津',value: 30},{name: '上海',value: 229},{name: '重庆',value: 59},{name: '河北',value: 190},{name: '河南',value: 300},{name: '云南',value: 20},{name: '辽宁',value: 40},{name: '黑龙江',value: 37},{name: '湖南',value: 180},{name: '安徽',value: 0},{name: '山东',value: 67},{name: '新疆',value: 10},{name: '江苏',value: 0},{name: '浙江',value: 0},{name: '江西',value: 0},{name: '湖北',value: 0},{name: '广西',value: 0},{name: '甘肃',value: 0},{name: '山西',value: 0},{name: '内蒙古',value: 89},{name: '陕西',value: 0},{name: '吉林',value: 0},{name: '福建',value: 66},{name: '贵州',value: 0},{name: '广东',value: 330},{name: '青海',value: 0},{name: '西藏',value: 74},{name: '四川',value: 601},{name: '宁夏',value: 0},{name: '海南',value: 45},{name: '台湾',value: 23},{name: '香港',value: 0},{name: '澳门',value: 0}]}}componentDidMount(){this.initMap();}//初始化地图initMap = () => {let myChart = echarts.init(document.getElementById('myMap'));let option = {tooltip: {formatter: function (e , t, n) {return e.seriesName + "<br />" + e.name + ":" + e.value}},visualMap: {min: 0,max: 1000,right: 26,bottom: 40,showLabel: !0,pieces: [{gt: 500,label: "500家以上",color: "#ED5351"}, {gte: 200,lte: 500,label: "201-500家",color: "#3B5A97"}, {gte: 100,lt: 200,label: "101-200家",color: "#59D9A5"}, {gt: 51,lte: 100,label: "51-100家",color: "#F6C021"}, {label: "1-50家",gt: 0,lte: 50,color: "#6DCAEC"}],show: !0},geo: {map: "china",roam: !1,scaleLimit: {min: 1,max: 2},zoom: 1.13,layoutCenter: ['30%', '30%'],                //地图中心在屏幕中的位置label: {normal: {show: !0,fontSize: "14",color: "rgba(0,0,0,0.7)"}},itemStyle: {normal: {borderColor: "rgba(0, 0, 0, 0.2)"},emphasis: {areaColor: "#F5DEB3",shadowOffsetX: 0,shadowOffsetY: 0,borderWidth: 0}}},series: [{name: "客户统计",type: "map",geoIndex: 0,data: this.state.data,areaColor: '#0FB8F0'}]};myChart.setOption(option);window.addEventListener("resize", function () {myChart.resize();});}render(){return (<div className="map"><div id="myMap" style = {{"height":"800px"}} ></div></div>)}
}ReactDOM.render(<App/>,document.getElementById('root'));

16 表单和图表 seach案例

涉及点: 父子传值, 常规dom渲染理解为jsx对象,map循环,

子页面的绑定事件,模块导出。

index.js

import React from 'react';
import ReactDOM from 'react-dom';import Search from './component/search';class Clock extends React.Component {constructor(props) {super(props)this.state = {listarr : [{id:1,title:'第一个标题1',cont:'我是内容1'},{id:2,title:'第一个标题2',cont:'我是内容2'}]}}render() {let listArr = this.state.listarr.map((itme,index)=>{return(<div key = {index} className = {'item'+index}><li>{itme.title}</li><p>{itme.cont}</p></div>)})return(  <div> <Search alldata = {this.state.listarr}></Search><ul>{listArr}</ul></div>)}
}ReactDOM.render(<Clock/> ,document.getElementById('root'));

search.js页面

import React from 'react';class Search extends React.Component {constructor(props) {super(props)this.state = {value:undefined,result:":查询结果"}}render() {return(   <div className= 'search'> <input type="text" onKeyDown = {this.serchEvent.bind(this)}  placeholder='请输入' //   value = {this.state.value}//   onChange = {this.chengeEvent.bind(this)}/><div><h2>查询结果</h2><div>这是查询结果 search{this.state.result}</div></div></div>)}serchEvent(e){// let a = this.props.alldata[e.target.value]if(e.keyCode === 13){if(this.props.alldata[e.target.value]){this.setState({result :(<h2>{this.props.alldata[e.target.value].cont}</h2> )})}else{this.setState({result :(<h2>只有两条数据啊</h2> )})}  }}chengeEvent(e){// console.log(e.target.value);this.setState({// value:e.target.value})}}export default Search;

17 React 的ajax案例

Ajax + React + axios + Express 案例

17-1 服务端

环境准备

常规准备
1. npm init    生成package.son文件 记录以来信息
2. npm i webpack --save-dev   安装webpack  生成node_modules 打包依赖文件  18M大小
项目使用的插件和框架准备3.npm install express --save      --save是保存版本信息。其中主要封装的是http。   
4.  npm install --global  n         odemon热加载

新建index.js

// 0 安装 
// 1 引包
const express = require('express')  // 引包const app = express() //调用
// app.get('/', (req, res) => res.send('Hello World!'))  //res.send 这里 变了app.get('/', function(req, res){res.send('Hello World!')
})// 再写一个
app.get('/app', function(req, res){res.send('您好我是:app')
})// app.listen(3000, () => console.log('running...'))
app.listen(3000, function(){console.log('running...')
})

启动服务:

cmd 命令行中输入: nodemon app.js ok项目启动 浏览器打开 
基本的服务搭建完成

项目使用的插件

axios

npm install axios --save注意引入index.js

asynchronous 异步

疫情接口( 仅学习使用)

https://voice.baidu.com/newpneumonia/get?target=trend&isCaseIn=0&stage=publish&callback=jsonp_1595142630965_83751(jsonp格式转换json格式)

app.get('/api', async function(req, res){//解决跨域问题
//   res.json({name:'lyx'})
let url = 'https://voice.baidu.com/newpneumonia/get?target=trend&isCaseIn=0&stage=publish&callback=jsonp_1595142630965_83751'let resdata = await axios.get(url)let data =resdata.data;// res.send(data)res.json(data) })打开页面,可以看到数据

17-2 前端

  1. 初始化react项目包

    包含操作: npm init /npm webpack / 外加两个文件夹/ md说明文档/ 就是一个快捷操作

 create-react-app reactapp
  1. axios 前端安装 axiox 都自己的node_modules
npm install axios --save注意引入app.js
const axios = require('axios')  

前端访问疫情接口:

		  async	componentWillMount(){console.log(0)// axios.get()
let url = 'https://voice.baidu.com/newpneumonia/get?target=trend&isCaseIn=0&stage=publish&callback=jsonp_1595142630965_83751'let resdata = await axios.get(url)let data =resdata.data;console.log(data);}

跨域: 解决

 这就是搭建后台的原因:async	 componentWillMount(){let url = 'http://localhost:4000/api'let resdata = await axios.get(url)let data_ = resdata.data.featuresthis.setState({Newslistdata:data_})console.log('前台返回第一层数据',data_);	 }

页面结构

  1. 这里的4个tab切换,不是路由,而是在主页面中引入了4个子页面。 放在主页面的cont中,flex横向排列。

    点击tab,控制父盒子的定位左侧移动。

    2.实现点击tab bar动画: state准备:tabIndex,条件渲染tab,tab 设置点击事件,this.setState({})方式修改tabIndex,dom会根据数据变化,自动重新渲染。 4个tab移动意识一样。

    1. new页面的数据,为自己请求的数据。

    2. 图片的引入和使用: 引入后的变量 : src = {变量}

      import Bannerimg from ‘./assets/img/newbanner.jpg’;

      图片
import React from 'react';
import './assets/css/styls.css';import NewsCom from './new';
const axios = require('axios')  function Map() {return(<div className = 'cont_item'><h1>我是map组件</h1></div>)
}class App extends React.Component{constructor(props){super(props)this.state = {msg:'lyx',navlist:['疫情地图','最新进展','广州疫情','新闻内容'],tabIndex:0,barStyle:{"left":"22px"},contStyle:{"transform" :"translate(0,0)"}}}// ------------------------------------------render(){var navjsx=	this.state.navlist.map((item,index)=>{if(index === this.state.tabIndex){return(<div className = "navItem active" onClick = {(event)=>{this.tabClickEvent(index)}} key ={index}>{item}</div>)	}else{return(<div className = "navItem" onClick = {(event)=>{this.tabClickEvent(index)}}   key ={index}>{item}</div>)	}})return (<div className = "App"><div className= "nav "><div className= 'bar' style = {this.state.barStyle}></div>{navjsx}</div><div className="cont" style ={this.state.contStyle}><NewsCom></NewsCom><Map></Map></div></div>);}// ----------	 ---------- tabClickEvent = (index)=>{this.setState({barStyle:{"left":(index*88+22)+"px"},contStyle:{"transform" :`translate(${-index*375}px,0)`}})}}export default App;

解析:

18 插槽

组件中写入内容,这些内容可以被识别和控制。 Recat需要自己开发支持插槽的功能。

原理: 在父页面 引入的子组件组件中写入的HTML, 会挂载到放到子组件 props中。

import React from 'react';
import ReactDOM from 'react-dom';class Children extends React.Component {constructor(props) {super(props)this.state = {}}render(){console.log(this);//2. 在子元素的this。props中则挂载了插槽了的数据。 属性值和jsx,// 所以可以实现条件渲染在自己的dom中。return(<div className = 'Children-dom'><h1>我是chidren</h1>{this.props.children}</div> )}}
// --------------------class Clock extends React.Component {constructor(props) {super(props)this.state = {fatherList : 'i is from father'}}render() {return(  <div>    {this.props.children}<h1>我是h1</h1><Children>  {/* 1. 插槽传值:在字标签中可以传入标签,dom 标签中的属性值,和state中的数据。 */}<h1 data-id ='1'>我是parent的插槽 头部</h1><h1 data-id ='2'>我是parent的插槽 尾部</h1><span>  {this.state.fatherList}</span></Children></div>)}}ReactDOM.render(<Clock></Clock> ,document.getElementById('root'));

19 路由

概念:

根据不同的路径,显示不同的组件(内容):React使用的库 react-router-dom;

安装:

npm install react-router-dom --save       (--save保存版本信息) "react-router-dom": "^5.2.0",

ReaterRouter : 三大组件

Router: 所有路由租金的跟组件(底层组件),包裹路由规则的最外层容器。

Route:路由规则匹配组件,显示当前规则对应的组件。

Link: 路由跳转的组件。

注意: 如果要精确匹配,那么可以在route上设置 exacct 属性。(注意单词adj. 准确的,精密的;精确的)

路由的两种引入:

hash 模式

#/ #号就是hash的标志。 不发送请求

import { HashRouter as Router, Route , Link} from 'react-router-dom'

history 模式

/后边导向 需要后端配合

  引入
import {BrowserRouter as Router, Route , Link} from 'react-router-dom'

总结:

basename 设根路径

route 映射路由和组件 关系

link 相当于a标签跳转

0. exact 精准匹配。

第一种: 当有link标签时, 加载link中。
第二种: 没有link标签,只有route 标签时,加在route中。<Link to = '/product' exact>产品页</Link>
<Route path =  "/"    component = { ()=> (   <div> 首页1</div>) }></Route><Route path =  "/"  exact  component = { ()=> (   <div> 首页1</div>) }></Route>
基本的路由模式 code

1. 常规的路由link跳转 和传值

APP.js 组件页面 挂载到index.js 主页面中

import React from 'react';
import ReactDOM from 'react-dom';import {BrowserRouter as Router, Link, Route} from 'react-router-dom'function Me(props){console.log(props);return(<h1>Me</h1>)
}function Home(props){console.log(props);return(<h1>Home</h1>)
}function Produc(props){console.log(props);return(<h1>Produc</h1>)
}class App extends React.Component {constructor(props) {super(props)this.state = {}}render(){return(   <div id = 'app'>    <div> 所有页面都显示的普通页面</div><Router >   <div className = 'nav'><Link to = { { pathname:"/",search:"?sername=admin",hash:"#abc",state:{msg:"helloworld"}} }>Home</Link><Link to = '/product'>产品页</Link><Link to = '/me'>个人中心</Link></div><Route path = "/" exact component = {Home}></Route><Route path =  "/product" component = {Produc}></Route><Route path =  "/me" component = {Me}></Route></Router>   </div>)}
}
export default App;
Link to = { 变量}
         <Router >   <div className = 'nav'><Link to = { { pathname:"/",search:"?sername=admin",hash:"#abc",state:                                       {msg:"helloworld"}} }>Home</Link></div><Route path = "/" exact component = {Home}></Route></Router> 1. link to  后面的path和route标签,映射关系。
2. exact 精准匹配。  否则 /me 页面会显示  /的页面。
3. link传递的值。可以在组件中收到function Home(props){console.log(props);return(<h1>Home</h1>)}点击会自动拼接
http://localhost:3000/?sername=admin#abc

2 path 传值

通过路由标签,link传值, route : 键值, 组件中props对象中可以看到params下的值。

        <Router >   <div className = 'nav'><Link to = '/me/12345' replace >个人中心</Link></div><Route path =  "/me/:id"    component = {Me}></Route></Router> 浏览器地址
http://localhost:3000/me/12345

3. Link 的 replace 路由切换跳转

替换栈 。 使用方法: 直接在Link 标签后内添加 replace 替换 属性。

        <Router >   <div className = 'nav'><Link to = '/me' replace >个人中心</Link></div><Route path =  "/me"    component = {Me}></Route></Router> 

路由跳转,replace / push 区别

 push: a-b-c 可以回到上一级例: this.props.history.push('路由地址')
replace: a-b-c 回不到上一级 适用于登录后,不需要重新回到登页面例: this.props.history.replace('路由地址')

4 重定向组件

形式也是一个组件,所以也有props 对象。

概念: 如果访问到某个组件时,如果有重定向组件,那么就会修改页面路径,使得页面内容显示未错定向路径的内容。

引入 Redirect 方法

import {BrowserRouter as Router, Link, Route, Redirect} from 'react-router-dom'

原理:

假设 form表单登录的时候, 设置访问FormCom() 组件,这个组件就是登录页面,点击提交,

组件内设置 ajax请求,获取用户权限,携带信息,跳转LoginInfo 组件, 组件内 标签 ,跳转到 登录或者是 首页。

import React from 'react';
// import ReactDOM from 'react-dom';import {BrowserRouter as Router, Link, Route, Redirect} from 'react-router-dom'function LoginInfo(props){    //重定向组件 if(props.location.state.login_state == 'success'){// 如果成功 定向到admin页面return <Redirect to = "/admin"> </Redirect> }else{return <Redirect to = "/login"></Redirect> }
}function FormCom(){let dataobj = {pathname:"LoginInfo",state:{login_state:'success'}}return(
<div><h1>表单验证模拟</h1><Link to = {dataobj }>点击跳转至LoginInfo控制组件</Link></div>)
}class App extends React.Component {render(){return(   <div id = 'app'> <Router >   <Route path =  "/"  exact  component = { ()=> (   <div> 首页1</div>) }></Route><Route path =  "/form" exact  component = { FormCom }></Route><Route path =  "/login" exact  component = { ()=> (   <div> login请重新登陆                           </div>) }></Route><Route path =  "/LoginInfo" exact  component = { LoginInfo }></Route><Route path =  "/admin" exact   component = { ()=> (   <div> admin登录成功到                              admin</div>) }></Route></Router>   </div>)
}
}export default App;

5 Switch (n. 开关) 匹配 only one

应用场景:

路由会一直匹配,直到查找完所有的路由映射。1.假设没有exact 精准匹配, 进入home 首页也会显示。<Route path =  "/" <Route path =  "/home" 
2.有exact 精准匹配,碰到两个path相同的,又会同时显示两个页面内容。<Route path =  "/"  exact  component = { ()=> (   <div> 首页1</div>) }></Route>  <Route path =  "/"  exact  component = { ()=> (   <div> 首页1</div>) }></Route>Switch 作用: 匹配一条route,符合要求,就停止匹配。                                                                                          

使用方式:

引入  Switch 方法  注意模块都是首字母大写import {BrowserRouter as Router, Link, Route, Redirect, Switch} from 'react-router-dom'包裹route 使用。
<Router >   <Switch><Route path =  "/"  exact  component = { ()=> (   <div> 首页1</div>) }></Route></Switch>
</Router> 

6 编程式路由 js控制

1. push ( ) 跳转

子页面,点击跳转同时携带数据, 传值

class Children extends React.Component {render(){return(   <div id = 'Children'>    <button onClick = { this.clickEvent}>  跳转到首页</button>我是 Children</div>)}clickEvent=()=>{  console.log(this.props.history.push("/",{name:"这是chilren传递的数据"}))}// push( ) 接受两个参数  第一个时路由path , 第二个是: 可以页面传值  目标组件的 props中的location-state 下挂载}
replace
go
clickEvent=()=>{  //  this.props.history.push("/",{name:"这是chilren传递的数据"})//  this.props.history.replace("/",{name:"这是chilren传递的数据"})this.props.history.go(-1)  //正数前进,负数后退。 历史堆栈中要有数据,否则不能跳转。}

7 动态路由

解析:

正常老说: path = “/” 只能在 localhost:3000/ 时可以访问。 不能加参数

path = “/:id” 这种, 后边可以加参数,变化的参数也可以。 动态。

同样 props中可以查看数据

<Route path =  "/:id"  exact  component = { shouye }></Route>

相关文章:

react笔记基础部分(组件生命周期路由)

注意点&#xff1a; class是一个关键字&#xff0c; 类。 所以react 写class, 用classname &#xff0c;会自动编译替换class 点击方法&#xff1a; <button onClick {this.sendData}>给父元素传值</button>常用的插件&#xff1a; 需要引入才能使用的&#xf…...

Sentinel授权规则和规则持久化

大家好我是苏麟 , 今天说说Sentinel规则持久化. 授权规则 授权规则可以对请求方来源做判断和控制。 授权规则 基本规则 授权规则可以对调用方的来源做控制&#xff0c;有白名单和黑名单两种方式。 白名单&#xff1a;来源&#xff08;origin&#xff09;在白名单内的调用…...

JVM(三) 垃圾回收

一、自动垃圾回收 1.1 C/C++的内存管理 在C/C++这类没有自动垃圾回收机制的语言中,一个对象如果不再使用,需要手动释放,否则就会出现内存泄漏。我们称这种释放对象的过程为垃圾回收,而需要程序员编写代码进行回收的方式为手动回收。 内存泄漏指的是不再使用的对象在系统中…...

vue3中使用svg并封装成组件

打包svg地图 安装插件 yarn add vite-plugin-svg-icons -D # or npm i vite-plugin-svg-icons -D # or pnpm install vite-plugin-svg-icons -D使用插件 vite.config.ts import { VantResolver } from unplugin-vue-components/resolvers import { createSvgIconsPlugin } from…...

实验六:DHCP、DNS、Apache、FTP服务器的安装和配置

1. (其它) 掌握Linux下DHCP、DNS、Apache、FTP服务器的安装和配置&#xff0c;在Linux服务器上部署JavaWeb应用 完成单元八的实训内容。 1、安装 JDK 2、安装 MySQL 3、部署JavaWeb应用 安装jdk 教程连接&#xff1a;linux安装jdk8详细步骤-CSDN博客 Jdk来源&#xff1a;linu…...

Python实验项目4 :面对对象程序设计

1&#xff1a;运行下面的程序&#xff0c;回答问题。 &#xff08;1&#xff09;说明程序的执行过程&#xff1b; &#xff08;2&#xff09;程序运行结果是什么&#xff1f; # &#xff08;1&#xff09;说明程序的执行过程&#xff1b; # &#xff08;2&#xff09;程序运行…...

用html、css和jQuery实现图片翻页的特效

在当今的web设计中&#xff0c;图片翻页特效是一种常见而且受欢迎的技术。通过图片的切换与过渡效果&#xff0c;能够使网页更具动感和吸引力。下面写一个简单的示例&#xff0c;来介绍一下如何使用html、css和jQuery实现图片翻页特效。 1&#xff0c;html结构 首先&#xff…...

awk 框架

参考自&#xff1a;https://zhuanlan.zhihu.com/p/627048291?utm_id0语法&#xff0c;由几部分组成 awk [options] script varvalue file(s) awk [options] -f scriptfile varvalue file(s)语法中的script部分&#xff0c;由两部分组成 模式操作 其中一个模式&#xff1a;B…...

专业135总分400+西安交通大学信息与通信工程学院909/815考研经验分享

今年初试发挥不错&#xff0c;400&#xff0c;专业课135&#xff0c;将近一年复习一路走来&#xff0c;感慨很多&#xff0c;希望以下经历可以给后来的同学提供一些参考。 初试备考经验 公共课&#xff1a;三门公共课&#xff0c;政治&#xff0c;英语&#xff0c;数学。在备考…...

在 Windows 用 Chrome System Settings 设置代理

在 Windows 用 Chrome System Settings 设置代理 贴心提示&#xff1a;在设置代理之前&#xff0c;请确保您已经安装了 浏览器。 &#x1f527; 设置代理的详细步骤如下&#xff1a; 打开 浏览器&#xff0c;输入 //settings/system 并回车。 在「系统和网络设置」页面中&am…...

Excel多线程导入数据库

文章目录 Excel多线程导入数据库1. CountDownLatch2.多线程导入数据库 Excel多线程导入数据库 书接上文 Excel20w数据5s导入 1. CountDownLatch CountDownLatch 维护了一个计数器&#xff0c;初始值为指定的数量。当一个或多个线程调用 await() 方法时&#xff0c;它们会被阻…...

Linux开机默认进入命令行或图形化模式

开机默认进入命令行 sudo systemctl set - default multi-user.target 执行上面命令后重新启动 reboot开机默认进入图形化界面 sudo systemctl set - default graphical.target 执行上面命令后重新启动 reboot或者 先进入root之后 su 在执行 systemctl set - default …...

ajax请求的时候get 和post方式的区别?

在 AJAX 请求中&#xff0c;GET 和 POST 是两种常用的请求方法&#xff0c;它们在发送请求时有一些区别&#xff1a; GET 请求&#xff1a; GET 请求用于向服务器请求获取指定资源&#xff0c;请求参数会附加在 URL 的末尾&#xff0c;以查询字符串的形式出现。GET 请求将请求…...

还不知道光场相机吗?

1.什么是光场&#xff1f; 光场&#xff08;light field&#xff09;&#xff1a;就是指光在每一个方向通过每一个点的光量。 从概念里&#xff0c;你至少可以得到两点信息&#xff1a; 光场包含光的方向光场包含一个点的光量 2.什么是光场相机 我们知道普通的相机拍照成像…...

软信天成:助力某制造企业建设产品主数据管理平台案例分享

某国有大型传统制造企业是一家跨领域、跨行业经营的国际化公司&#xff0c;在全球范围内拥有动力系统、工程机械、汽车制造等多个业务板块、分子公司遍及世界、产品远销110多个国家和地区&#xff0c;产品品类繁多&#xff0c;分支架构错综复杂。 近年来&#xff0c;数字化的深…...

C#WPFPrism框架导航应用实例

本文实例演示C#WPFPrism框架导航应用实例。 一、导航实现步骤 首先创建WPF项目,修改App相关文件内容,以便使用prism。 承接上一个模块化的实例,在这个基础上更改增加导航功能。 1.1首先在ModuleA中添加ViewModels文件夹,添加ViewAViewModel.cs类 如果想上下文自动查找…...

Centos安装gitlabce

服务器配置要求&#xff08;2c4g&#xff09; 1、 安装其他组件 yum install -y curl policycoreutils-python openssh perl2、 安装Postfix服务以发送电子邮件通知&#xff0c;启动服务并自启 yum -y install postfix systemctl enable postfix --now3、 安装gitlab&#xf…...

android8.1- Show virtual keyboard 默认打开

修改路径&#xff1a;android-8.1\frameworks\base\packages\SettingsProvider\res\values\defaults.xml 将 &#xff1a;<bool name"def_show_ime_with_hard_keyboard">false</bool> 改成 &#xff1a;true <!-- Default for Settings.Secure.MULTI_…...

打印机连接网络后怎么安装驱动?

打印机在我们办公和生活中算是比较常见的设备&#xff0c;特别是在上班时需要时常打印各种文件&#xff0c;但是有时电脑上的打印机也会有无法打印的问题&#xff0c;或者新买的打印机需要先安装驱动才能正常打印的。 那么这个时候我们需要先检查电脑上的打印机是否有安装驱动&…...

光流法动目标检测

目录 前言 一、效果展示 二、光流法介绍 三、代码展示 总结 前言 动目标检测是计算机视觉领域的一个热门研究方向。传统的方法主要基于背景建模&#xff0c;但这些方法对于光照变化、遮挡和噪声敏感。因此&#xff0c;研究人员一直在寻找更加鲁棒和有效的技术来解决这一问题。…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...