React入门笔记(四):React生命周期、插槽、路由

五、React生命周期

5.1、钩子函数

生命周期即是组件从实例化到渲染到最终从页面销毁,整个过程就是生命周期,在这个生命周期中,我们有许多可以调用的事件,我们也俗称为钩子函数

生命周期的三个状态:

  1. Mounting:将组件插入到dom
  2. 将数据更新到dom
  3. unmounting:将组件移除dom

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

  1. ComponentWillMount:组件将要渲染,Ajax,添加动画前的类
  2. ComponentDidMount:组件渲染完毕,添加动画
  3. ComponentWillReceiveProps:组件将要接收props数据,查看接收的props数据是什么
  4. ShouldComponentUpdate:组件接收到新的state或者props,判断是否要更新,返回布尔值
  5. ComponentWillUpdate:组件将要更新
  6. ComponentDidUpdate:组件已经更新
  7. ComponentWillUnmount:组件将要卸载
import React, { Component } from "react";
import ReactDOM from "react-dom";

class ComLife extends Component {
  constructor(props) {
    super(props);
    this.state = {
      msg: "你好",
    };
    console.log("constructor构造函数");
  }

  componentWillMount() {
    console.log("componentWillMount组件将要渲染");
  }

  componentDidMount() {
    console.log("componentDidMount组件渲染完毕");
  }

  componentWillReceiveProps() {
    console.log("componentWillReceiveProps组件将要接受新的状态state和props");
  }

  shouldComponentUpdate() {
    //如果希望更新就返回为真,不希望更新就返回为false
    console.log("进行判断是否要更新");
    if (this.state.msg === "你好") {
      return true;
    } else {
      return false;
    }
  }

  componentWillUpdate() {
    console.log("componentWillUpdate组件将要更新");
  }

  componentDidUpdate() {
    console.log("componentDidUpdate组件更新完毕");
  }

  componentWillUnmount() {
    console.log("componentWillUnmount组件将要移除");
  }

  changeMsg = () => {
    this.setState({
      msg: "你好,陈",
    });
  };

  render() {
    console.log("render渲染函数");
    return (
      <div>
        <h1>{this.state.msg}</h1>
        <button onClick={this.changeMsg}>组件更新</button>
      </div>
    );
  }
}

class ParentCom extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isShow: true,
    };
  }

  removeCom = () => {
    this.setState({
      isShow: false,
    });
  };

  render() {
    if (this.state.isShow) {
      return (
        <div>
          <button onClick={this.removeCom}>移除ComLife</button>
          <ComLife />
        </div>
      );
    } else {
      return <h1>将ComLif移除</h1>;
    }
  }
}

ReactDOM.render(<ParentCom />, document.getElementById("root"));

image-20200621201157072

image-20200621201208463

六、React插槽

6.1、插槽介绍

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

6.2、使用props.children实现插槽

原理:组件中写入的HTML可以传入到props

import React, { Component } from "react";
import ReactDOM from "react-dom";

class ParentCom extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        <h1>组件插槽</h1>
        {this.props.children}
      </div>
    );
  }
}

ReactDOM.render(
  <ParentCom>
    <h2>子组件1</h2>
    <h2>子组件2</h2>
    <h2>子组件3</h2>
  </ParentCom>,
  document.getElementById("root")
);

image-20200622191143265

插槽也可以获取元素的值:

import React, { Component } from "react";
import ReactDOM from "react-dom";

class ParentCom extends Component {
  render() {
    console.log(this.props);
    return (
      <div>
        <h1>组件插槽</h1>
        {this.props.children}
      </div>
    );
  }
}

class RootCom extends Component {
  constructor(props) {
    super(props);
    this.state = {
      arr: [1, 2, 3],
    };
  }
  render() {
    return (
      <ParentCom>
        <h2 data-name="a" data-index={this.state.arr[0]}>
          子组件1
        </h2>
        <h2 data-name="b" data-index={this.state.arr[1]}>
          子组件2
        </h2>
        <h2 data-name="c" data-index={this.state.arr[2]}>
          子组件3
        </h2>
      </ParentCom>
    );
  }
}

ReactDOM.render(<RootCom></RootCom>, document.getElementById("root"));

image-20200622191829249

在做一个小例子,通过获取插槽内元素的值来动态的判断div放置的位置:

import React, { Component } from "react";
import ReactDOM from "react-dom";

class ParentCom extends Component {
  render() {
    console.log(this.props);
    return (
      <div>
        <h1>组件插槽</h1>
        {this.props.children}
        <ChildCom>
          <h1 data-position="header">这是放置到头部的内容</h1>
          <h1 data-position="main">这是主要的内容</h1>
          <h1 data-position="footer">这是放置到尾部的内容</h1>
        </ChildCom>
      </div>
    );
  }
}

class ChildCom extends Component{
  render(){
    let headerCom,mainCom,footerCom
    this.props.children.forEach((item,index)=>{
      if(item.props['data-position']==='header'){
        headerCom = item
      }else if(item.props['data-position']==='main'){
        mainCom = item
      }else{
        footerCom = item
      }
    })
    return(
      <div>
        <div className="header">
          {headerCom}
        </div>
        <div className="main">
          {mainCom}
        </div>
        <div className="footer">
          {footerCom}
        </div>
      </div>
    )
  }
}

class RootCom extends Component {
  constructor(props) {
    super(props);
    this.state = {
      arr: [1, 2, 3],
    };
  }
  render() {
    return (
      <ParentCom>
        <h2 data-name="a" data-index={this.state.arr[0]}>
          子组件1
        </h2>
        <h2 data-name="b" data-index={this.state.arr[1]}>
          子组件2
        </h2>
        <h2 data-name="c" data-index={this.state.arr[2]}>
          子组件3
        </h2>
      </ParentCom>
    );
  }
}

ReactDOM.render(<RootCom></RootCom>, document.getElementById("root"));

image-20200622192707337

组件中的HTML直接可全部插入,也可以通过条件判断来决定插入的位置

七、React路由

7.1、路由介绍

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

安装:

yarn add react-router-dom  或 npm install --save add react-router-dom
7.2、路由三大组件
  • Router:所有路由组件的根组件(底层组件),包裹路由规则的最外层容器
  • Route:路由规则匹配组件,显示当前规则对应的组件
  • Link:路由跳转的组件

注意:如果要精确匹配,那么可以在Route上设置exact属性

使用history模式制作一个建议的导航:

import React, { Component } from 'react';
// hash模式
// import {HashRouter as Router,Link,Route} from 'react-router-dom'

// history模式 后端配合使用
import {BrowserRouter as Router,Link,Route} from 'react-router-dom'


function Home(){
  return(
    <div>
      <h1>首页</h1>
    </div>
  )
}

function Me(){
  return(
    <div>
      <h1>个人中心</h1>
    </div>
  )
}

function Product(){
  return(
    <div>
      <h1>产品页面</h1>
    </div>
  )
}

class App extends Component{
  render(){
    return(
      <div id="app">
        <Router  basename="/admin">
          <div className="nav">
            <Link to="/">Home</Link>
            <Link to="/product">Product</Link>
            <Link to="/me">个人中心</Link>
          </div>
          <Route path="/" exact component={Home}></Route>
          <Route path="/product" component={Product}></Route>
          <Route path="/me" component={Me}></Route>
        </Router>
      </div>
    )
  }
}

export default App;

image-20200622194804418

可以通过设置basename来规定根路径,也可以使用exact来达到精确匹配,Router可以在一个组件写多个

import React, { Component } from "react";
// hash模式
// import {HashRouter as Router,Link,Route} from 'react-router-dom'

// history模式 后端配合使用
import { BrowserRouter as Router, Link, Route } from "react-router-dom";

function Home() {
  return (
    <div>
      <h1>admin首页</h1>
    </div>
  );
}

function Me() {
  return (
    <div>
      <h1>admin个人中心</h1>
    </div>
  );
}

function Product() {
  return (
    <div>
      <h1>admin产品页面</h1>
    </div>
  );
}

class App extends Component {
  render() {
    return (
      <div id="app">
        <div>所有页面普通内容</div>
        <Router>
          <Route path="/" exact component={() => <div>首页</div>}></Route>
          <Route path="/me" component={() => <div>个人中心</div>}></Route>
          <Route path="/product" component={() => <div>产品</div>}></Route>
        </Router>
        <Router>
          {/* <div className="nav">
            <Link to="/">Home</Link>
            <Link to="/product">Product</Link>
            <Link to="/me">个人中心</Link>
          </div> */}
          <Route path="/admin/" exact component={Home}></Route>
          <Route path="/admin/product" component={Product}></Route>
          <Route path="/admin/me" exact component={Me}></Route>
        </Router>
      </div>
    );
  }
}

export default App;

Link组件中的to可以直接写路径,也可以通过对象,进行更详细的配置

render() {
    let meObj = {
      pathname: "/me",//跳转的路径
      search: "?username=admin",//get请求的参数
      hash: "#abc",//设置的hash值
      state: { msg: "hello" },//传入组件的数据
    };
    return (
      <div id="app">
        <div>所有页面普通内容</div>
        <Router>
          <Route path="/" exact component={() => <div>首页</div>}></Route>
          <Route path="/me" component={() => <div>个人中心</div>}></Route>
          <Route path="/product" component={() => <div>产品</div>}></Route>
        </Router>
        <Router>
          <div className="nav">
            <Link to="/">Home</Link>
            <Link to="/product">Product</Link>
            <Link to={meObj}>个人中心</Link>
          </div>
          <Route path="/admin/" exact component={Home}></Route>
          <Route path="/admin/product" component={Product}></Route>
          <Route path="/admin/me" exact component={Me}></Route>
        </Router>
      </div>
    );
  }

Link的replace属性,点击链接后,将新地址替换成历史访问记录的原地址

<Link to={meObj} replace>个人中心</Link>

7.3、动态路由实现
function News(props){
  console.log(props)
  return(
    <div>
      新闻页
      新闻id:{props.match.params.id}
    </div>

  )
}

...

<Router>
          <div className="nav">
            <Link to="/">Home</Link>
            <Link to="/product">Product</Link>
            <Link to="/news/456789">新闻页面</Link>
            <Link to={meObj} replace>个人中心</Link>
          </div>
          <Route path="/admin/" exact component={Home}></Route>
          <Route path="/admin/product" component={Product}></Route>
          <Route path="/admin/me" exact component={Me}></Route>
          <Route path="/news/:id" component={News}></Route>
        </Router>

image-20200622202336013

7.4、重定向组件

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

import React, { Component } from "react";
// hash模式
// import {HashRouter as Router,Link,Route} from 'react-router-dom'

// history模式 后端配合使用
import {
  BrowserRouter as Router,
  Link,
  Route,
  Redirect,
} from "react-router-dom";

function LoginInfo(props) {
  // props.LoginState = 'success'
  // props.LoginState = 'fail'
  if (props.location.state.loginState === "success") {
    return <Redirect to="/admin"></Redirect>;
  } else {
    return <Redirect to="/login"></Redirect>;
  }
}

let FormCom = () => {
  let pathObj = {
    pathname:"/login_info",
    state:{
      loginState:"success"
    }
  }
  return (
    <div>
      <h1>表单验证</h1>
      <Link to={pathObj}>登陆验证后页面</Link>
    </div>
  );
};

class App extends Component {
  render() {
    return (
      <div>
        <Router>
          <Route path="/" exact component={() => <h1>首页</h1>}></Route>
          <Route path="/form" exact component={FormCom}></Route>
          <Route path="/login" exact component={() => <h1>登陆页</h1>}></Route>
          <Route path="/login_info" exact component={LoginInfo}></Route>
          <Route path="/admin" exact component={() => <h1>admin页,登录成功</h1>}></Route>
        </Router>
      </div>
    );
  }
}

export default App;

7.5、Switch组件

Switch组件内容的route只匹配一个,只要匹配到了,剩余的路由规则将不被匹配

render() {
    return (
      <div>
        <Router>
          <Switch>
            <Route path="/" exact component={() => <h1>首页</h1>}></Route>
            <Route path="/form" exact component={FormCom}></Route>
            <Route path="/login" exact component={() => <h1>登陆页</h1>}></Route>
            <Route path="/login_info" exact component={LoginInfo}></Route>
            <Route path="/admin" exact component={() => <h1>admin页,登录成功</h1>}></Route>
            <Route path="/abc" exact component={() => <h1>abc1</h1>}></Route>
            <Route path="/abc" exact component={() => <h1>abc2</h1>}></Route>
          </Switch>
        </Router>
      </div>
    );
  }

image-20200622210156066

7.6、使用js跳转页面

使用propshistroy中的属性和方法来进行页面路由的跳转:

class ChildCom extends Component{

  clickEvent = () =>{
    //console.log(this.props)
    this.props.history.push('/',{msg:"这是由ChildCom发给首页的数据"})
    this.props.history.replace('/',{msg:"这是由ChildCom发给首页的数据"})
      //前进
    this.props.history.go(1)
    this.props.history.goForward(1)
    //后退
    this.props.history.go(-1)
    this.props.history.goBack(-1)
  }

  render(){
    return(
      <div>
        <button onClick={this.clickEvent}>跳转到首页</button>
      </div>
    )
  }
}

image-20200622211116940

props.match可以获取到动态路由传递的参数:

<Route path="/:id" exact component={(props) => {console.log(props); return (<h1>首页</h1>)}}></Route>

image-20200622211538258

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值