vue 之 路由 以及 单页面应用程序 (路由可是重难点)

首先简单说一下单页面应用程序

单页面应用程序 

  • SPA : single page application   单页面应用程序
    • MPA : Multiple Page Application  多页面应用程序
  • 单页面 web 应用 
    • 就是只有一个web页面的应用
    • 是加载单个HTML页面
    • 并在用户与应用程序交互时,动态更新该页面的wen应用程序
  • 区别
    • 对于传统的多页面应用程序来说,每次请求服务器返回的都是一个完整的页面 
    • 对于单页面应用程序来说 :  
      • 只要第一次加载页面,   以后每次请求   仅仅是获取必要的数据, 然后由 页面中 js 解析 获取的数据展示在页面中
  • 单页面优势 :
  1. 减少了请求体积 , 加快页面响应速度 ,降低了对服务器的压力
  2. 更好的用户体验 , 让用户在 web app 感受 native app 的流畅 (局部刷新)
  • 单页面的劣势 
  1. 开发成本高 ( 需要学习路由 )
  2. 不利于SEO

路由

介绍路由 : 

  • 路由 : 是浏览器URL 中的哈希值( #hash ) 与 展示视图内容之间的对用规则 
    • 简单的来说 : 路由就是一套映射规则(一对一的对应规则),由开发人员制定规则
    • 当URL中的哈希值(#hash) 发生改变后, 路由会根据制定好的规则,展示对用的视图内容
  • 为什么要学习路由 ?
    • 渐进式 => vue => vue-router (管理多个页面)
    • 在web App中 , 经常会出现通过一个页面来展示和管理整个应用的功能
    • SPA 往往是功能复杂的应用 , 为了有效管理所有视图内容,前端路由 应运而生
  • vue 中的路由 : 是hashcomponent 的对应关系 , 一个哈希值对应一个组件

一 : 路由的基本使用

准备工作 (3个)

  • 安装  :    npm i vue-router
  • 引入 :    在引入vue之后引用  <script src="./node_modules/vue-router/dist/vue-router.js">
  • 实例路由对象 + 挂载到vue上

具体步骤(4个) 

  •  1. 入口 
  •  2. 路由规则
  •  3. 组件
  •  4. 出口 
// 1. 入口 
    //  方式1 : url 地址为入口    调试开发用
    输入 url 地址  改变哈希值   
    // 方式2  : 声明式导航 : router-link + to
 
// 2. 路由规则 
    path : 路由路径 
    component : 将要展示的路由组件
routes : [
    {path : '/one',component : One},
    {path : '/two',component : Two}
]

// 3. 组件 
    // 使用返回值的这个组件名称
const One = Vue.component('one',{
    template : `<div>子组件 one </div>`
})

// 4 . 出口 
// 也就是组件要展示的地方
<router-view></router-view>

#  总结 
拿到入口 哈希路径   ,根据路由匹配规则,找到对应的组件,显示到对用的出口位置

二 : 路由使用注意事项

  • 入口

    • 最长用的 入口是  声明式导航  router-link 
      // router-link 组件 最终被渲染为 a 标签  
      // to属性转化为a标签的href 属性 
      // to属性的值 , 实际上就是哈希值 , 将来要参与路由规则中进行匹配  
       <router-link to='/one'>首页</router-link>
  • 组件 

const One = { 
    template : `<div> 子组件 one </div>`
}
  • 演示 : 多个组件 匹配 

    <div id="app">
      <!-- 1 路由入口:链接导航 -->
      <router-link to="/one">One</router-link>
      <router-link to="/two">Two</router-link>
    
      <!-- 4 路由出口:用来展示匹配路由视图内容 -->
      <router-view></router-view>
    </div>
    
    <!--  导入 vue.js -->
    <script src="./vue.js"></script>
    <!--  导入 路由文件 -->
    <script src="./node_modules/vue-router/dist/vue-router.js"></script>
    <script>
      // 3 创建两个组件
      const One ={
        template: '<h1>这是 one 组件</h1>'
      }
      const Two =  {
        template: '<h1>这是 two 组件</h1>'
      }
    
      // 0 创建路由对象
      const router = new VueRouter({
        // 2. 路由规则
        routes: [
          { path: '/one', component: One },
          { path: '/two', component: Two }
        ]
      })
    
      const vm = new Vue({
        el: '#app',
        //0. 不要忘记,将路由与vue实例关联到一起!
        router
      })
    </script>

三 : 入口导航菜单高亮处理 

  • 点击导航 => 元素里添加了两个类

<a href="#/one" class="router-link-exact-active router-link-active">One</a>
<a href="#/two" class="">Two</a>
  • 修改方式1 : 直接修改类的样式

.router-link-exact-active,
.router-link-active {
  color: red;
  font-size: 50px;
}
  • 修改方式2 : 使用存在过的类样式 => 修改默认高亮类名

const router = new VueRouter({
  routes: [],
  // 修改默认高亮的a标签的类名
  // red 是已经存在过的
  linkActiveClass: 'red'
})

精确匹配和模糊匹配

  • 精确匹配 : router-link-exact-active 类名 : 只有当 浏览器地址栏中的哈希值 与 router-link 的 to 属性值,完全匹配对,才会添加该类

  • 模糊匹配: router-link-active 类名 : 只要 浏览器地址栏中的哈希值 包含 router-link 的 to 属性值,就会添加该类名

  • 解决办法 : 加个 exact

<router-link to="/" exact>
  One
</router-link>
  • 注意 : 精确匹配和模糊匹配,只对添加类名这个机制有效,与路由的匹配规则无关!!!

四 : 路由配置 

4.1 动态路由 => 详情列表 

导入 : 列表的三个手机都要点击进去详情页 , 只需要一个组件 , 显示不同的数据即可

入口 : to="/detial/3"

规则 : path : '/detail/:id ?'

获取值 :   组件    --->   $route.params.id

               事件中  --->  this.$route.params.id

               监听     --->  $route(to){ to.params.id }   或者   watch 

4.2 路由对象  - $route  

  • 一个路由对象(route object) 表示当前激活的路由的状态信息, 包含了当前url解析得到的信息
  • 一个哈希值路径  ===>  一个路由对象
  • 路由对象
    • 例如 : /detail/4?age=21#one
      • $route.name : 路由规则名称
      • $route.params : 路由参数     对象      ----->     { id : '4' }
      • $route.query :  查询参数       对象      ----->     {age=21}
      • $route.path  :  哈希 值 路径               ----->      '/detail/4'
      • $route.hash    当前路由的hash 值     ----->      "#one"
      • $route.fullPath   全路径                      ----->      /detail/4?age=21#one

4.3  嵌套路由   

作用 :   想在一个组件(child)显示在另一个组件(parent) 里

如何使用 :  

  1. 在parent组件里留一个出口  Parent :  ---   <router-view></router-view>
  2. 规则     children       children:[{ path:'/child' , componemt:'Child' }]

/child和child的区别 :  

  • 如果是 /child => 那么直接访问就可以了  #/child
  • 如果是 child => 那么直接访问就应该访问#/parent/child  才可以了  

4.4 命名路由  name

  • 有时候,通过一个名称来标识一个路由显得更方便一些
  • 特别是在创建一个路由 , 或者执行一些跳转的时候  
  • 你可以在创建ROuter实例的时候,在routers配置中给某个路由设置名称 
    # 命名
    routes: [
        {
            path: '/parent',
            name: 'parent',
            component: parent
        }
    ]
    
    # 入口链接 + 跳转  (使用 path 和 name 的转换)
    <!-- 方式1 : url手动写 -->
    
    <!-- 方式2 : 入口链接 声明式导航 -->
    <router-link to="/parent">点击</router-link>
    <router-link :to="{ name : 'parent' }">点击</router-link>  # 忘了 带 : 原始对象类型
    
    <!-- 方式3 : 编程式导航 -->
     fn() {
         // this.$router.push('/parent')
         this.$router.push({
             name: 'parent'
         })
     }

4.5 命名视图

作用 :  一个哈希值路径显示多个组件

如何使用 : 

    1. 规则里面 { path :'/',  components : {   
                                                                   default : header,  
                                                                   m : main, 
                                                                    f :footer   
                                                              } }

      2.  出口 : <router-view />     <router-view name='m' />     <router-view  name='f' />

4.6  重定向 

作用 : 改变路由规则

使用 :  

{path:'/',redirect : ''}

// 1
redirect: '/header'
// 2
redirect: { name: 'header' }
// 3
redirect: to => {
      // console.log(to)
    return {
        name: 'about'
    }
}

4.7 组件传参 

  • 原始方式使用$route获取
    # 入口
        <router-link to="/header/3">123</router-link>
    # 规则
    routes: [
        {
            path: '/header/:id',
            component: header,
        }
    ]
    # 获取参数
    const header = {
        template: `<p>header  {{ $route.params.id }}  </p>`
    }
  • 布尔模式
    # 入口
        <router-link to="/header/3">123</router-link>
    
    # 规则
    routes: [
        {
            path: '/header/:id',
            component: header,
            // 如果 props 被设置为 true,route.params 将会被设置为组件属性
            props: true
        }
    ]
    
    # 获取参数
    const header = {
        // 参数 id 当成参数
        props: ['id'],
        template: `<p>header   {{ id }} </p>`
    }
  • 对象模式
    # 入口
     <router-link to="/header">123</router-link>
    
    # 规则
     routes: [
         {
             path: '/header',
             component: header,
             props: { foo: '0000' }
         }
     ]
    # 组件
     const header = {
            props: ['foo'],
            template: `<p>header   {{ foo }} </p>`
     }
  • 函数模式
    # 同对象模式一样
    # 区别是props值不一样
     props: to => {
         return { foo: '0000' }
     }

路由进阶 

一 . 元信息 

  • 作用 : 给路由添加一些自己的信息  在导航路由的时候,可以用作判断
  • 规则 : {path :'/one'   ....    meta : { title : '春' '}}
  • 获取 : $route.meta.title

二. 导航守卫 

说明 : 通过跳转或者取消的方式 ,  守卫导航    比如 : 先登录,在去home,要不然就会跳登录页

方法 

router.beforeEach((to, from, next) => {
    // 访问 login

    if (to.name == 'login') {
        // 下一步
        next()
    } else {
        // 停止跳转
        next(false)
        // 跳转到下一步
        next({ name: 'login' }) 或者 使用路径  next('/login')
    }
})

$route 和 $router   的区别

$route : 路由对象   --->  url解析对象  ---->   path/name/meta   ----->  都是属性

$router : 路由实例  ---> new VueRouter()   ---> 编程式导航  ----->  跳转用的   --->   push    back    replace

发布了64 篇原创文章 · 获赞 19 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44114310/article/details/91378005