IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> React笔记2——ReactAjax和React路由 -> 正文阅读

[JavaScript知识库]React笔记2——ReactAjax和React路由

React笔记2——ReactAjax和React路由

三、ReactAjax

1、脚手架配置

  1. 首先,安装一个轻量级框架axios

    yarn add axios
    
  2. 在App组件中定义两个简单的按钮分别用来获取学生数据和汽车数据。在测试时,需要打开测试服务器进行监听。

    import React, { Component } from 'react'
    import axios from 'axios'
    
    export default class App extends Component {
    	getStudentData = () => {
    		axios.get('http://localhost:3000/api1/students').then(
    			response => {console.log('成功了', response.data);},
    			error => {console.log('失败了', error);}
    		)
    	}
    
    	getCarData = () => {
    		axios.get('http://localhost:3000/api2/cars').then(
    			response => {console.log('成功了', response.data)},
    			error => {console.log('失败了', error);}
    		)
    	}
    
    	render() {
    		return (
    			<div>
    				<button onClick={this.getStudentData}>点我获取学生数据</button>
    				<button onClick={this.getCarData}>点我获取汽车数据</button>
    			</div>
    		)
    	}
    }
    
    
  3. 进行脚手架的配置,在src文件夹下创建setupProxy.js文件。因为配置文件一个项目只需要写一次,所以每次只需要把该文件进行复制粘贴即可。配置文件如下:(该项目因为向两个不同的服务器发送了请求,所以设置了两个代理)

    const proxy = require('http-proxy-middleware')
    
    module.exports = function(app) {
      app.use(
        proxy('/api1', { //遇见'/api1'前缀的请求,就会触发该代理配置
          target: 'http://localhost:5000', //请求转发给谁
          changeOrigin: true, //控制服务器收到的响应头中Host字段的值(这条写不写影响不大)
          pathRewrite: {'^/api1':''} //重写请求路径(必须的,用于走代理时将'/api1'换成空字符串)
        }),
        proxy('/api2', {
          target: 'http://localhost:5001',
          changeOrigin: true,
          pathRewrite: {'^/api2':''}
        })
      )
    }
    
  4. 代理配置总结

  • 方法1:

    在package.json中追加如下配置

    "proxy":"http://localhost:5000"
    

    说明:

    1. 优点:配置简单,前端请求资源时可以不加任何前缀。
    2. 缺点:不能配置多个代理。
    3. 工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)
  • 方法2:

    1. 第一步:创建代理配置文件

      在src下创建配置文件:src/setupProxy.js
      
    2. 编写setupProxy.js配置具体代理规则:

      const proxy = require('http-proxy-middleware')
      
      module.exports = function(app) {
        app.use(
          proxy('/api1', {  //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
            target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
            changeOrigin: true, //控制服务器接收到的请求头中host字段的值
            /*
            	changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
            	changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
            	changeOrigin默认值为false,但我们一般将changeOrigin值设为true
            */
            pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
          }),
          proxy('/api2', { 
            target: 'http://localhost:5001',
            changeOrigin: true,
            pathRewrite: {'^/api2': ''}
          })
        )
      }
      

    说明:

    1. 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
    2. 缺点:配置繁琐,前端请求资源时必须加前缀。

2、github搜索案例

  1. 将静态页面拆成React的Search、Item、List组件

  2. 将公共的样式放在App.css中,单独的样式也拆到各自的index.css里(该案例样式较为简单,所以只有List组件中有样式)

  3. state都定义在App组件中方便进行修改;App组件中定义了一个修改state的方法updateAppState并将其传给了Search组件

    import React, { Component } from 'react'
    import Search from './components/Search'
    import List from './components/List'
    
    export default class App extends Component {
    	state = {    //初始化状态
    		users: [], //users初始值为数组
    		isFirst: true, //是否为第一次打开页面
    		isLoading: false, //标识是否处于加载中
    		err: '', //存储请求相关的错误信息
    	} 
    
    	updateAppState = (stateObj) => {
    		this.setState(stateObj)
    	}
    
    	render() {
    		return (
    			<div className="container">
    				<Search updateAppState={this.updateAppState} />
    				<List {...this.state} />
    			</div>
    		)
    	}
    }
    
    
  4. Search组件

    1. 导入axios框架用于向github接口发送get请求;

    2. 利用ref核心属性给Search实例对象添加keyWordElement属性,该属性对应着input标签。同时keyWordElement是一个对象,它有一个value属性,该属性对应着input标签中输入的文字。

    3. 我们将该value属性重新赋值为keyword,并通过axios将关键字作为参数发送出去

      import React, { Component } from 'react'
      import axios from 'axios'
      
      export default class Search extends Component {
        search = () => {
          // 获取用户的输入(连续解构赋值+重命名)
          const {keyWordElement: {value:keyword}} = this
          
          // 发送请求前通知App更新状态
          this.props.updateAppState({isFirst:false, isLoading:true})
      
          // 发送网络请求
          // 因为我们端口是3001,也从该端口发送请求,所以可以省略http://localhost:3001
          axios.get(`/api1/search/users?q=${keyword}`).then(
            response => {
              // 请求成功后通知APP更新状态
              this.props.updateAppState({isLoading:false, users:response.data.items})
              // console.log(response);
            },
            error => {
              // 请求失败后通知APP更新状态
              this.props.updateAppState({isLoading: false, err: error.message, users: []})
              // console.log('失败了', error);
            }
          )
        }
      
        render() {
          return (
            <section className="jumbotron">
              <h3 className="jumbotron-heading">搜索Github用户</h3>
              <div>
                <input ref={c => this.keyWordElement = c} type="text" placeholder="输入关键字点击搜索"/>&nbsp;
                 <button onClick={this.search} >搜索</button>
              </div>
          </section>
          )
        }
      }
      
      
  5. List组件

    1. App组件通过展开运算符把state所有属性通过props传递给List组件

    2. List通过解构赋值拿到必要的属性

    3. jsx只能写js表达式,而不能写for/if/switch这类js语句。故条件判断这里使用三元运算符。重点:三元表达式可以进行连续判断,效果相当于if语句

    4. 利用map对users数组进行处理,每个元素单独返回,并通过props将所有user属性传给Item组件

      import React, { Component } from 'react'
      import './index.css'
      import Item from '../Item'
      
      
      export default class List extends Component {
        render() {
          const {isFirst, users, isLoading, err} = this.props
          return (
            <div className="row">
              {
                isFirst ? <h2>欢迎使用,输入关键字,随后点击搜索</h2> :
                isLoading ? <h2>加载中...</h2> :
                err ? <h2 style={{color:'red'}}>{err}</h2> :
                users.map((user) => {
                  return <Item key={user.id} {...user} />
                })
              }
            </div>
          )
        }
      }
      
      
  6. Item组件

    1. 对我们需要的user属性进行解构赋值,包括头像链接、用户仓库链接和用户名

    2. 将属性通过{}放在需要显示数据的位置

      import React, { Component } from 'react'
      
      export default class Item extends Component {
        render() {
          const {avatar_url, html_url, login} = this.props
          return (
            <div className="card">
              <a rel="noreferrer" href={html_url} target="_blank">
                <img alt='avatar' src={avatar_url} style={{width: '100px'}}/>
              </a>
              <p className="card-text">{login}</p>
            </div>
          )
        }
      }
      
  7. 代理文件

    const proxy = require('http-proxy-middleware')
    
    module.exports = function(app) {
      app.use(
        proxy('/api1', { //遇见'/api1'前缀的请求,就会触发该代理配置
          target: 'http://localhost:5000', //请求转发给谁
          changeOrigin: true, //控制服务器收到的响应头中Host字段的值(这条写不写影响不大)
          pathRewrite: {'^/api1':''} //重写请求路径(必须的,用于走代理时将'/api1'换成空字符串)
        })
      )
    }
    
  8. 总结

    1. 设计状态时要考虑全面,例如带有网络请求的组件,要考虑请求失败怎么办。
    2. ES6小知识点:解构赋值+重命名
      let obj = {a:{b:1}}
      const {a} = obj; //传统解构赋值
      const {a:{b}} = obj; //连续解构赋值
      const {a:{b:value}} = obj; //连续解构赋值+重命名

3、消息订阅-发布机制

  1. 使用PubSub

    1. 安装pubsub-js

      yarn install pubsub-js
      
    2. 使用方法(https://github.com/mroderick/PubSubJS)

      1. import PubSub from ‘pubsub-js’ //引入
      2. PubSub.subscribe(‘delete’, function(data){ }); //订阅
      3. PubSub.publish(‘delete’, data) //发布消息
  2. PubSub简化了App组件,因为该方法可以实现兄弟组件间的通信

  3. 简化的App组件

    import React, { Component } from 'react'
    import Search from './components/Search'
    import List from './components/List'
    
    export default class App extends Component {
    	
    	render() {
    		return (
    			<div className="container">
    				<Search />
    				<List />
    			</div>
    		)
    	}
    }
    
  4. Search组件

    1. 导入PubSub工具库,导入axios框架

    2. 使用PubSub.publish()方法发布消息,更新兄弟组件List的state

      import React, { Component } from 'react'
      import PubSub from 'pubsub-js'
      import axios from 'axios'
      
      export default class Search extends Component {
      
      
        search = () => {
       
          // 获取用户的输入(连续解构赋值+重命名)
          const {keyWordElement: {value:keyword}} = this
          
          // 发送请求前通知List更新状态
      this.props.updateAppState({isFirst:false, isLoading:true})
          PubSub.publish('atguigu', {isFirst:false, isLoading:true})
      
          // 发送网络请求
          // 因为我们端口是3000,也从该端口发送请求,所以可以省略http://localhost:3000
          axios.get(`/api1/search/users?q=${keyword}`).then(
            response => {
              // 请求成功后通知List更新状态
            PubSub.publish('atguigu', {isLoading:false, users:response.data.items})
              
            },
            error => {
              // 请求失败后通知List更新状态
             PubSub.publish('atguigu', {isLoading: false, err: error.message, users: []})
            }
          )
        
        }
      
        render() {
          return (
            <section className="jumbotron">
              <h3 className="jumbotron-heading">搜索Github用户</h3>
              <div>
                <input ref={c => this.keyWordElement = c} type="text" placeholder="输入关键字点击搜索"/>&nbsp;
                 <button onClick={this.search} >搜索</button>
              </div>
          </section>
          )
        }
      }
      
      
  5. List组件

    1. state状态放在List组件中

    2. 在componentDidMount钩子函数中使用PubSub.subscribe()方法接收消息

    3. 在componentWillUnmount钩子函数中取消订阅

      import React, { Component } from 'react'
      import PubSub from 'pubsub-js'
      import './index.css'
      import Item from '../Item'
      
      
      export default class List extends Component {
      
        state = {    //初始化状态
      		users: [], //users初始值为数组
      		isFirst: true, //是否为第一次打开页面
      		isLoading: false, //标识是否处于加载中
      		err: '', //存储请求相关的错误信息
        }
      
        componentDidMount() {
          this.token = PubSub.subscribe('atguigu', (_, stateObj) => {
            // console.log('List组件收到数据了', data);
            this.setState(stateObj)
          })
        }
      
        componentWillUnmount() {
          PubSub.unsubscribe(this.token)
        }
      
        render() {
          const {isFirst, users, isLoading, err} = this.state
          return (
            <div className="row">
              {/* jsx只能写js表达式,而不能写for/if/switch这类js语句。故条件判断这里使用三元运算符。三元表达式可以进行连续判断 */}
              {
                isFirst ? <h2>欢迎使用,输入关键字,随后点击搜索</h2> :
                isLoading ? <h2>加载中...</h2> :
                err ? <h2 style={{color:'red'}}>{err}</h2> :
                users.map((user) => {
                  return <Item key={user.id} {...user} />
                })
              }
            </div>
          )
        }
      }
      
      
  6. Item组件

    Item组件还保持跟之前一样。

四、React路由

1.react-router-dom

  • react的一个插件库。

  • 专门用来实现一个SPA应用。

  • 基于react的项目基本都会用到此库。

  • 安装react-router-dom

    yarn add react-router-dom
    

2.路由的基本使用

  1. 明确好界面中的导航区、展示区

  2. 导航区的a标签改为Link标签

    <Link to="/xxxxx">Demo</Link>
    
  3. 展示区写Route标签进行路径的匹配

    <Route path='/xxxx' component={Demo}/>
    
  4. 的最外侧包裹了一个或

3.一个简单的路由跳转实例

  1. App组件,导入Link和Route

    import React, { Component } from 'react'
    import {Link, Route} from 'react-router-dom'
    import Home from './components/Home'
    import About from './components/About'
    
    export default class App extends Component {
    	render() {
    		return (
    			<div>
    				<div className="row">
    					<div className="col-xs-offset-2 col-xs-8">
    						<div className="page-header"><h2>React Router Demo</h2></div>
    					</div>
    				</div>
    				<div className="row">
    					<div className="col-xs-2 col-xs-offset-2">
    						<div className="list-group">
    							{/* 原生html中,靠<a>跳转不同的页面 */}
    							{/* <a className="list-group-item" href="./about.html">About</a>
    							<a className="list-group-item active" href="./home.html">Home</a> */}
    
    							{/* 在React中靠路由链接实现切换组件 */}
    							<Link className="list-group-item" to="/about">About</Link>
    							<Link className="list-group-item" to="/home">Home</Link>
    						</div>
    					</div>
    					<div className="col-xs-6">
    						<div className="panel">
    							<div className="panel-body">
    								{/* 注册路由 */}
    								<Route path="/home" component={Home}/>
    								<Route path="/about" component={About}/>				
    							</div>
    						</div>
    					</div>
    				</div>
    			</div>
    		)
    	}
    }
    
    
    
  2. components中的Home和About组件

    1. Home组件

      import React, { Component } from 'react'
      
      export default class Home extends Component {
        render() {
          return (
            <h3>我是Home的内容</h3>
          )
        }
      }
      
      
    2. About组件

      import React, { Component } from 'react'
      
      export default class About extends Component {
        render() {
          return (
            <h3>我是About的内容</h3>
          )
        }
      }
      
      

4.路由组件与一般组件

		1.写法不同:
					一般组件:<Demo/>
					路由组件:<Route path="/demo" component={Demo}/>
		2.存放位置不同:
					一般组件:components
					路由组件:pages
		3.接收到的props不同:
					一般组件:写组件标签时传递了什么,就能收到什么
					路由组件:接收到三个固定的属性
										history:
													go: ? go(n)
													goBack: ? goBack()
													goForward: ? goForward()
													push: ? push(path, state)
													replace: ? replace(path, state)
										location:
													pathname: "/about"
													search: ""
													state: undefined
										match:
													params: {}
													path: "/about"
													url: "/about"

5.NavLink的使用

? NavLink可以实现路由链接的高亮,通过activeClassName指定样式名。

  1. 将导入的Link改为NavLink

  2. 若不写activeClassName,则默认对点击的NavLink添加一个active的类。因为这里导入了bootstrap.css样式,里面本身自带有active的样式。

  3. 若要自定义样式,可在index.html文件中通过style定义样式

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8" />
    		<title>react脚手架</title>
    		<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    		<link rel="stylesheet" href="/css/bootstrap.css">
    		<style>
    			.leon{
    				background-color: pink !important;
    				/* color: white !important; */
    			}
    		</style>
    	</head>
    	<body>
    		<div id="root"></div>
    	</body>
    </html>
    
  4. App.jsx组件中的NavLink

    	<NavLink activeClassName="leon" className="list-group-item" to="/home">Home</NavLink>
    							<NavLink activeClassName="leon" className="list-group-item" to="/about">About</NavLink>
    
  5. 自定义MyNavLink标签

    1. 在components创建MyNavLink文件,在这里对NavLink进行一层封装

    2. App组件的属性皆可以通过props传送过来

      					{/* 在React中靠路由链接实现切换组件 */}
      							<MyNavLink to="/home">Home</MyNavLink>
      							<MyNavLink to="/about">About</MyNavLink>
      
    3. MyNavLink标签中的Home、About会作为children属性传送过来,故利用展开运算符,可以将所有属性以简便的方式赋值给NavLink中的属性,如下是MyNavLink组件

      import React, { Component } from 'react'
      import {NavLink} from 'react-router-dom'
      
      export default class MyNavLink extends Component {
      
        render() {
          // console.log(this.props);
      
          return (
            <NavLink activeClassName="leon" className="list-group-item" {...this.props}/>
          )
        }  
      }
      
      

6.Switch的使用

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-20 12:24:14  更:2021-10-20 12:26:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 16:06:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码