Vue2-Vue Router前端路由实现思路

1.路由是什么?

Router路由器:数据包转发设备,路由器通过转发数据包(数据分组)来实现网络互连

Route路由:数据分组从源到目的地时,决定端到端路径的网络范围的进程  | - 网络层

Distribute分发:数据包或任务根据规则,分配到不同的路径

Default Route默认路由:路由表中没有匹配的路由时,默认显示的路由

Fallback Routing404路由/保底路由:匹配所有处理未定义或未找到路由请求的特殊路由

Nested Routing嵌套路由:一个路由组件内部定义其他路由组件,形成父子结构的路由

Routing Table路由表:存储到各个目的地的最佳路径的表,引导分组转送  | - 对象

#原生js实现路由

/* index.html */
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test Router</title>

</head>
<body>
  <section>
     <a href="#1">page 1</a><br/>
     <a href="#2">page 2</a><br/>
     <a href="#3">page 3</a><br/>
     <a href="#4">page 4</a><br/>
  </section>

  <div id="app"></div>

  <div id="div1" style="display: none">1</div>
  <div id="div2" style="display: none">2</div>
  <div id="div3" style="display: none">3</div>
  <div id="div4" style="display: none">4</div>

  <div id="div404" style="display: none">
      <span>404</span><hr/><span>Not found</span>
  </div>

  <script src="./src/main.js"></script>
</body>
</html>

<style>
    a{
       color: blueviolet;
       text-decoration: none;
    }
    #app{
        background: pink;
        font-size: 32px;
    }
    #div404{
        text-align: center;
    }
</style>
#hash模式(URL)

/* main.js 实现不同路由匹配不同页面 */
function route(){
    /* 获取hash */
    let hash=window.location.hash
    let number=hash.substr(1) || '1'
    console.log(hash,number)

    /* 获取并显示当前哈希匹配的div */
    let div=document.querySelector(`#div${number}`)
    if (div) {
        div.style.display = "block";
        let app = document.querySelector('#app');
        app.appendChild(div);
    }else{
        /* 保底路由404 */
        div = document.querySelector(`#div404`)
        div.style.display = "block";
        document.querySelector("body").appendChild(div);
    }
}
route()

window.addEventListener("hashchange",()=>{
    /* 隐藏所有div */
    let allDivs = document.querySelectorAll('[id^="div"]');
    allDivs.forEach(div => div.style.display = "none");

    /* 更新路由匹配 */
    route()
})

##任何情况都能使用hash模式
##SEO不友好,服务器无法接收#参数(#参数不会被接受,只展示默认路由页面内容)

2.前端路由的三种模式

#history模式(URL)

/* main.js */
const div1=document.createElement("div")
div1.textContent="1"
const div2=document.createElement("div")
div2.textContent="2"
const div3=document.createElement("div")
div3.textContent="3"
const div4=document.createElement("div")
div4.textContent="4"

const routeTable={
    "/1":div1,
    "/2":div2,
    "/3":div3,
    "/4":div4
}

function route(){
    /* 获取path */
    let path= window.location.pathname
    console.log(path)

    let number= path
    if(number ==="/"){ number = "/1" }

    /* 获取并显示当前path匹配的div */
    let div=routeTable[number.toString()]
    if (div) {
        div.style.display = "block";
        const app=document.querySelector("#app")
        app.appendChild(div);
    }else{
        /* 保底路由404 */
        div = document.querySelector(`#div404`)
        div.style.display = "block";
        document.querySelector("body").appendChild(div);
    }
}

const allA = document.querySelectorAll("a.link")
for (let a of allA) {
    a.addEventListener("click", e => {
        /* 阻止 a 默认刷新 */
        e.preventDefault();

        /* 获取目标path */
        const href = a.getAttribute("href");

        /* history模式api, 实现更改url无刷新跳转(不会重新加载页面) */
        window.history.pushState(null, `page ${href}`, href);

        /* 重新渲染目标path页面 */
        onStateChange(href);
    });
}

route()

/* 更新路由匹配,通知state变化 */
function onStateChange(){
    console.log("state changed!")
    document.querySelector("#app").innerHTML=''
    route()
}

##后端将所有前端路由渲染到同一页面
##IE8以下不支持
##popstate方法不会被window.addEventListener监听 | window.history.pushState()不会触发popstate

#memory模式(无URL,localStorage or 数据库 存储路径)

/* main.js */
const div1=document.createElement("div")
div1.textContent="1"
const div2=document.createElement("div")
div2.textContent="2"
const div3=document.createElement("div")
div3.textContent="3"
const div4=document.createElement("div")
div4.textContent="4"

const routeTable={
    "/1":div1,
    "/2":div2,
    "/3":div3,
    "/4":div4
}

function route(){
    /* 读取本地localStorage中存储URL对象 */
    let path= window.localStorage.getItem("pathObject")
    console.log(path)

    /* 写入 pathObject初值 作为默认路由 */
    let number= path
    if(!number){ number = "/1" }

    /* 获取并显示当前path匹配的div */
    let div=routeTable[number.toString()]
    if (div) {
        div.style.display = "block";
        const app=document.querySelector("#app")
        app.appendChild(div);
    }else{
        /* 保底路由404 */
        div = document.querySelector(`#div404`)
        div.style.display = "block";
        document.querySelector("body").appendChild(div);
    }
}

const allA = document.querySelectorAll("a.link")
for (let a of allA) {
    a.addEventListener("click", e => {
        /* 阻止 a 默认刷新 */
        e.preventDefault();

        /* 获取目标path */
        const href = a.getAttribute("href");

        /* 写入 localStorage存储URL对象 新值,更新目标path */
       window.localStorage.setItem("pathObject",href)

        /* 渲染目标path */
        onStateChange(href);
    });
}

route()

/* 更新路由匹配,通知本地对象value变化 */
function onStateChange(){
    console.log("localStorage's path changed!")
    document.querySelector("#app").innerHTML=''
    route()
}

##适合react native | weex(vue手机端)没有路径的情况 
##URL会记录path信息,memory没有URL单机路由

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值