React的安装
npm i react react-dom
React的使用
<script src="./node_modules/react/umd/react.development.js">script>
<script src="./node_modules/react-dom/umd/react-dom.development.js">script>
// 创建元素节点
// 1. 参数1:元素名称
// 2. 参数2:元素属性 传递的是个对象
// 3. 第三个及其以后的参数:元素内容
let title = React.createElement('li', null, 'hellow react');
//let title = React.createElement('li', {title='标题',id='10'}, 'hellow react');
// 渲染到页面
ReactDOM.render(title, root)
*1.使用React脚手架初始化项目
2.脚手架中使用React
import React from 'react'
import ReactDOM from 'react-dom'
let h1 = React.createElement('h1',null,'我是标题')
ReactDOM.render(h1,document.getElementById('root'))
JSX产生的原因
由于通过createElement()方法创建的React元素有一些问题,代码比较繁琐,结构不直观,无法一眼看出描述的结构,不优雅,用户体验不爽
JSX的概述
JSX是JavaScript XML 的简写,表示在JavaScript代码中写HTML格式的代码
优势:声明式语法更加直观,与HTML结构相同,降低了学习成本,提升开发效率
使用步骤
let h1 = 我是通过JSX创建的元素
ReactDOM.render(h1,document.getElementById('root'))
为什么在脚手架中可以使用JSX语法
注意点
/>
来结束JSX是来描述页面的结构,我们一般在编写业务逻辑渲染页面的时候,需要涉及到传递值,调用函数,判断条件,循环等,这一些在JSX中都能得到支持
嵌入JS表达式
语法:{JavaScritp表达式}
例子:
let content = '插入的内容'
let h1 = 我是通过JSX创建的元素+ {content}
注意点
条件渲染
根据不同的条件来渲染不同的JSX结构
let isLoading = true
let loading = ()=>{
if(isLoading){
return Loading...
}
return 加载完成
}
可以发现,写JSX的条件渲染与我们之前编写代码的逻辑是差不多的,根据不同的判断逻辑,返回不同的 JSX结构,然后渲染到页面中
列表渲染
const arr = [{
id:1,
name:'三国演义'
},{
id:2,
name:'水浒传'
},{
id:3,
name:'西游记'
},{
id:4,
name:'红楼梦'
}]
const ul = (
{arr.map(item => - {item.name}
)}
)
ReactDOM.render(ul,document.getElementById('root'))
样式处理
1). 行内样式 -style
在style里面我们通过对象的方式传递数据
{item.name}
这种方式比较的麻烦,不方便进行阅读,而且还会导致代码比较的繁琐
2). 类名 -className
创建CSS文件编写样式代码
.container {
text-align: center
}
在js中进行引入,然后设置类名即可
import './css/index.css'
{item.name}
函数创建组件
编写函数组件
function Hello() {
return (
这是第一个函数组件
)
}
利用ReactDOM.render()进行渲染
ReactDOM.render( ,document.getElementById('root'))
类组件(★★★)
创建class类,继承React.Component,在里面提供render方法,在return里面返回内容
class Hello extends React.Component{
render(){
return (
这是第一个类组件
)
}
}
通过ReactDOM进行渲染
ReactDOM.render( ,document.getElementById('root'))
抽离成单独的JS文件(★★★)
示例demo
import React from 'react'
export default class extends React.Component {
render(){
return (
单独抽离出来的 Hello
)
}
}
import Hello from './js/Hello'
ReactDOM.render( ,document.getElementById('root'))
事件绑定
示例demo
export default class extends React.Component {
clickHandle = (e) => {
console.log('点了')
}
render(){
return (
)
}
}
小结
事件对象
stopPropagation()
和 preventDefault()
nativeEvent
属性来进行获取export default class extends React.Component {
clickHandle = (e) => {
// 获取原生事件对象
console.log(e.nativeEvent)
}
render(){
return (
)
}
}
有状态组件和无状态组件
1.写法一(★★★)
//事件对象作为第二个参数传递
delFolder = (name,e)=>{
console.log(name);
console.log(e);
}
2.写法二
//用bind绑定,调用是作为第二个参数传递,不用显示传递事件对象,定义方法时,事件对象作为最后一个参数传入
delFolder = (name,e)=>{
alert(name)
}
3.写法三
//返回一个函数,事件对象在返回的函数中
delFolder = (name)=>{
return (e)=>{
console.log(e);
console.log(name);
}
}
1.state基本使用
export default class extends React.Component {
constructor(){
super()
// 第一种初始化方式
this.state = {
count : 0
}
}
// 第二种初始化方式
state = {
count:1
}
render(){
return (
计数器 :{this.state.count}
)
}
}
2.setState() 修改状态
export default class extends React.Component {
// 第二种初始化方式
state = {
count:1
}
render(){
return (
计数器 :{this.state.count}
)
}
}
//扩展 修改state中对象的某个值
//1.es6的解构赋值
handlepagenum = (num,size) => {
const queryInfo = {...this.state.queryInfo };
queryInfo.pagenum = num;
this.setState(() => {
return {
queryInfo:queryInfo
}
},() => {
this.getUserList();
});
}
//2.Object.assign
handlepagesize = (num,size) => {
const queryInfo = Object.assign({}, this.state.queryInfo, { pagenum: 1,pagesize: size })
this.setState(() => {
return {
queryInfo:queryInfo
}
},() => {
this.getUserList();
});
}
小结
原因
利用箭头函数自身不绑定this的特点
利用bind方法(★★★)
利用原型bind方法是可以更改函数里面this的指向的,所以我们可以在构造中调用bind方法,然后把返回的值赋值给我们的函数即可
class App extends React.Component {
constructor() {
super()
...
// 通过bind方法改变了当前函数中this的指向
this.onIncrement = this.onIncrement.bind(this)
}
// 事件处理程序
onIncrement() {
...
}
render() {
...
}
}
class的实例方法(★★★)
// 事件处理程序
onIncrement = () => {
console.log('事件处理程序中的this:', this)
this.setState({
count: this.state.count + 1
})
}
受控组件(★★★)
setState()
方法来修改
非受控组件 (了解)
class MyComponent extends React.Component {
handleClick() {
// 使用原生的 DOM API 获取焦点
this.refs.myInput.focus();
}
render() {
// 当组件插入到 DOM 后,ref 属性添加一个组件的引用于到 this.refs
return (
);
}
}
ReactDOM.render(
,
document.getElementById('example')
);
组件通讯介绍
组件是独立且封闭的单元,默认情况下,只能使用组件自己的数据。在组件化过程中,我们将一个完整的功能拆分成多个组件,以更好的完成整个应用的功能。而在这个过程中,多个组件之间不可避免的要共享某些数据。为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通,这个过程就是组件通讯
基本使用
组件时封闭的,要接受外部数据应该通过props来实现
props的作用:接收传递给组件的数据
传递数据:给组件标签添加属性
接收数据:函数组件通过 参数 props接收数据,类组件通过 this.props接收数据
函数组件获取
function Hello(props) {
console.log(props)
return (
接收的数据:{props.name}
)
}
类组件获取
class Hello extends React.Component {
render() {
return (
接收的数据:{this.props.name}
)
}
}
特点
可以给组件传递任意类型的数据
props是只读属性,不能对值进行修改
注意:使用类组件时,如果写了构造函数,应该将props传递给super(),否则,无法在构造函数中获取到props,其他的地方是可以拿到的
class Hello extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
接收的数据:{this.props.name}
)
}
}
父组件提供要传递的state数据
给子组件标签添加属性,值为state中的数据
子组件中通过props接收父组件中传递的数据
class Parent extends React.Component {
state = {lastName: '张三'};
render() {
return (
传递数据给子组件:
)
}
}
function Child(props) {
return(
子组件接收到数据:{props.name}
)
}
利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数
父组件提供一个回调函数,用来接收数据
将该函数作为属性的值,传递给子组件
class Parent extends React.Component {
state = {
parentMsg: ''
}
//提供回调函数
getChildMsg = (msg) => {
console.log('接收到子组件数据',msg)
this.setState({
parentMsg: msg
})
}
render() {
return (
父组件: {this.state.parentMsg}
子组件:
)
}
}
子组件通过props调用回调函数
class Child extends React.Component {
state = {childMsg: 'react'}
handleClick = () => {
this.props.getMsg(this.state.childMsg)
}
render() {
return (
)
}
}
1.定义布局结构,一个Counter里面包含两个子组件,一个是计数器的提示,一个是按钮
class Counter extends React.Component {
render() {
return (
)
}
}
class Child1 extends React.Component {
render() {
return (
计数器:
)
}
}
class Child2 extends React.Component {
render() {
return (
)
}
}
2.在父组件里定义共享状态,把这个状态传递给第一个子组件
class Counter extends React.Component {
// 提供共享的状态
state = {
count: 0
}
render() {
return (
{/* 把状态提供给第一个子组件 */}
)
}
}
3.在第一个子组件里面就能通过props获取到
class Child1 extends React.Component {
render() {
return (
计数器:{this.props.count}
)
}
}
4.在父组件中提供共享方法,通过属性传递给第二个子组件,方便第二个子组件来进行调用
// 提供共享方法
onIncrement = (res) => {
// 只要第二个子组件调用了这个函数,就会执行里面代码
this.setState({
count: this.state.count + res
})
}
render() {
return (
...
{/* 把共享方法提供给第二个子组件 */}
)
}
5.在第二个子组件里面通过props来获取到对应函数,然后进行调用
class Child2 extends React.Component {
handleClick = () => {
// 这里一旦调用,就会执行父组件里面 onIncrement函数
this.props.onIncrement(2)
}
render() {
return (
)
}
}
如果出现层级比较多的情况下(例如:爷爷传递数据给孙子),我们会使用Context来进行传递
作用: 跨组件传递数据
使用步骤
调用 React.createContext()
创建 Provider(提供数据) 和 Consumer(消费数据) 两个组件
const { Provider,Consumer} = React.createContext()
使用Provider 组件作为父节点
设置value属性,表示要传递的数据
哪一层想要接收数据,就用Consumer进行包裹,在里面回调函数中的参数就是传递过来的值
{data => data参数表示接收到的数据 -- {data}}
//创建context得到两个组件
const {Provider,Consumer} = React.createContext()
class App extends React.Component {
render() {
return (
)
}
}
class Node extends React.Component {
render() {
return (
)
}
}
class SubNode extends React.Component {
render() {
return (
)
}
}
class Child extends React.Component {
render() {
return (
{data => data参数表示接收到的数据 -- {data}}
)
}
}
ReactDOM.render(
,document.getElementById('example')
);
children属性: 表示组件标签的子节点,当组件标签有子节点时,props就会有该属性
children属性与普通的props一样,值可以使任意值(文本、react元素、组件、甚至是函数)
function Hello(props) {
return (
组件的子节点:{props.children}
)
}
我是子节点
对于组件来说,props是外来的,无法保证组件使用者传入什么格式的数据,简单来说就是组件调用者可能不知道组件封装着需要什么样的数据
如果传入的数据不对,可能会导致报错
关键问题:组件的使用者不知道需要传递什么样的数据
props校验:允许在创建组件的时候,指定props的类型、格式等
App.propTypes = {
colors: PropTypes.array
}
作用:捕获使用组件时因为props导致的错误,给出明确的错误提示,增加组件的健壮性
使用步骤
安装包 prop-types (yarn add prop-types | npm i props-types)
导入prop-types 包
使用组件名.propTypes={}
来给组件的props添加校验规则
校验规则通过PropTypes对象来指定
import PropTypes from 'prop-types'
function App(props) {
return (
Hi,{props.colors}
)
}
App.propTypes = {
//约定colors属性为array类型
//如果类型不对,则报出明确错误,便于分析错误原因
colors: PropTypes.array
}
常见的约束规则
创建的类型: array、bool、func、number、object、string
React元素类型:element
必填项:isRequired
特定结构的对象: shape({})
更多的约束规则
//常见类型
optionalFunc: PropTypes.func,
//必选
requiredFunc: PropTypes.func.isRequired,
//特定结构的对象
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize:Proptypes.number
})
场景:分页组件 -> 每页显示条数
function App(props) {
return (
此处展示props的默认值:{props.pageSize}
)
}
//设置默认值
App.defaultProps = {
pageSize: 10
}
//不传入pageSize属性
概述
意义:组件的生命周期有助于理解组件的运行方式,完成更复杂的组件功能、分析组件错误原因等
组件的生命周期: 组件从被创建到挂载到页面中运行,再到组件不在时卸载的过程
生命周期的每个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数
构造函数的作用:为开发人员在不同阶段操作组件提供了实际
钩子函数 | 触发时间 | 作用 |
---|---|---|
constructor | 创建组件时最先执行 | 1.初始化state2.为事件处理程序绑定this |
render | 每次组件渲染时都会触发 | 渲染UI(不能调用setState()) |
componentDidMount | 组件挂载(完成DOM渲染)后 | 1.发送网络请求2.DOM操作 |
执行时机:setState()、 forceUpdate()、 组件接收到新的props
说明:以上三者任意一种变化,组件就会重新渲染
钩子函数 | 触发时间 | 作用 |
---|---|---|
render | 每次组件渲染时都会触发 | 渲染UI(与挂载阶段是同一个render) |
componentUpdate | 组件更新(完成DOM渲染)后 | 1.发送网络请求 2.DOM操作 **注:**如果要setState(),必须放在一个if()条件中(比较更新前后的props是否相同,来决定是否重新渲染组件) |
执行时机:组件从页面中消失
作用:用来做清理操作
钩子函数 | 触发时间 | 作用 |
---|---|---|
componentWillUnmount | 组件挂卸载(从页面中消失) | 执行清理工作(比如清理定时器) |
getDerivedStateFromProps()
getDerivedStateFromProps
会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容shouldComponentUpdate()
shouldComponentUpdate()
的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。默认行为是 state 每次发生变化组件都会重新渲染shouldComponentUpdate()
会在渲染执行之前被调用。返回值默认为 truegetSnapshotBeforeUpdate()
getSnapshotBeforeUpdate()
在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()
import React from 'react';
class Mouse extends React.Component {
constructor(props) {
super(props)
this.state = {
x: 0,
y: 0
}
// console.log(props.children)
}
componentDidMount() {
window.addEventListener('mousemove',this.handleMouseMove)
}
componentWillUnmount() {
window.removeEventListener('mousemove',this.handleMouseMove)
}
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
render() {
// 向外界提供当前子组件里面的数据
return this.props.render(this.state)
//children代替render属性
//注意:并不是该模式叫 render props就必须使用名为render的prop,实际上可以使用任意名称的prop
//把prop是一个函数并且告诉组件要渲染什么内容的技术叫做: render props模式
//推荐:使用childre代替render属性
//return this.props.children(this.state)
}
}
export default Mouse;
class App extends React.Component {
render() {
return (
{
return X{mouse.x}Y{mouse.y}
}}/>
//{(mouse) => p的位置是X{mouse.x},Y{mouse.y}
)
}
}
ReactDOM.render( ,document.getElementById('root'))
WrappedComponent
使用步骤
import React from 'react'
// 定义一个函数,在函数内部创建一个相应类组件
function withMouse(WrappedComponent) {
// 该组件提供复用状态逻辑
class Mouse extends React.Component {
state = {
x: 0,
y: 0
}
// 事件的处理函数
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
// 当组件挂载的时候进行事件绑定
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove)
}
// 当组件移除时候解绑事件
componentWillUnmount() {
window.removeEventListener('mousemove', this.handleMouseMove)
}
render() {
// 在render函数里面返回传递过来的组件,把当前组件的状态设置进去
//传递props
//问题:如果没有传递props,会导致props丢失问题
//解决方式: 渲染WrappedComponent时,将state和props一起传递给组件
//return
return
}
}
//设置displayName
//使用高阶组件存在的问题:得到两个组件的名称相同
//原因:默认情况下,React使用组件名称作为displayName
//解决方式:为高阶组件设置displayName,便于调试时区分不同的组件
//displayName的作用:用于设置调试信息(React Developer Tools信息)
Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`
return Mouse
}
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}
export default withMouse;
import withMouse from './withMouse.js'
//哪个组件需要加强,通过调用withMouse这个函数,然后把返回的值设置到父组件中即可
function Position(props) {
return (
X:{props.x}
Y:{props.y}
)
}
// 把position 组件来进行包装
let MousePosition = withMouse(Position)
class App extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
高阶组件
)
}
}
更新数据
setState()
更新数据是异步的setState
不要依赖前面setState
的值setState
,只会触发一次render推荐语法
推荐:使用 setState((state,props) => {})
语法
参数state: 表示最新的state
参数props: 表示最新的props
this.setState((state,props) => {
return {
count: state.count + 1
}
})
console.log(this.state.count)//1
第二个参数
setState(update[,callback])
this.setState((state,props) => {
return {
count: state.count + 1
}
},
() => {console.log("这个回调函数会在状态更新后立即执行")}
)
createElement()
方法的语法糖(简化语法)createElement()
方法//JSX语法
const element = (Hello JSX
)
//createElement()
const element = React.createElement('h1',{className:'greeting'},'Hello JSX')
//React元素
//注意:这是简化过程
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello JSX'
}
}
减轻state
class Hello extends Component {
componentDidMount() {
//timerId存储到this中,而不是state中
this.timerId = setInterval(() => {},2000)
}
componentWillUnmount() {
clearInterval(this.timerId)
}
render() {...}
}
避免不必要的重新渲染
利用nextState参数来判断当前组件是否需要更新
import React from 'react'
import ReactDOM from 'react-dom'
/*
组件性能优化:
*/
// 生成随机数
class App extends React.Component {
state = {
number: 0
}
handleClick = () => {
this.setState(() => {
return {
number: Math.floor(Math.random() * 3)
}
})
}
// 因为两次生成的随机数可能相同,如果相同,此时,不需要重新渲染
shouldComponentUpdate(nextProps, nextState) {
console.log('最新状态:', nextState, ', 当前状态:', this.state)
return nextState.number !== this.state.number
// if (nextState.number !== this.state.number) {
// return true
// }
// return false
// if (nextState.number === this.state.number) {
// return false
// }
// return true
}
render() {
console.log('render')
return (
随机数:{this.state.number}
)
}
}
ReactDOM.render( , document.getElementById('root'))
利用props参数来判断是否需要进行更新
class App extends React.Component {
state = {
number: 0
}
// 点击事件,每次点击生成一个随机数
hanldeBtn = () => {
this.setState({
number: Math.floor(Math.random() * 3)
})
}
render() {
return (
)
}
}
class NumberBox extends React.Component {
// 将要更新UI的时候会执行这个钩子函数
shouldComponentUpdate(nextProps, nextState) {
// 判断一下当前生成的 值是否与页面的值相等
if (nextProps.number !== this.props.number) {
return true
}
return false
}
render() {
return (
随机数:{this.props.number}
)
}
}
import React from 'react'
import ReactDOM from 'react-dom'
/*
组件性能优化:
*/
// 生成随机数
class App extends React.Component {
state = {
number: 0
}
handleClick = () => {
this.setState(() => {
return {
number: Math.floor(Math.random() * 3)
}
})
}
render() {
return (
)
}
}
class NumberBox extends React.PureComponent {
render() {
console.log('子组件中的render')
return 随机数:{this.props.number}
}
}
ReactDOM.render( , document.getElementById('root'))
import React from 'react'
import ReactDOM from 'react-dom'
/*
组件性能优化:
*/
// 生成随机数
class App extends React.PureComponent {
state = {
number: 0
}
handleClick = () => {
this.setState(() => {
return {
number: Math.floor(Math.random() * 3)
}
})
}
render() {
console.log('父组件中的render')
return (
随机数:{this.state.number}
)
}
}
ReactDOM.render( , document.getElementById('root'))
import React from 'react'
import ReactDOM from 'react-dom'
/*
组件性能优化:
*/
// 引用类型:
const obj = { number: 0 }
const newObj = obj
newObj.number = 2
console.log(newObj === obj) // true
// 生成随机数
class App extends React.PureComponent {
state = {
obj: {
number: 0
}
}
handleClick = () => {
// 正确做法:创建新对象
// 不要用数组的push/unshift等直接修改当前数组的方法
// 应该使用concat或slice等这些返回新数组的方法
const newObj = { ...this.state.obj, number: Math.floor(Math.random() * 3) }
this.setState(() => {
return {
obj: newObj
}
})
// 错误演示:直接修改原始对象中属性的值
/* const newObj = this.state.obj
newObj.number = Math.floor(Math.random() * 3)
this.setState(() => {
return {
obj: newObj
}
}) */
}
render() {
console.log('父组件重新render')
return (
随机数:{this.state.obj.number}
)
}
}
ReactDOM.render( , document.getElementById('root'))
Diff算法
执行过程
基本使用
使用步骤
安装: yarn add react-router-dom
导入路由的三个核心组件: Router / Route / Link
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
使用Router 组件包裹整个应用
使用Link组件作为导航菜单(路由入口)
使用Route组件配置路由规则和要展示的组件(路由出口)
import React from 'react'
import ReactDOM from 'react-dom'
/*
react-router-dom 的基本使用:
1 安装: yarn add react-router-dom
*/
// 2 导入组件:
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
const First = () => 页面一的内容
// 3 使用Router组件包裹整个应用
const App = () => (
React路由基础
{/* 4 指定路由入口 */}
页面一
{/* 5 指定路由出口 */}
)
ReactDOM.render( , document.getElementById('root'))
路由的执行过程
**场景:**点击登陆按钮,登陆成功后,通过代码跳转到后台首页,如何实现?
**编程式导航:**通过JS代码来实现页面跳转
history是React路由提供的,用于获取浏览器历史记录的相关信息
**push(path):**跳转到某个页面,参数path表示要跳转的路径
go(n):前进或后退功能,参数n表示前进或后退页面数量
import React from 'react'
import ReactDOM from 'react-dom'
/*
编程式导航
*/
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
class Login extends React.Component {
handleLogin = () => {
// 使用编程式导航实现路由跳转
// ...省略其他功能代码
this.props.history.push('/home')
}
render() {
return (
登录页面:
)
}
}
const Home = props => {
const handleBack = () => {
// go(-1) 表示返回上一个页面
props.history.go(-1)
}
return (
我是后台首页
)
}
const App = () => (
编程式导航:
去登录页面
)
ReactDOM.render( , document.getElementById('root'))
'/'
模糊匹配模式
当Link组件的to属性值为 ‘/login’ 时候,为什么默认路由也被匹配成功?
默认情况下,React路由是模糊匹配模式
模糊匹配规则:只要pathname以path开头就会匹配成功
path | 能够匹配的pathname |
---|---|
/ | 所有的pathname |
/first | /first或/first/a或/first/a/… |
import React from 'react'
import ReactDOM from 'react-dom'
/*
模糊匹配模式
*/
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
const Home = () => 进入页面的时候,你能看到我吗?
const Login = () => 我是Login组件的内容
const App = () => (
默认路由
登录页面
//登录页面
//登录页面
{/* 默认路由 */}
)
ReactDOM.render( , document.getElementById('root'))
精准匹配
默认路由认可情况下都会展示,如果避免这种问题?
给Route组件添加exact属性,让其变为精准匹配模式
精确匹配:只有当path和pathname完全匹配时才会展示改路由
import React from 'react'
import ReactDOM from 'react-dom'
/*
模糊匹配模式
*/
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
const Home = () => 进入页面的时候,你能看到我吗?
const Login = () => 我是Login组件的内容
const App = () => (
默认路由
-
首页
-
登录页面
{/* 默认路由,添加 exact 属性,就会让当前路由变为精确匹配 */}
)
ReactDOM.render( , document.getElementById('root'))
传单个值
//main.js
import React from 'react';
import {BrowserRouter as Router,Route,Link} from 'react-router-dom';
import News from './News';
class Main extends React.Component{
constructor(props){
super(props);
this.state={
id:66
}
}
render(){
return (
{/* 1. 固定传值 */}
News
{/* 2. 拼接传值 */}
News
{/* 3. ES6模板传值 */}
News
)
}
}
export default Main;
传多个值
//main.js
import React from 'react';
import {BrowserRouter as Router,Route,Link} from 'react-router-dom';
import News from './News';
class Main extends React.Component{
constructor(props){
super(props);
this.state={
id:66,
name:"易安"
}
}
render(){
return (
News
)
}
}
export default Main;
取值
//News.js中取值
import React from 'react';
class News extends React.Component {
componentDidMount(){
console.log(this.props.match.params.uid);
console.log(this.props.match.params.uname);
}
render() {
return (
News
);
}
}
export default News;
路由的get传值,值在location的search,可以写算法进行解析,也可安装node的url模块进行解析。
import React from 'react';
import {BrowserRouter as Router,Route,Link} from 'react-router-dom';
import My from './My';
class Main extends React.Component{
render(){
return (
My
)
}
}
export default Main;
取值
算法解析
//my.js
import React from 'react';
class My extends React.Component {
componentDidMount(){
let locurl=this.props.location.search;
this.changeUrl(locurl);
}
changeUrl=(locurl)=>{
let u=locurl.replace("?","");
let ur=u.replace(/=/g,":").replace("&",",");
console.log(ur.split(",")[0].split(":")[1]);
}
render() {
return (
My
);
}
}
export default My;
url模块解析
//my.js
import React from 'react';
import url from 'url';
class My extends React.Component {
componentDidMount(){
let locurl=this.props.location.search;
let data=url.parse(locurl,true).query;
console.log(data);
}
render() {
return (
My
);
}
}
export default My;
动态路由传值+get传值:
//main.js
import React from 'react';
import {BrowserRouter as Router,Route,Link} from 'react-router-dom';
import dyValue from './dyValue';
import getValue from './getValue';
class Main extends React.Component{
constructor(props){
super(props);
this.state={
arr:[
{
aid:1,
title:"Vue"
},
{
aid:2,
title:"React"
},
{
aid:3,
title:"Node"
}
]
}
}
render(){
return (
动态路由传值
{
this.state.arr.map((value,index)=>{
return (
{value.title}
)
})
}
get方式传值
{
this.state.arr.map((value,index)=>{
return (
{value.title}
)
})
}
)
}
}
export default Main;
在对应跳转页面参数值:
componentDidMount() {
console.log(this.props.match.params.aid); //动态路由取值
console.log(this.props.location.search); //get取值,取出来的是?aid=1这种格式,需手动转或引入url模块,进行路由解析
}
前提:必须由其他页面跳过来,参数才会被传递过来
注:不需要配置路由表。路由表中的内容照常:
1.Link处
HTML方式
JS方式
this.props.router.push({ path : '/sort' ,query : { name: ' sunny'} })
2.sort页面
this.props.location.query.name
同query差不多,只是属性不一样,而且state传的参数是加密的,query传的参数是公开的,在地址栏
1.Link 处
HTML方式:
JS方式:
this.props.router.push({ pathname:'/sort',state:{name : 'sunny' } })
2.sort页面
this.props.location.state.name