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 的 hooks 和 路由 -> 正文阅读

[JavaScript知识库]React 的 hooks 和 路由

一.React的hooks ( 函数组件 )

1. 什么是 Hooks

  • React 一直都提倡使用函数组件,但是有时候需要使用 state 或者其他一些功能时,只能使用类组件,因为函数组件没有实例,没有生命周期函数,只有类组件才有.
  • Hooks 是 React 16.8 新增的特性,它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性.
  • 如果在编写函数组件时需要向添加一些 state,以前的做法是必须将其它转化为 class。现在可以直接在现有的函数组件中使用 Hooks.
  • 凡是 use 开头的 React API 都是 Hooks.

2.React Hooks 的用法

  1. userState() 状态钩子
  • 纯函数组件没有状态,useState()用于为函数组件引入状态
  • useState 唯一的参数就是初始 state
    useState 会返回一个数组:
    第一项是一个变量,指向状态的当前值, 类似this.state
    第二项是一个函数,用来更新状态,类似 setState
  • 下面的代码看起来更加的轻便简洁,没有了继承,没有了渲染逻辑,没有了生命周期等
    示例代码:
import React, {useState} from 'react'
function Parent() {
	// let [状态的值,修改状态的方法] = useState(状态的初始值)
    // let [name,setName] = React.useState('下雨了')
    let [name,setName] = React.useState({
        name: '小明',
        age:20
    })
    return (
        <div>
            <h1>状态的初始值是: {name.name}</h1>
            <h1>状态的初始值是: {name.age}</h1>
            <button onClick={() => {
                // setName('呵呵呵呵')
                setName({
                    name: '张三',
                    age:50
                })
            }}>修改状态的初始值</button>
        </div>
    )
}
  1. React 的 useEffect()
  • Effect Hook 可以让你在函数组件中执行副作用操作,这里的副作用操作,就是除了状态(数据)相关的逻辑,比如网络请求,监听事件,查找 dom。
useEffect(() => {},[array])
useEffect()接受两个参数,第一个参数是你要进行的异步操作,第二个参数是一个数组,用来给出Effect的依赖项
  • 类组件在绑定事件、解绑事件、设定定时器、查找 dom 的时候,是通过 componentDidMount、componentDidUpdate、componentWillUnmount 生命周期来实现的,而 useEffect 会在组件每次 render 之后调用,就相当于这三个生命周期函数,只不过可以通过传参来决定是否调用

决定useEffect的是第二个参数:

  • 什么都不传时,组件每次 render 之后 useEffect 都会调用,相当于 componentDidMount 和 componentDidUpdate
  • 传入一个空数组 [ ], 只会调用一次,相当于 componentDidMount 和 componentWillUnmount
  • 传入一个数组,其中包括变量,只有这些变量变动时,useEffect 才会执行
import React,{useEffect} from 'react';
function Parent() {
    // let [name,setName] = React.useState('下雨了')
    let [name,setName] = React.useState({
        name: '小明',
        age:20
    })
    //最简单用法
    useEffect(() => {
        //只有方法体,相当于componentDidMount和componentDidUpdate中的代码
        console.log('挂载了')
    })
    //加空数组参数用法
    useEffect(() => {
        // 相当于 componentDidMount
        return () => {
            // 相当于 componentWillUnmount
            console.log('卸载了')
        }
    },[])
    //监听值用法
    useEffect(() => {
        //只有当name的值发生变化,此函数才会执行
        console.log('更新了')
    },[name])

    return (
        <div>
            <h1>状态的初始值是: {name.name}</h1>
            <h1>状态的初始值是: {name.age}</h1>
            <button onClick={() => {
                // setName('呵呵呵呵')
                setName({
                    name: '张三',
                    age:50
                })
            }}>修改状态的初始值</button>
        </div>
    )
}
  1. useRef
    useRef跟类中的createRef类似,都可以用来获取DOM对象
import React,{useRef} from 'react';
function Parent() {
    // let [name,setName] = React.useState('下雨了')
    let [name,setName] = React.useState({
        name: '小明',
        age:20
    })
    let names = useRef()
    //最简单用法
    useEffect(() => {
        //只有方法体,相当于componentDidMount和componentDidUpdate中的代码
        console.log('挂载了')
        // 通过 current 获取到
        console.log(names.current)
    })
    
    return (
        <div>
            <h1 ref={names}>状态的初始值是: {name.name}</h1>
            <h1>状态的初始值是: {name.age}</h1>
            <button onClick={() => {
                // setName('呵呵呵呵')
                setName({
                    name: '张三',
                    age:50
                })
            }}>修改状态的初始值</button>
        </div>
    )
}

二. React 路由

1.前端路由介绍

现在的前端应用大部分都是 SPA (单页面应用程序),也就是只有一个 HTML 页面的应用程序,因为它的用户体验好,对服务器的压力更小,所以更受欢迎.为了有效的使用单个页面来管理原来多页面的功能,前端路由就出来了.

  • 前端路由的功能:让用户从一个视图(页面) 导航到另一个视图(页面),但是一定不会直接发送请求,它只是仅仅改变了浏览器地址栏上的URL
  • 前端路由是一套映射规则,在 React 中,是 URL 路径组件 的对应关系
  • 使用React路由简单来说,就是配置 路径组件

目前前端路由主要的模式:

  • 基于 URL Hash 的路由
  • 基于 HTML5 History API 的路由

2.安装react-router-dom

在项目命令行中,执行 npm install react-router-dom -S 下载到生产环境的依赖中。
在组件中通过对象的解构方式去获取到react-router-dom内置组件,在组件中,按需引入内置组件,在页面中进行使用

3.路由的三个核心组件:Router(BrowserRouter) / Route / Link

import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
BrowserRouter as Router: //这个as是起别名的意思,这句话的意思是BrowseerRouter起别名为Router,这样在下面的标签里就可以直接使用<Router></Router>了

4.使用 Router 组件包裹整个应用

  • Router 组件:包裹整个应用,一个 React 应用只需要使用一次
  • 两种常用 Router: HashRouter 和 BrowserRouter
  • HashRouter: 使用 URL 的哈希值实现,刷新页面后会导致路由state参数的丢失( localhost:3000/#/first )
  • BrowserRouter (推荐) : 使用 H5 的 history API 实现 ,不兼容IE9及以下版本,对路由state参数没有任何影响,因为state保存在history对象中( localhost:3000/first )
// 导入组件
import {BrowserRouter as Router} from 'react-router-dom'

// 使用 Router组件包裹整个应用
const App = () => (
  <Router>
    <h1>React路由基础</h1>
  </Router>
)

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

5.使用 Link 组件作为导航菜单(路由入口)

Link 组件用来处理 a 链接 类似的功能(Link会在页面中生成一个 a 标签),但设置这里需要注意的,react-router-dom 拦截了实际 a 标签的默认动作,然后根据所有使用的路由模式(Hash 或者 HTML5)来进行处理,改变了 URL,但不会发生请求,同时根据 Route 中的设置把对应的组件显示在指定的位置

Link: 用于指定导航链接 (a标签)
// to 属性: 浏览器地址栏中的 pathname 
// to 属性类似 a 标签中的 href,但不会跳转
<Link to="/first">页面一</Link>

6.NavLink 组件,NavLink 与 Link 类似,但是它提供了两个特殊属性用来处理页面导航

  • NavLink 可以实现路由链接的高亮,通过 activeClassName 指定样式名
  • 标签体内容是一个特殊的标签属性
  • 通过 this.props.children 可以获取标签体内容
<NavLink activeClassName="active" exact to="/">about</NavLink> |
<NavLink activeClassName="active" exact to="/home">home</NavLink>
    
activeStyle
	当前 URL 与 NavLink 中的 to 匹配的时候,激活 activeStyle 中的样式
activeClassName
	与 activeStyle 类似,但是激活的是 className

7.使用 Route 组件配置路由规则和要展示的组件(路由出口)

const First = () => <p>页面一的内容</p>
function App() {
  return (
    <div>
      <Link to="/first">页面一</Link> 
	 Route 组件:指定路由展示组件相关信息
          path 属性: 路由规则  (注意: path的属性要和Link组件的to属性一样)
          component 属性: 展示组件
          Route 组件写在哪里,渲染出来的组件就展示在哪
      <Route path="/first" component={First} />
      // 路由传参
      <Route path="/first" render={() => {
            return <First />
      }} />
    </div>
  );
}
ReactDOM.render(
  <Router>
    <App />
  </Router>,
  document.getElementById('root')
);

8.exact

exact是Route下的一个属性,react路由会匹配到所有能匹配到的路由组件,exact能够使得路由的匹配更严格。
exact的值为bool型,为true时表示严格匹配,为false时为正常匹配。
示例如下:

<Route path="/" component={About} />
<Route path="/home" component={Home} />
//以上这种情况下,如果匹配路由path='/home',那么About组件也会展示出来。
//就是路由path='/home'会匹配路由path='/'和路由path='/home'

// 解决办法: 通常会添加 exact 来解决上面的问题
// 这样匹配路由 path="/home", 只会匹配到 Home 组件
 <Route path="/" exact component={About} />
 <Route path="/home" exact component={Home} />

9.Switch 组件的使用

通常情况下,path 和 component 是一 一 对应的关系
Switch组件 可以提高路由匹配效率 ( 单一匹配 ) ( 只会渲染首个被匹配的组件 )

import {Route,Switch} from "react-router-dom"
<Switch>
    <Route path="/" exact component={About} />
    <Route path="/home" exact component={Home} />
    <Route path="/home" exact component={Test} />
</Switch>

10.Redirect 的使用 ( 重定向 )

  • 一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到 Redirect 指定的路由
import {Route,Switch,Redirect} from "react-router-dom"
<Switch>
   <Route path="/about" exact component={About} />
   <Route path="/home" exact component={Home} />
   <Redirect to="/home" /> 
</Switch>

11.编程式导航

  • 编程式导航:通过 JS 代码来实现页面跳转
  • history 是 React 路由提供的,用于获取浏览器历史记录的相关信息
  • push(path): 跳转到某个页面,参数 path 表示要跳转的路径,有历史记录
  • replace(path): 跳转到某个页面,没有历史记录
  • go(n): 前进或后退到某个页面,参数 n 表示前进或后退页面数量 (比如: -1 表示后退到上一页)
// replace跳转+携带params参数
props.history.replace(`/home/message/detail/${id}/${title}`)
// replace跳转+携带search参数
props.history.replace(`/home/message/detail?id=${id}&title=${title}`)
// replace跳转+携带state参数 (path,state)
props.history.replace(`/home/message/detail`,{id:'',title:''})
// 在函数组件中跳转
function About(props){
    return (
        <div>
            <h1>我是about</h1>
            <button onClick={() => props.history.push('/home')}>在about中</button>
            history.replace('/home')  它没有历史记录
        </div>
    )
}

12.向路由组件传递参数

  1. params 参数
路由链接(携带参数): <Link to='/demo/test/tom/18'>详情</Link>
注册路由(声明接收): <Route path="/demo/test/:name/:age" component={Test} />
接收参数: const {id,name} = this.props.match.params
  1. search 参数
路由链接(携带参数):<Link to='/demo/test/tom/18'>详情</Link>
注册路由(不需要声明,正常注册就可以): <Route path=" /demo/test" component={Test}/>
接收参数:const {search} = this.props.location
注意: 获取到的search是urlencoded编码字 符串,需要借助querystring解析

import qs from 'querystring'; // 这个querystring 不用我们下载,因为react脚手架已经帮助我们下载好了
let obj = {name:'tom',age:18}  
console.log(qs.stringify(obj))   // name=tom&age=18
let str = 'name=tom&age=18'
console.log(qs.parse(str))   // {name:'tom',age:18}  
  1. state 参数
路由链接(携带参数):<Link to={{path:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
注册路由(不需要声明,正常注册就可以): <Route path=" /demo/test" component={Test}/>
接收参数:this.props.location.state
注意点: 刷新页面也可以保留住参数
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-02 10:43:22  更:2021-08-02 10:43:35 
 
开发: 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/21 22:25:25-

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