Vue 路由 基本操作 路由模式 hash路由模式的实现原理

1-路由

1.1-路由的概念

  • 页面访问路径和组件之间的对应关系

1.2-路由的安装

npm i vue-router -S	

1.3-路由的基本使用流程

1.3.1-第一步

  • 配置路由规则(数组)
import Home from './pages/Home'
import Login from './pages/Login'
const rotues=[
    {
        // 页面访问路径
        path:'/home',
        // 页面组件对象
        component:Home
    },
    {
        // 页面访问路径
        path:'/login',
        // 页面组件对象
        component:Login
    }
]

1.3.2-第二步

  • 根据路由规则数组, 创建路由实例对象
import Vue from 'vue';
// 1-导入路由模块
import VueRouter from 'vue-router';
// 2-将路由模块注册成vue的插件
Vue.use(VueRouter);
// 3-创建路由实例对象
const  router=new VueRouter({
    // 路由规则数组
    routes:routes
});
// 4-导出路由对象

1.3.3-第三步

  • 将路由实例挂在到vue上
import router from './router/index';
new Vue({
    el:'#app',
    // 挂载路由实例
    router:router
});

1.3.4-第四步

  • 在根组件App.vue中添加路由占位符合路由导航链接
<template>
  <!-- 必须有一个唯一的根标签 -->
  <div id="app">
    <!-- 导航链接 -->
    <!-- to属性: 指定页面的跳转地址, 必须和路由规则数组中的path属性保持一致 -->
    <router-link to="/home">首页</router-link>
    <router-link to="/reg">注册</router-link>
    <router-link to="/login">登录</router-link>
    <hr>
    <!-- 路由占位符: 访问地址匹配到的路由组件的显示位置 -->
    <router-view></router-view>
   </div>
</template>

1.4-路由模式

  • hash模式:

    • 页面访问地址中带有#, 默认路由模式
    • hash路由模式, 通过npm run build打包之后, 不需要web服务器的支持
    new  VueRouter({
        // 路由规则数组
        routes,
        // mode可选值: hash, history
        mode:'hash'		
    });
    
  • history模式:

    • 页面访问地址中不带#
    • history路由模式, 通过npm run build打包之后,需要web服务器的支持
    new  VueRouter({
        // 路由规则数组
        routes,
        // mode可选值: hash, history
        mode:'history'		
    });
    

1.5-路由导航高亮

  1. 给默认的路由导航高亮类名router-link-active添加对应css属性, 使其高亮显示即可

  2. 自定义导航链接高亮类名

    new  VueRouter({
        // 自定义导航链接高亮类名
        linkActiveClass:''
    });
    

1.6-路由重定向

  • router/index.js
// 3-定义路由规则数组
const  routes=[
    {
        path:'/',
        // component:Home
        // 重定向
        redirect:'/login'
    }
]

1.7-命名路由

  • router/index.js

    // 3-定义路由规则数组
    const  routes=[
        {
            name:'index',
            path:'/',
            // component:Home
            // 重定向
            redirect:'/login'
        },
        {
            name:'home',
            path:'/home',
            component:Home
        },
        {
            name:'login',
            path:'/login',
            component:Login
        },
        {
            name:'reg',
            path:'/reg',
            component:Reg
        }
    ];
    
  • App.js

    <router-link class="nav-btn" v-bind:to="{name:'home'}" tag="div">首页</router-link>
    

1.8-编程式导航

  • 通过js的方式实现页面跳转

  • this.$router: 包含和页面跳转相关的方法

    • push(): 实现页面跳转, 追加一条访问历史

      • 路由字符串

        this.$router.push('/home');
        
      • 路由对象

        this.$router.push({name:'home'});
        
    • replace: 实现页面跳转, 覆盖前一次的访问历史

      • 路由字符串

        this.$router.replace('/home');
        
      • 路由对象

        this.$router.replace({name:'home'});
        
    • go(): 实现页面前进后者回退

      • 正数: 前进
      • 负数: 回退
    • forward(): 实现页面前进一步

    • back(): 实现页面回退一步


1.9-路由元信息

  • 定义

    router/index.js

    // 3-定义路由规则数组
    const  routes=[
        {
            name:'index',
            path:'/',
            // component:Home
            // 重定向
            redirect:'/login'
        },
        {
            name:'home',
            path:'/home',
            component:Home,
            // 路由元信息
            meta:{
                title:'网站首页'
            }
        },
        {
            name:'login',
            path:'/login',
            component:Login,
            meta:{
                title:'登录页面'
            }
        },
        {
            name:'reg',
            path:'/reg',
            component:Reg,
            meta:{
                title:'注册页面'
            }
        }
    ];
    
  • 调用

    • 使用路由元信息, 实现更新页面标题
    • this.$route: 存储的是和路由相关的属性(包含路由元信息)

    页面组件中: 通过this.$route.meta读取路由元信息

    export default {
      created(){
        // this.$route: 存储的是和路由相关的属性(包含路由元信息)
        // 通过this.$route对象读取路由元信息
        const title=this.$route.meta.title;
        // 通过操作真实dom, 实现更新页面标题
        document.title=title;
      }
    }
    

1.10-命名视图

  • 应用场景: 一个路由访问地址, 对应多个视图组件

1.10.1-配置命名视图路由规则

router/index.js

import Home from '../pages/Home';
import Aside from '../components/Aside';
// 3-定义路由规则数组
const  routes=[
    // 一个访问路径, 对应多个组件, 需要用到命名视图
    {
        name:'home',
        path:'/home',
        // component:Home,
        components:{
            // aside: 要和插入的router-view的name属性保持一致
            // Aside: 组件对象
            aside:Aside,
            // content: 要和插入的router-view的name属性保持一致
            // Home: 组件对象
            content:Home
        }
    }
}

1.10.2-在根组件中添加命名视图

App.vue

<template>
  <!-- 必须有一个唯一的根标签 -->
  <div id="app" class="container">
    <!-- 命名视图aside -->
    <router-view name="aside"></router-view>
    <div class="right">
      <!-- 导航链接 -->
      <router-link class="nav-btn" v-bind:to="{name:'home'}" tag="div">首页</router-link>
      <router-link class="nav-btn" :to="{name:'reg'}" tag="div">注册</router-link>
      <router-link class="nav-btn" to="/login" tag="div">登录</router-link>
      <router-link class="nav-btn" to="/ucenter" tag="div">我的</router-link>
      <hr />
      <!-- 命名视图content -->
      <router-view name="content"></router-view>
      <!-- 默认视图: 默认路由出口 -->
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {
  // 组件名字
  name: "App"
};
</script>

<style>
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}
#app {
   1000px;
  margin: 20px auto;
}
h1 {
  margin-bottom: 10px;
}
/* 路由导航链接高亮显示 */
.nav-btn {
  background: #ddd;
  border: 1px solid #eee;
  display: inline-block;
   80px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  text-decoration: none;
}
/* 默认高亮类名:router-link-active */
/* 自定义导航链接高亮类名 */
.active {
  background: brown;
  color: #fff;
}

/* 命名视图对应样式 */
.container {
  display: flex;
  height: 600px;
}
.right {
  flex: 1;
  background: lightgreen;
}
</style>

1.11-动态路由

  • 定义动态路由规则

    // 3-定义路由规则数组
    const  routes=[
        // 动态路由, id动态路由参数
        {
            path:'/goods/:goodsId',
            component:Goods,
            // 路由元信息的定义
            meta:{
                title:'商品详情',
                // 自定义属性, auth:true,表示必须登录之后, 才能访问
                auth:false
            }
        }
    ];
    
  • 动态路由链接

    <router-link class="nav-btn" to="/goods/100" tag="div">商品详情</router-link>
    
  • 动态路由参数的获取

    this.$route.params
    

1.11.1-动态路由参数的解耦

  1. 在路由规则对象中添加如下配置

    {
        path:'/goods/:goodsId',
        component:Home
        // 路由参数解耦
        props:true
    }
    
  2. 在组件配置对象中添加如下配置

    {
        data(){
          return {}  
        },
        props:['goodsId']
    }
    
  3. 在组件视图层直接通过goodsId获取动态路由参数

    <h1>{{goodsId}}</h1>
    <!--完整写法-->
    <h1>{{$route.params.goodsId}}</h1>
    

1.12-通过查询字符串的方式实现路由传参

  1. 通过查询字符串传递数据

    <router-link class="nav-btn" to="/news?newsId=1&wd=vue" tag="div">新闻详情</router-link>
    
  2. 组件内通过this.$route.query获取查询字符串对象

    this.$route.query
    

1.13-路由懒加载

  • 作用: 提升页面渲染性能

    const Home=()=>import('../pages/Home');
    const Login=()=>import('../pages/Login');
    const Reg=()=>import('../pages/Reg');
    const Ucenter=()=>import('../pages/Ucenter');
    const Goods=()=>import('../pages/Goods');
    const News=()=>import('../pages/News');
    

1.14-路由匹配模式

  • 默认是模糊匹配: 访问地址中只要包含路由对象中的path, 就认为是匹配成功(所以会自动电量对应的导航链接)
启用路由严格匹配模式
  • 在路由导航链接组件上添加exact属性

    <router-link exact tag="li" to="/">管理中心</router-link> 
    

2-hash路由模式实现原理

  1. 监听页面锚点字符串的更新

    <component :is="page"></component>
    
    // 导入页面组件
    import Home from './pages/Home';
    import Reg from './pages/Reg';
    import Login from './pages/Login';
    export default {
      // 组件名字
      name: "App",
      data(){
        return {
          page:'Home'
        }
      },
      // 注册子组件
      components: {Home,Reg,Login},
      created(){
        window.addEventListener('hashchange',()=>{
          // console.log('hashchange',location.hash.split('/')[1]);
          // 更新page变量的值
          this.page=location.hash.split('/')[1];
        });
      }
    };
    
  2. 根据锚点字符串, 显示对应的组件

3-案例

3.1-后台管理系统

  • 根组件

    App.vue

    <template>
      <div class="container">
        <div class="left">
          <ul class="navbar">
            <!-- <li :class="page==='Main'?'active':''" @click="changePage('Main')">管理中心</li>
            <li :class="page==='Goods'?'active':''" @click="changePage('Goods')">商品管理</li>
            <li :class="page==='User'?'active':''" @click="changePage('User')">会员管理</li>
            <li :class="page==='Order'?'active':''" @click="changePage('Order')">订单管理</li> -->
            <!-- 启用路由严格匹配模式 -->
            <router-link exact tag="li" to="/">管理中心</router-link> 
            <router-link tag="li" to="/goods">商品管理</router-link> 
            <router-link tag="li" to="/user">会员管理</router-link> 
            <router-link tag="li" to="/order">订单管理</router-link> 
    
          </ul>
        </div>
        <div class="right">
          <!-- 头部 -->
          <Header></Header>
          <div class="content">
            <!-- <component :is="page"></component> -->
            <!-- 路由占位符 -->
            <router-view></router-view>
          </div>
          <!-- 底部 -->
          <Footer />
        </div>
      </div>
    </template>
    
    <script>
    // 1-导入页组件
    // import Main from "./pages/Main";
    // import Goods from "./pages/Goods";
    // import Order from "./pages/Order";
    // import User from "./pages/User";
    // 导入功能组件
    import Header from "./components/Header";
    import Footer from "./components/Footer";
    
    export default {
      // 2-注册组件
      components: {
        // Main,
        // Goods,
        // Order,
        // User,
        Header,
        Footer
      },
      data() {
        return {
          // 页面组件名称
          page: "Order"
        };
      },
      methods: {
        // 切换页面
        changePage(page) {
          this.page = page;
        }
      }
    };
    </script>
    
    <style>
    *{
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }
    .container {
      background-color: #ddd;
      /* vh:相对单位; 100vh=屏幕的高度  1vh==1/100屏幕高度; viewport height */
      height: 100vh;
      display: flex;
    }
    /* 左侧导航栏 */
    .container .left {
       226px;
      background: #00152a;
    }
    .left .navbar li {
      list-style: none;
      line-height: 50px;
      color: #fff;
      text-align: center;
      cursor: pointer;
    }
    .left .navbar li:hover {
      background: #0077b8;
    }
    .left .navbar li.active {
      background: #0077b8;
    }
    
    .container .right {
      flex: 1;
      display: flex;
      flex-direction: column;
    }
    .right .header {
      height: 60px;
      line-height: 60px;
      text-align: center;
      background: #fff;
    }
    .right .content {
      margin: 10px;
      background: #fff;
      height: 300px;
      text-align: center;
      flex: 1;
    }
    .right .footer {
      line-height: 60px;
      text-align: center;
      background: #fff;
    }
    </style>
    
  • 路由文件

    ruoter/index.js

    // 1-导入路由模块
    import Vue from 'vue'
    import VueRouter from 'vue-router';
    
    // 2-注册插件
    Vue.use(VueRouter);
    
    
    // 3-创建路由规则
    // 导入页面组件
    import Main from '../pages/Main';
    import Goods from '../pages/Goods';
    import Order from '../pages/Order';
    import User from '../pages/User';
    
    const routes=[
        {
            // 模糊匹配: 访问地址中包含路由规则对象中的path, 那么认为匹配成功
            path:'/',
            component:Main,
            meta:{
                title:'管理中心'
            }
        },
        {
            path:'/goods',
            component:Goods,
            meta:{
                title:'商品管理'
            }
        },
        {
            path:'/user',
            component:User,
            meta:{
                title:'会员管理'
            }
        },
        {
            path:'/order',
            component:Order,
            meta:{
                title:'订单中心'
            }
        }
    ];
    
    // 4-创建路由对象
    const router=new  VueRouter({
        routes,
        mode:'hash',
        linkActiveClass:'active'
    });
    
    // 5-导出路由实例对象
    export default router;
    
  • 项目入口文件

    /main.js

    // The Vue build version to load with the `import` command
    // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
    import Vue from 'vue'
    // 导入了根组件
    import App from './App'
    // 导入路由实例对象
    import router from './router'
    /* eslint-disable no-new */
    new Vue({
      // 模板编译之后挂载的容器
      el: '#app',
      // 挂载路由模块
      router,
      components: { App },
      // vue实例的视图模板: 使用根组件App充当默认视图
      template:'<App/>'
    })
    
    

4-在线参考文档

原文地址:https://www.cnblogs.com/bnzw/p/14026617.html