React入门实战页面跳转(附完整代码)

Posted 安之ccy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React入门实战页面跳转(附完整代码)相关的知识,希望对你有一定的参考价值。

React入门实战二,通过此练习掌握如下知识点:

  • React路由跳转、路由参数等 —— react-router-dom
  • axios请求数据
  • 生命周期钩子componentDidMount的使用

数据使用:用第三方接口JsonPlaceHolder的 posts 数据,字段如下:

字段名描述
userId用户ID
id数据ID
titlepost标题
bodypost内容

涉及的组件:

组件描述
App.js主组件
Home.js展示Post
Navbar.js导航栏
About.js辅助路由的效果展示
Contact.js辅助路由的效果展示
SinglePost.jspost详情页(单条post记录展示)

基本搭建

先搭一下各个组件,由于导航栏和About组件只是用于展示的,所以使用UI组件;其他组件涉及的功能较为复杂,均为容器组件

App.js:

// 引入必要的组件
import React, { Component } from 'react'
import Navbar from './Navbar'

class App extends Component {
  render() {
    return (
        <div className="App">
          <Navbar />
        </div>
    );
  }
}

export default App;

Home.js组件:

import React, { Component } from 'react'

class Home extends Component {
    render() {
        return (
            <div className='container home'>
                <h1 className='center'>这是Home页面</h1>
            </div>
        )
    }
}

export default Home

About.js组件、Contact.js组件和Home组件一样,都只是显示一句话:这是About /Contact页面,就不列举了

Navbar.js,导航栏,在右侧设置三个组件的链接:Home、About、Contact

import React from 'react'

const Navbar = () => {
    return (
        <nav className='nav-wrapper red darken-3'>
            <div className='container'>
                <a href='/' className='brand-logo'>React入门实战(二)</a>

                <ul className='right'>
                    <li><a href='/'>Home页面</a></li>
                    <li><a href='/about'>About页面</a></li>
                    <li><a href='/contact'>Contact页面</a></li>
                </ul>
            </div>
        </nav>
    )
}

export default Navbar

SinglePost组件先不写

先来看看效果:

在这里插入图片描述



路由设置:

添加路由,实现点击Home、About、Contact三个页面切换的效果

App.js:

// 引入路由库
import { Route, BrowserRouter } from 'react-router-dom'
// 引入子组件
import Home from './Home';
import About from './About';
import Contact from './Contact';

// Route标签设置跳转路径
class App extends Component {
  	render() {
    	return (
      	<BrowserRouter>
        	<div className="App">
          		<Navbar />
        	</div>
        	<Route exact path='/' component={Home} />
        	<Route path='/about' component={About} />
        	<Route path='/contact' component={Contact} />
      </BrowserRouter>
    );
  }
}

export default App;

点击“About页面”即可切换到About页面,但每次点击都会再刷新一次页面,如果只是想跳转,不需要重新加载渲染,可以使用Link标签,减少DOM性能消耗(Link标签会被渲染成a标签,但节省了很多性能,还有一个Navlink标签,当链接被选中时,增加一个native的className)

用Link标签对导航栏中的三个跳转路径做修改(需引入react-router-dom库)

<ul className='right'>
    <li><Link to='/'>Home页面</Link></li>
    <li><Link to='/about'>About页面</Link></li>
    <li><Link to='/contact'>Contact页面</Link></li>
</ul>

效果:可以看到,切换页面时左上角那个刷新图标没有转动,即没有重新加载

在这里插入图片描述


axios请求数据与钩子函数componentDidMount()使用

  • 在Home页面装载完毕时,通过axios向JsonPlaceHolder发起数据请求;
  • 数据请求的过程在钩子函数componentDidMount()中进行;
  • 当axios请求得到回应,记为res,其中的data字段就是我们需要的数据,由于数据较多,只存储前20条记录;
  • 将得到的数据记录到state中(方便在render函数中取用);
  • 如果得到posts数据,就用JSX语法处理后渲染展示;否则提示正在加载中。
import React, { Component } from 'react'
import axios from 'axios'

class Home extends Component {
    state = {
        posts: null
    }
    componentDidMount() {
        // 向第三方库请求数据并保存到state中
        axios.get("http://jsonplaceholder.typicode.com/posts").then(res => {
            this.setState({
                posts: res.data.splice(0, 20)
            })
        })
    }
    render() {
        // 处理获得的数据
        const { posts } = this.state;
        // 如果得到posts数据,就用JSX语法处理后渲染展示;否则提示正在加载中
        const postsList = posts ? (
            posts.map(post => {
                return (
                    <div className='card post' key={post.id}>
                        <div className='card-content'>
                            <h3 className='card-title'>{post.title}</h3>
                            <p className='card-action'>{post.body}</p>
                        </div>
                    </div>
                )
            })

        ) : (
            <p className='center'>加载信息中,请稍候......</p>
        )
        return (
            < div className='container' >
                <h1 className='center'>这是Home页面</h1>
                {postsList}
            </div >
        )
    }
}

export default Home;

效果:展示出posts信息

在这里插入图片描述



单条post详情页:路由参数

  • 设置详情页的路由表
  • 点击某条post,就跳转到这条记录的详情页——Link标签与路由参数的使用
  • 详情页组件接收到路由参数,向第三方库请求数据,得到数据后展示
  • 为防止一个路由参数匹配到多条路径,使用Switch标签——只匹配单条路由

App.js 设置详情页路由,设置Switch匹配单条路径

<Switch>
    <Route exact path='/' component={Home} />
    <Route path='/about' component={About} />
    <Route path='/contact' component={Contact} />
    {/*详情页路由*/}
    <Route path='/:post_id' component={SinglePost} />
</Switch>

新建SinglePost.js,作为详情页组件

import React, { Component } from 'react'
import axios from 'axios'

class SinglePost extends Component {
    state = {
        post: []
    }
    componentDidMount() {
        // 请求单页数据并存储到state
        const post_id = this.props.match.params.post_id
        axios.get("http://jsonplaceholder.typicode.com/posts/" + post_id).then(res => {
            this.setState({
                post: res.data
            })
        })
    }
    render() {
        // 从state中取出数据并加工
        const { post } = this.state;
        const postShow = post ? (
            <div className='collection-item' key={post.id}>
                <h3 className='center'>{post.title}</h3>
                <p>{post.body}</p>
            </div>
        ) : (
            <div className='center'>还在加载中......</div>
        )
        return (
            <div className='container'>
                <div className='collection'>
                    {postShow}
                </div>
            </div>
        )
    }
}

export default SinglePost;

在Home.js中,将post的title部分包裹上Link标签,让用户可以点击跳转

<Link to={'/' + post.id}>
    <h3 className='card-title'>{post.title}</h3>
</Link>

最后再加上图片背景,在index.css中加样式

最终效果如下:

在这里插入图片描述


完整代码

App.js:

import React, { Component } from 'react'
import Navbar from './Navbar';
import { Route, BrowserRouter, Switch } from 'react-router-dom'

import Home from './Home';
import About from './About';
import Contact from './Contact';
import SinglePost from './SinglePost';

class App extends Component {
  render() {
      return (
          <BrowserRouter>
              <div className="App">
                  <Navbar />
              </div>
              <Switch>
                  <Route exact path='/' component={Home} />
                  <Route path='/about' component={About} />
                  <Route path='/contact' component={Contact} />
                  <Route path='/:post_id' component={SinglePost} />
              </Switch>
          </BrowserRouter>
      );
  }
}

export default App;

Home.js

import React, { Component } from 'react'
import axios from 'axios'
import { Link } from 'react-router-dom'
import MyImg from './1.jpg'

class Home extends Component {
    state = {
        posts: null
    }
    componentDidMount() {
        // 向第三方库请求数据并保存到state中
        axios.get("http://jsonplaceholder.typicode.com/posts").then(res => {
            this.setState({
                posts: res.data.splice(0, 20)
            })
        })
    }
    render() {
        // 解构
        const { posts } = this.state;
        const postsList = posts ? (
            posts.map(post => {
                return (
                    <div className='card post' key={post.id}>
                        <img src={MyImg} />
                        <div className='card-content'>
                            <Link to={'/' + post.id}>
                                <h3 className='card-title title center'>{post.title}</h3>
                            </Link>
                            <p className='card-action'>{post.body}</p>
                        </div>
                    </div>
                )
            })

        ) : (
            <p className='center'>加载信息中,请稍候......</p>
        )
        return (
            < div className='container home' >
                <h1 className='center'>这是Home页面</h1>
                {postsList}
            </div >
        )
    }
}

export default Home;

Navbar.js:

import React from 'react'
import {Link} from 'react-router-dom'

const Navbar = () => {
    return (
        <nav className='nav-wrapper red darken-3'>
            <div className='container'>
                <a href='/'className='brand-logo'>React入门实战(二)</a>
                <ul className='right'>
                    <li><Link to='/'>Home页面</Link></li>
                    <li><Link to='/about'>About页面</Link></li>
                    <li><Link to='/contact'>Contact页面</Link></li>
                </ul>
            </div>
        </nav>

    )
}

export default Navbar;

About.js:

import React from 'react'

const About = ()=>{
    return (
        <div className='container'>
            <h1 className='center'>这是About页面</h1>
        </div>
    )
}

export default About;

Contact.js:

import React from 'react'

const Contact = () => {
    return (
        <div className='container'>
            <h1 className='center'>这是Contact页面</h1>
        </div>
    )
}

export default Contact;

Single.js的全部代码在上文已经完整给出,这里不再重复

index.css文件里添加以下样式:

.home .post img {
  width: 20%;
  position: absolute;
  top: 10px;
  left:7px;
  opacity: 0.5;
}

.home .post .title {
  padding-left:150px
}

以上是关于React入门实战页面跳转(附完整代码)的主要内容,如果未能解决你的问题,请参考以下文章

React入门实战联系人列表Contact(附完整代码)

React入门实战联系人列表Contact(附完整代码)

天池赛题解析:零基础入门语义分割-地表建筑物识别-CV语义分割实战(附部分代码)

<前端组件化>拆分组件思想--吃饭睡觉打代码案例(附源码)

后台返回完整的HTML页面代码,如何打开展示

知识图谱完整项目实战(附源码)