react3.0-组件、组件传值、Context、组件生命周期、路由、匹配模式

26 篇文章 0 订阅
7 篇文章 0 订阅

react3.0

全局导入的变量名可以自定义,按需导入则是要用规定的变量名

复习组件传值:

父传子,子传父:

review.js

import React from "react"
// 传值要注意this指向问题,解决办法有三个:1.在构造函数里面用bind,2.初始化时使用箭头函数,3.在该函数外面套一层箭头函数
// 父组件
class Person extends React.Component {
    state = {
        msg:'我是父组件的数据'
    }
    render() {
        return (
            <div>hello,早上好呀
                { this.state.msg}
                <Son msg={this.state.msg} />
                { /*info是Child子组件绑定的属性,属性值是父组件的回调函数,用来接收数据*/}
                <Child info={ this.getInfo}/>
            </div>
            
        )
    }
    // 给父组件添加事件,是一个回调函数
    // 接收Child传递过来的数据,并重新修改state中msg的值
    // 参数msg就是子组件传递过来的数据
    getInfo = (msg) => {
        this.setState({
            msg:msg
        })
    }
}
// 父传子
// 子组件
function Son(props) {
    return (
        <div>我是Son子组件,父组件传递过来的数据:{ props.msg}</div>
    )
}


class Child extends React.Component {
    // 给子组件添加状态
    state = {
        msg:'我是子组件Child的数据'
    }
    render() {
        return (
            <div>
                我是Child子组件
                { /*通过触发handle事件,将state中的msg数据传递给父组件*/}
                <button onClick={this.handle}>传值,改变父组件的msg</button>
            </div>
        )
    }
    handle = () => {
        // 通过this.props调用父组件的回调函数
        // info是标签的自定义属性,是一个回调函数,参数是要传递的数据
        this.props.info(this.state.msg)
    }
}

export default Person

index.js


import React from 'react';
import ReactDOM from 'react-dom';
// 子传父,父传子
import Person from "./components/review"

ReactDOM.render(
  <div><Person/></div>,
  document.getElementById('root')
);

兄弟组件之间传值:


import React from 'react';
import ReactDOM from 'react-dom';
// 兄弟组件之间的传值:子传父,父传子相结合,通过自定义属性传值
// 公共组件Hello
class Hello extends React.Component {
  // 公用状态count
  state = {
    count: 0
  }
  render() {
    return (
      <div>
        <Son1 info={ this.state.count}/>
        <Son2 info={ this.getInfo}/>
      </div>
    )
  }
  // 处理count
  getInfo = () => {
    this.setState({
      count:this.state.count+1
    })
  }
}

// Son1组件:显示count
class Son1 extends React.Component {
  render() {
    return (
      <div>
        { this.props.info}
      </div>
    )
  }
}
// Son2组件:操作count
class Son2 extends React.Component {
  render() {
    return (
      <div>
        <button onClick={ this.handle}>+1</button>
      </div>
    )
  }
  handle = () => {
    this.props.info()
  }
}

ReactDOM.render(
  <div><Hello /></div>,
  document.getElementById('root')
);

Context

import React from 'react';
import ReactDOM from 'react-dom';
// Provider:提供数据,Consumer:使用数据
const {Provider,Consumer } =React.createContext()
// 想要给哪个组件传值,就在该组件标签外面加一个Provider标签,该标签的value属性值就是要传递的数据

class Hello extends React.Component {
    state = {
        msg:'我是Provider提供的数据'
    }
    render() {
        return (
            <div>
                <Provider value={this.state.msg}>
                    我是Provider标签
                    <Son />
                </Provider>
                <Provider value="我是一个干饭人,加油,努力干饭">
                    <Child/>
                </Provider>
            </div>
        )
    }
}
// 向使用Provider提供的数据数据
class Son extends React.Component {
    render() {
        return (
            <div>
                <Child />
                <Consumer>
                        {data => { return data}}
                </Consumer>
            </div>
        )
    }
}

class Child extends React.Component {
    render() {
        return (
            <div>
                我是Son组件
                <Consumer>{data => { return data}}</Consumer>
            </div>
        )
    }
}


ReactDOM.render(
  <div><Hello /></div>,
  document.getElementById('root')
);

组件生命周期

组件生命周期:组件从被创建挂载到页面中运行,再到组件不用时卸载的过程;生命周期的每个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数

只有类组件才有生命周期,函数组件没有生命周期

钩子函数的作用:为开发人员在不同阶段操作组件提供了时机

生命周期的三个阶段
1.创建时(挂载阶段)

执行时机:组件创建时(页面加载时)

钩子函数的执行顺序:constructor(){}——>render(){}——>componentDidMount(){}

钩子函数触发时机作用
constructor创建组件时,最先执行1.初始化state;2.为事件处理程序绑定this
render每次组件渲染都会触发渲染UI(注意:不能调用setState())
componentDidMount组件挂载(完成DOM渲染)后1.发送网络请求;2.DOM操作
2.更新时(更新阶段)

执行时机:1.setState();2.forceUpdate();3.组件接收到新的props

说明:以上三者任意一种变化,组件就会重新渲染

执行顺序:render()——>componentDidUpdate()

钩子函数触发时机作用
render每次组件渲染都会触发渲染UI(与挂载阶段是同一render)
componentDidUpdate组件更新(完成DOM渲染后)1.发送网络请求;2.DOM操作 注意:如果要setState()必须放在一个if条件中

如果要发起网络请求,一般是在挂载阶段的componentDidMount()里面执行,因为在更新阶段要有执行时机,才会触发componentDidUpdate()

3.卸载时(卸载阶段)

执行时机:组件从页面中消失

钩子函数触发时机作用
componentWillUnmount组件卸载(从页面中消失)执行清理工作(比如:清理定时器,移除监听事件等)
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            // 计数器
            count: 0
        }
    }
    render() {
        return (
            <div>
                {
                    this.state.count > 5 ? <Line /> : <Counter count={this.state.count }/>
                }
                <button onClick={ this.handle}>+1</button>
            </div>
        )
    }
    // 处理count
    handle = () => {
        this.setState({
            count: this.state.count+1
        })
    }
}
// count>5之后,就显示Line组件
class Line extends React.Component {
    render() {
        return (
            <div>
                <p>豆豆上天了</p>
            </div>
        )
    }
}
// count<=5时,显示的是Counter组件
class Counter extends React.Component {
    // 故而在阶段
    componentDidMount() {
        this.timer = setInterval(() => {
            console.log("计数器正在执行中");
        },1000)
    }
    render() {
        return (
            <div>
                <p>豆豆被打的次数:{ this.props.count}</p>
            </div>
        )
    }
    // 卸载阶段
    // 这个组件不存在了,或者被其他组件替换了,困就触发这个事件
    componentWillUnmount() {
        console.log('豆豆上天了,Counter组件被Line组件替换了,不存在了');
        clearInterval(this.timer)
    }
 }

ReactDOM.render(
    <div><App /></div>,
    document.getElementById('root')
);

React路由

SPA:单页面程序,就是只有一个html页面的应用程序;用户体验更好、对服务器的压力更小,所以更受欢迎。一个组件就是页面

前端路由的功能:让用户从一个视图(页面)导航到另一个视图(页面)

前端路由式一套映射规则,在React中,是URL路径与组件的对应关系

使用React路由就是配置路径和组件(配对)

使用步骤:

1.安装:

yarn add react-router-dom
npm i react-router-dom

2.导入(按需导入)路由的三个核心组件:Router,Route,Link

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

Router是BrowserRouter的别名,按需导入的别名用as实现,解构数据的别名用**😗*实现

3.使用Router组件标签包裹整个应用

4.使用Link组件作为导航菜单(路由入口),相当于一个a标签,要有to属性(类似a标签的href属性),

5.使用Route组件配置路由规则和要战士的组件(路由出口),要有path属性和component,

<Router>
//路由入口
	<Link to="/One">到One组件页面去</Link>
	//路由出口
	<Route path='/One' component={One}></Route>
</Router>
import React from 'react';
import ReactDOM from 'react-dom';
// 按需导入
// BrowserRouter as Router:按需导入BrowserRouter,用as,给它取个别名Router
import { BrowserRouter as Router, Route, Link } from "react-router-dom"
// /One页面
const One = () => {
    return (
        <div>
            我是第一个页面
        </div>
    )
}
// App页面
class App extends React.Component {
    render() {
        return (
            <Router>
                {/* 路由入口 */}
                <Link to="/One">到One组件页面去</Link>
                {/* 路由出口 */}
                <Route path='/One' component={One}></Route>
            </Router>
        )
    }
}


ReactDOM.render(
    <div><App /></div>,
    document.getElementById('root')
);

常用组件说明

Router组件:包裹整个应用,一个React应用只需要使用一次

两种常用Router:HashRouterBrowserRouter

HashRouter:使用URL的哈希值实现(localhost/#/One)

(推荐)BrowserRouter:使用H5的historyAPI实现(localhost:3000/One)

匹配模式

import React from 'react';
import ReactDOM from 'react-dom';
// 按需导入
// BrowserRouter as Router:按需导入BrowserRouter,用as,给它取个别名Router
import { BrowserRouter as Router, Route, Link } from "react-router-dom"
// Login页面
class Login extends React.Component {
    handleLogin = () => {
        // 编程式导航
        // 跳转到某个页面
        this.props.history.push('/home')
    }
    render() {
        return (
            <div>
                我是Login页面
                <button onClick={this.handleLogin}>Home</button>
            </div>
        )
    }
}
// Home页面
// 因为是函数组件,所有没有自己的状态
const Home = props => {
    const handleBack = () => {
        // 编程式导航
        // 退回上一页
        props.history.go(-1)
    }
    return (
        <div>
            <h3>我是Home页面</h3>
            <button onClick={handleBack}>Login</button>
        </div>
    )
}
// 默认显示的页面
const Hello = () => {
    return (
        <div>
            <p>hello</p>
        </div>
    )
}
// App页面,整个应用界面
// 在Router标签里面,不要弄编程式导航,因为需要用到props,可是这个App是一级的,没有组件给它传值,所以编程式导航实现不了
class App extends React.Component {
    render() {
        return (
            <Router>
                <div>
                    {/* 路由入口 ,相当一个a标签*/}
                    {/*模糊匹配: to="/hello/login/home",原意是想去home页面,但是匹配的结果是:三个页面都匹配到了 */}
                    {/*精确匹配: 想要精确匹配到某个页面 ,就在该路由出口Route标签添加exact属性*/}
                    <Link to="/hello/login/home">登录</Link>
                    {/* 路由出口 */}
                    {/* 默认路由 */}
                    <Route exact path='/hello' component={Hello}></Route>
                    <Route exact path='/hello/login' component={Login}></Route>
                    <Route exact path='/hello/login/home' component={Home}></Route>
                </div>
            </Router>
        )
    }
}

ReactDOM.render(
    <div><App /></div>,
    document.getElementById('root')
);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值