其他分享
首页 > 其他分享> > 从零实现一个简易版Vue-Router,太通俗易懂了

从零实现一个简易版Vue-Router,太通俗易懂了

作者:互联网

1、含义:
浏览器无论访问什么地址,访问的真实页面始终是index.htmlvue根据不同的地址,渲染不同的组件。由于真实页面是唯一的,用户看到的页面切换,实际上是组件的切换,这种应用称之为单页应用

 

2、开发单页应用涉及到两个核心问题:

二、初识vue-router

1、vue-router 是 Vue.js 官方的路由管理器,使用vue-router 可以非常轻松的构建单页应用程序。
官网地址:https://router.vuejs.org/zh/

2、路由实际上就是可以理解为指向,就是我在页面上点击一个按钮需要跳转到对应的页面,这就是路由跳转。

3、首先我们来学习三个单词:

4、路由模式:

二、Vue Router案例

1、、基于vue-cli创建名为router的vue项目

2、打开router项目终端,使用如下指令安装vue-router插件库

npm install vue-router

 

 3、在components下新建Header.vueFooter.vue公共组件
1)Header.vue代码-主要实现菜单

<template>
    <!-- 头部菜单 -->
    <div class="header">
        <!-- 使用 router-link 组件来导航. -->
        <!-- 通过传入 `to` 属性指定链接. -->
        <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
        <router-link to="/">首页</router-link>
        <router-link to="/blog">博客</router-link>
        <router-link to="/about">关于我们</router-link>
    </div>
</template>
 
<script>
    export default {
        
    }
</script>
 
<style scoped>
.header {
    width:1000px;
    margin:0 auto;
    height:80px;
    background:black;
    display:flex;
    justify-content: center;
    align-items:center;
}
.header a{
    font-size:18px;
    text-decoration: none;
    color:white;
    margin:0 10px;
}
</style>

 2)Footer.vue代码

<template>
    <div class="footer">
        底部区域
    </div>
</template>
 
<script>
    export default {
        
    }
</script>
 
<style scoped>
.footer{
    width:1000px;
    line-height:80px;
    background: gray;
    margin:0 auto;
    text-align:center;
    color:white;
}
</style>

 4、在src下新建views目录,主要放一些非公共页面组件
5、在views下新建Home.vueBlog.vueAbout.vue,分别代码主页、博客页和关于我们
1)Home.vue代码

<template>
    <div>
        这里是首页内容
    </div>
</template>
 
<script>
    export default {
        
    }
</script>
 
<style scoped>
 
</style>

2)Blog.vue代码

<template>
    <div>
        这里是博客内容
    </div>
</template>
 
<script>
    export default {
        
    }
</script>
 
<style scoped>
 
</style>

 3)About.vue代码

<template>
    <div>
        这里是关于我们内容
    </div>
</template>
 
<script>
    export default {
        
    }
</script>
 
<style scoped>
 
</style>

 6、在src下新建router目录,存放路由配置,并在router目录下新建config.jsindex.js
config.js代码如下:
1)写法1——不推荐

原因:因为如果页面太多,依赖就会越多,会导致加载一个页面时将依赖的也加载进来,所以我们需要使用延时加载,访问哪个路径就导入哪个页面

//index.js

// 导入页面组件,@代表src目录,编译后代表根路径
import Home from '@/views/Home.vue'
import Blog from '@/views/Blog.vue'
import About from '@/views/About.vue'
// 导出路由配置
export default{
    // 1、路由模式
    mode:"history",
    // 2、路径配置,数组形式,一个路径对应一个对象
    routes:[
        {
            path:"/",
            component:Home
        },
        {
            path:"/blog",
            component:Blog
        },
        {
            path:"/about",
            component:About
        }
    ]
}

 2)写法2——推荐-懒加载,用到哪个就加载哪个

// 导出路由配置
export default{
    // 1、路由模式
    mode:"history",
    // 2、路径配置,数组形式,一个路径对应一个对象
    routes:[
        {
            path:"/",
            component:()=>import('@/views/Home.vue')
        },
        {
            path:"/blog",
            component:()=>import('@/views/Blog.vue')
        },
        {
            path:"/about",
            component:()=>import('@/views/About.vue')
        }
    ]
}

 index.js代码如下:

// 1、导入vue-router
import VueRouter from "vue-router";
// 2、导入vue
import Vue from "vue";
// 3、安装
import config from "./config.js";
// 4、Vue安装vue-router插件
Vue.use(VueRouter);
// 5、创建路由对象
const router = new VueRouter(config);
// 6、导出
export default router;

 当然你也可以将这两个js合并到index.js文件中,如下:

// 1、导入vue-router
import VueRouter from 'vue-router'
// 2、导入vue
import Vue from 'vue'
// 3、安装
Vue.use(VueRouter)
// 4、创建VueRouter实例-路由对象
const router = new VueRouter({
    // 5、配置路由
    //5.1配置路模式
    mode:"history",
    // 5.2 配置路由对象数组
    routes: [
       {
      path: "/",
      name: "Home",
      component: () => import("@/views/Home.vue"),
    },
    {
      path: "/blog",
      name: "Blog",
      component: () => import("@/views/Blog.vue"),
    },
    {
      path: "/about",
      name: "About",
      component: () => import("@/views/About.vue"),
    },
    ]
})
// 6、导出路由对象
export default router;

 7、在main.js中使用路由

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

通过注入路由器,我们可以在任何组件内通过 this.$router 访问路由器,也可以通过 this.$route 访问当前路由(后面演示)。

8、在App.vue中导入、注册、使用相关组件

<template>
  <div id="app">
    <!-- 头部 -->
    <Header/>
    <!-- 中间内容区域 -->
    <div class="container">
        <!-- 该组件会根据不同的访问路径,渲染不同的组件 -->
        <router-view></router-view>
    </div>    
    <!-- 底部 -->
    <Footer/>
  </div>
</template>
 
<script>
// 导入组件
import Header from './components/Header.vue'
import Footer from './components/Footer.vue'
export default {
  name: 'app',
  components: {
      // 注册组件
      Header,
      Footer
  }
}
</script>
 
<style>
.container{
    border: 1px solid gray; 
    margin:30px auto;
    width:1000px; 
    min-height: 200px;
} 
</style>

 9、执行如下指令启动服务,运行至浏览器,访问

 

三、router-link声明式导航组件和router-view

1、Header.vue中的template中,不使用a标签跳转原因:
因为如果使用a标签跳转,虽然能实现页面跳转,但点击上面的菜单访问,会发现了一个问题,就是页面会刷新,这会导致网站响应速度过慢,因为页面刷新的过程是这样的:

浏览器输入地址–>请求至服务器–>服务器返回html+css+js –>浏览器渲染页面,执行js –>创建vue实例–>渲染根组件->router-view标签根据不同的路径渲染不同的组件

最佳的方式就是直接通过router-view组件根据不同的路径渲染不同的组件,就是我们上面使用的router-link声明式导航组件。

2、router-link组件支持用户在具有路由功能的应用中点击导航。通过to属性指定目标地址,默认渲染为带有正确连接的a标签,可以通过配置tag属性生成别的标签。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的css类名。
3、router-link组件的属性有(不作展开讲-了解):


4、router-view组件:写在组件想要渲染的地方,等组件跳转过来就渲染,该组件会根据不同的访问路径,渲染不同的组件

四、命名路由

以上Header.vue中的template中的router-linkto属性值,我们是写死的,效果不是太好,如果一旦菜单路由配置对应的跳转地址发生变化,则可能会需要做大量的修改,因此,我们可以做如下优化:
1)我们修改src\router目录下config.js,给每个路由配置使用name进行命名,让名称与路由地址对应:

// 导出路由配置
export default{
    // 1、路由模式
    mode:"history",
    // 2、路径配置,数组形式,一个路径对应一个对象
    routes:[
        {
            path:"/",
            name:"Home",
            component:()=>import('@/views/Home.vue')
        },
        {
            path:"/blog",
            name:"Blog",
            component:()=>import('@/views/Blog.vue')
        },
        {
            path:"/about",
            name:"About",
            component:()=>import('@/views/About.vue')
        }
    ]
}

2)修改Header.vue中的template,直接使用名称去路由配置中匹配路由地址,注意要使用:to,值为一个对象:

<template>
    <!-- 头部菜单 -->
    <div class="header">
        <router-link :to="{name:'Home'}">首页</router-link>
        <router-link :to="{name:'Blog'}">博客</router-link>
        <router-link :to="{name:'About'}">关于我们</router-link>
    </div>
</template>

 

3)测试效果与之前一样

五、动态路由匹配

1、捕获所有路由或404 Not Found路由


如果我们浏览器输入的一个地址,在我们的项目中并不存在对应的具体页面,即404找不到,这种不存在的地址有无限多种可能,这些请求路径,我们都交给一个404页面处理,那么对于404页面而言,就需要匹配所有不存在请求地址。
1)在components中新建NotFound.vue组件

<!-- 纯css 3D立体样式 -->
<template>
    <div class="container404">
        <div class="page404">
            <div class="f404"><span>4</span><span>0</span><span>4</span></div>
            <div class="f404-des">
                该页面不存在(´・ω・`)
            </div>
        </div>
    </div>
    
</template>
 
<script>
    export default {
        
    }
</script>
 
<style scoped>
.container404 {
  background-color: #ECECEC;
  font-family:Arial, Helvetica, sans-serif;
  font-size: 14px;
  color: #3c3c3c;
  padding:150px;
}
.page404 .f404{
  text-align: center;
  font-size: 150px;
  font-weight: bold;
  line-height: 100px;
  letter-spacing: 5px;
  color: #fff;
  margin-bottom:60px;
}
 
.page404 .f404 span {
  cursor: pointer;
  text-shadow: 0px 0px 2px #686868,
    0px 1px 1px #ddd,
    0px 2px 1px #d6d6d6,
    0px 3px 1px #ccc,
    0px 4px 1px #c5c5c5,
    0px 5px 1px #c1c1c1,
    0px 6px 1px #bbb,
    0px 7px 1px #777,
    0px 8px 3px rgba(100, 100, 100, 0.4),
    0px 9px 5px rgba(100, 100, 100, 0.1),
    0px 10px 7px rgba(100, 100, 100, 0.15),
    0px 11px 9px rgba(100, 100, 100, 0.2),
    0px 12px 11px rgba(100, 100, 100, 0.25),
    0px 13px 15px rgba(100, 100, 100, 0.3);
  -webkit-transition: all .1s linear;
  transition: all .1s linear;
}
 
.page404 .f404 span:hover {
  text-shadow: 0px 0px 2px #686868,
    0px 1px 1px #fff,
    0px 2px 1px #fff,
    0px 3px 1px #fff,
    0px 4px 1px #fff,
    0px 5px 1px #fff,
    0px 6px 1px #fff,
    0px 7px 1px #777,
    0px 8px 3px #fff,
    0px 9px 5px #fff,
    0px 10px 7px #fff,
    0px 11px 9px #fff,
    0px 12px 11px #fff,
    0px 13px 15px #fff;
  -webkit-transition: all .1s linear;
  transition: all .1s linear;
}
 
.page404 .f404-des{
  text-align: center;
  color: #666;
  font-family: cursive;
  font-size: 20px;
  text-shadow: 0 1px 0 #fff;
  letter-spacing: 1px;
  line-height: 2em;
}
</style>

2)在src\router目录下config.js,新增匹配所有请求的路由配置: 

// * 号通配符,其他配置都未匹配到都会走这个配置,/user-*'会匹配以 `/user-` 开头的任意路径
{
    path:"*",
    name:"404",
    component:()=>import('@/components/NotFound.vue')
}

3)测试下效果: 

补充:
1、高级匹配模式:
vue-router 使用 path-to-regexp 作为路径匹配引擎,所以支持很多高级的匹配模式,例如:可选的动态路径参数、匹配零个或多个、一个或多个,甚至是自定义正则匹配。查看它的文档学习高阶的路径匹配,还有这个例子 展示 vue-router 怎么使用这类匹配
2、匹配优先级:
有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。

2、响应路由参数的变化


1、我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对于所有 username 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果。
 

2、在views目录下新建User.vue组件 

<template>
    <div>
        欢迎 {{ $route.params.username }} 用户回来!
    </div>
</template>
 
<script>
    export default {
        
    }
</script>
 
<style scoped>
 
</style>

3、修改src\router目录下config.js,新增配置如下: 

{ 
    path: '/user/:username', 
    name:'User',
    component:()=>import('@/views/User.vue')
}

 

现在呢,像 /user/foo 和 /user/bar都将映射到相同的路由。一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。

4、修改Header.Vuetemplate新增用户请求:

<!--params:传参  -->
<router-link :to="{name:'User',params:{username:'小明'}}">用户</router-link>
<!-- 或直接写地址然后动态拼接参数 -->
<!-- <router-link to="/user/小明">用户</router-link> -->

5、测试 

6、上面的理解了,类似/user/:username/post/:post_id多参数的应该也就会了
1)修改src\router目录下config.js,修改上面动态地址配置如下: 

{ 
    path: '/user/:username/post/:post_id', 
    name:'User',
    component:()=>import('@/views/User.vue')
}

 2)修改User.vuetemplate如下:

<template>
    <div>
        欢迎 {{ $route.params.username }} 用户回来,post_id: {{ $route.params.post_id }} 
    </div>
</template>

 3)修改Header.Vuetemplate中动态地址:

<!--params:传参  -->
<router-link :to="{name:'User',params:{username:'小明',post_id:20}}">用户</router-link>
<!-- 或直接写地址然后动态拼接参数 -->
<!-- <router-link to="/user/小明/post/20">用户</router-link> -->

4)测试: 

标签:Vue,import,简易版,vue,router,组件,Router,0px,路由
来源: https://blog.csdn.net/weixin_51646421/article/details/122866546