Vue快速上手:九、了解前端路由

91 阅读3分钟

简介

路由是什么,简单来说根据不同URL地址访问不同的内容。在以前路由这一功能都是在服务器端实现的,一个页面对应着一个URL地址,由服务端根据URL响应不同的页面给浏览器,这是多页面跳转。

前端的路由因为在浏览器端完成的,所以这是一个单页面的跳转技术,根据URL的变化显示页面不同的内容。

前端路由有两种:hash路由、history路由。

hash路由

hash路由就是根据URL的hash部分的变化显示不同的内容或组件。

URL的hash部分

我们知道一个完整的URL有以下几个部分:协议、端口、域名、虚拟目录以及文件路径、参数、锚。

如:http://localhost:5173/index/index.html?id=1#title

http就是协议,localhost就是域名,5173是端口,index/index.html是虚拟目录以及文件路径,这一部分如果没有就是网站的根目录,?后面的是参数,#后面的是锚部分也叫hash部分。

因为锚链接是跳转到当前页id为对应hash值的元素位置,只会在本页面上进行跳转,所以可以根据监测URL的hash部分的变化就可以切换不同的内容。

hashchange事件就是当hash值发生变化时执行的事件。

实现代码如下,过程都在注释当中:

<div id="app">
    <!-- hash路由切换的锚链接, #后面就是hash值 -->
    <nav>
       <a href="#index">首页</a>
       <a href="#list">列表页</a>
       <a href="#contact">联系我们</a>
    </nav>

    <!-- hash路由切换显示的区域 -->
    <div class="router-view">

    </div>
</div>

<script>
    // 获取显示组件的容器
    const routerViewBox = document.querySelector(".router-view");

    // 模拟创建组件的方法,创建一个组件容器元素然后设置好HTML以及命名。
    function createComponent(componentName, componentTemplate) {
       const div = document.createElement("div");
       div.dataset.name = componentName;
       div.innerHTML = componentTemplate;
       return div;
    }

    // 创建首页组件
    function Index() {
       const template = `
          <h1>我是首页</h1>
          <p>欢迎来个学习前端知识</p>
       `;
       return createComponent("index", template);
    }

    // 创建列表页组件
    function List() {
       const template = `
          <ul>
             <li>学习HTML</li>
             <li>学习CSS</li>
             <li>学习JavaScript</li>
             <li>学习Node.js</li>
             <li>学习Vue</li>
             <li>学习React</li>
          </ul>
       `;
       return createComponent("list", template);
    }

    // 创建联系我们组件
    function Contact() {
       const template = `
          <article>
             <p>地址:xxxxxxxxxx</p>
             <p>邮箱:xxxxxxxxxx</p>
             <p>电话:xxxxxxxxxx</p>
          </article>
       `;
       return createComponent("contact", template);
    }

    function Error404() {
       const template = `<div>404, 非法路由</div>`;
       return createComponent("error404", template);
    }

    // 模拟渲染组件,通过hash的值渲染
    function renderer() {
       const hash = location.hash.slice(1); // 获取URL的hash的值
       routerViewBox.innerHTML = ""; // 清空显示区域的HTML。

       // 根据hash的值渲染不同的组件
       switch (hash) {
          case "": //首次加载的值
          case "index":
             routerViewBox.appendChild( Index() )
             break;
          case "list":
             routerViewBox.appendChild( List() )
             break;
          case "contact":
             routerViewBox.appendChild( Contact() )
             break;
          default:
             routerViewBox.appendChild( Error404());
             break;
       }
    }

    // 地址栏 hash变化事件
    window.onhashchange = () => {
       renderer();
    }

    renderer(); // 首次加载渲染组件

</script>

history路由

history是根据浏览器的历史记录来控制显示不同内容的,使用history.pushState方法在历史记录中添加新的历史记录,然后渲染新的显示内容。

<div id="app">
     <!-- hash路由切换的链接 -->
     <nav>
         <a href="/index">首页</a>
         <a href="/list">列表页</a>
         <a href="/contact">联系我们</a>
     </nav>

     <!-- hash路由切换显示的区域 -->
     <div class="router-view">

     </div>
 </div>

 <script>
     const routerViewBox = document.querySelector(".router-view");

     // 模拟创建组件的方法
     function createComponent(componentName, componentTemplate) {
         const div = document.createElement("div");
         div.dataset.name = componentName;
         div.innerHTML = componentTemplate;
         return div;
     }

     // 模拟首页组件
     function Index() {
         const template = `
            <h1>我是首页</h1>
            <p>欢迎来个学习前端知识</p>
        `;
         return createComponent("index", template);
     }

     // 模拟列表页组件
     function List() {
         const template = `
            <ul>
               <li>学习HTML</li>
               <li>学习CSS</li>
               <li>学习JavaScript</li>
               <li>学习Node.js</li>
               <li>学习Vue</li>
               <li>学习React</li>
            </ul>
        `;
         return createComponent("list", template);
     }

     // 模拟联系我们组件
     function Contact() {
         const template = `
            <article>
               <p>地址:xxxxxxxxxx</p>
               <p>邮箱:xxxxxxxxxx</p>
               <p>电话:xxxxxxxxxx</p>
            </article>
        `;
         return createComponent("contact", template);
     }

     // 模拟渲染组件
     function renderer() {
         const pathname = location.pathname;
         routerViewBox.innerHTML = "";
         switch (pathname) {
             case "/index":
                 routerViewBox.appendChild( Index() )
                 break;
             case "/list":
                 routerViewBox.appendChild( List() )
                 break;
             case "/contact":
                 routerViewBox.appendChild( Contact() )
                 break;
             default:
                 routerViewBox.appendChild( Index() )
                 break;
         }
     }

     // 使用事件代理监听 a 标签的点击事件
     document.querySelector("nav").addEventListener("click", e => {
         if(e.target.nodeName === "A") { // 如果点击的是 A 标签
             const href = e.target.getAttribute("href");  // 获取 A 标签的 href 属性
             history.pushState({name: "首页", path: "/index"}, "", href); // 添加历史记录
             renderer(); // 渲染组件
             e.preventDefault(); // 阻止A标签的默认跳转行为
         }
     })

     renderer();
 </script>

Vue路由简介

Vue Router是基于Vue的组件系统构建的路由插件,可通过配置来告诉Vue Router为每个URL路径显示哪些组件,还提供其它额外的功能,如:路由守卫、动态路由等,下一节开始正式讲解Vue Router的使用。