极品-React中的DOM虚拟DOM,与deff算法,router

Posted 哈比老乌龟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了极品-React中的DOM虚拟DOM,与deff算法,router相关的知识,希望对你有一定的参考价值。

在react中state中存放的是数据
初次渲染时react会根据state(model),创建出一个虚拟DOM树
然后经过render将虚拟DOM形成出真实的DOM
当数据发生变化的时候(setState())他会生成一个新的虚拟DOM树
通过deff算法计算上一次的值和新更新的值有什么新的变化
最后render只会将更新的内容渲染到真实DOM上

安装
安装react-router-dom
yarn add react-router-dom --save
代码中基本使用

import React,{ Component } from "react";
import { BrowserRouter,Route,Switch } from "react-router-dom";
import routers from "./router/index";
class App extends Component<any,any>{
  render(): React.ReactNode {
    return (
        <BrowserRouter>
            {
                routers.map(router=>{
                    return (
                        <Route
                            path={router.path}
                            component = { router.component }
                        ></Route>
                    )
                })
            }
        </BrowserRouter>
    )
  }
}
export default App

        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"

路由传参接受
方式1
通过params

<Route path='/:userId' component={User}></Route>

跳转路由

this.props.history.push('/1234')

接收

this.props.match.params.userId

特点 :刷新页面数据不会丢失,但是只能传字符串

方式2 通过query

跳转路由

 this.props.history.push({ pathname: '/home' , query : { id: '6666' }})

接收参数

this.props.location.query.id

方式3 通过state
跳转路由

 this.props.history.push({ pathname: '/home' , state: { id: '6666' }})

接收参数

this.props.location.state.id

通过params传参 页面刷新 数据不会丢失 query与state传参 刷新页面数据会丢失

嵌套路由

先定义页面
Topic.js, About.js, Topic.js, A.js, B.js (将里面的文字做相应的替换)

import React from 'react'

export default class Topic extends React.Component {
    render() {
        return (
            <>
                <div>
                    Topic页面
                </div>
            </>
        )
    }
}

Home2.js

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

export default class Home extends React.Component {
    render() {
        return (
                <div>
                    <ul>
                        <li>
                            <Link to="/">Home2</Link>
                        </li>
                        <li>
                            <Link to="/about">About2</Link>
                        </li>
                        <li>
                            <Link to="/topic">Topics2</Link>
                        </li>
                    </ul>

                    <hr/>
                    {/* 子页面 */}
                    {/* 所有子组件 */}
                    {this.props.children}
                </div>
        )
    }
}

router.js

import React from 'react'
import { HashRouter as Router, Route, Link, Switch, useRouteMatch, useParams } from 'react-router-dom'

import Main from './Main'
import About from './About'
import Topic from './Topic'

import Home from './Home'
import A from './A'
import B from './B'

/**
 * 这个页面就是 最终输出页面
 * 在项目根目录的 index.js 文件里面
 * 
 * import Router from './pages/router_demo/router02/router';
 * ReactDOM.render(<Router />, document.getElementById('root'));
 */
export default class IRouter extends React.Component {

    render() {
        return (
            <>
                <Router>
                    {/* 只能有一个根节点 */}
                    <Home>
                        {/* 页面路由,一个 Route 代表一个页面 */}
                        {/* 4.0  版本开始允许加载多个路由,所以建议加上 exact 进行精准匹配*/}
                        <Route exact={true} path="/" component={Main}/>
                        <Route exact={true} path="/about" component={About}/>
                        <Route exact={true} path="/topic" component={Topic}/>
                        {/* 嵌套路由,不能在父级家 exact,因为先要匹配父级然后才能匹配子集 */}
                        {/* 比如:/nested/a , 会先匹配父级 /nested 饭后才能匹配 /nested/a */}
                        <Route path="/nested" component={() => <Nested />} />
                    </Home>
                </Router>
            </>
        )
    }
}

/**
 * 函数组件
 * @param {*} props 
 */
export function Nested(props) {
    // 获取route的匹配数据
    // path 路径, url 路径, params 参数
    const { path, url, params } = useRouteMatch()
    // 获取 path 参数, http://localhost:3000/a/:number
    // const { number } = useParams()

    console.log(path, url, params)
    return (
        <>
            <ul>
                <li>
                    <Link to={`${path}/a`}>A页面</Link>
                </li>
                <li>
                    <Link to={`${path}/b`}>B页面</Link>
                </li>
            </ul>
            <hr/>
            {/* {props.children} */}
            <Switch>
                <Route exact path={path} component={() => <h3>嵌套路由</h3>}/>
                <Route  path={`${path}/a`} component={A}/>
                <Route  path={`${path}/b`} component={B}/>
            </Switch>
        </>
    )
}

嵌套路由的重点在于,嵌套路由,不能在父级加 exact(精准匹配),因为先要匹配 父级 然后才能匹配 子集
比如:/nested/a , 会先匹配父级 /nested 后才能匹配 /nested/a

<Route path="/nested" component={() => <Nested />} />
.......  分隔符 ...........

// <Nested /> 组件的内部
// 这里的 path 就是 /nested
// `${path}/a` 就是 /nested/a
<Switch>
     <Route exact path={path} component={() => <h3>嵌套路由</h3>}/>
     <Route  path={`${path}/a`} component={A}/>
     <Route  path={`${path}/b`} component={B}/>
</Switch>

以上是关于极品-React中的DOM虚拟DOM,与deff算法,router的主要内容,如果未能解决你的问题,请参考以下文章

极品-React中的DOM虚拟DOM,与deff算法,router

极品-React中的DOM虚拟DOM,与deff算法,router

关于React中的虚拟DOM与Diff算法

React 触发虚拟 DOM 输入的 onChange 事件与常规 DOM 中的输入不同。为啥是这样?

React虚拟dom中的key值

深入理解react中的虚拟DOMdiff算法