vue-router

后端路由:每次仿问都要向 server 发送一个请求,server 需要响应解析,会有延迟「网络不好更严重」;

前端路由:只是改变浏览器的地址,不刷新浏览器,不和服务端交互,所以性能有大大的提高「用户体验提高」,前端路由有两种实现方式

路由的实现方式

1 改变 hash 值,监听 hashchange 事件,可以兼容低版本浏览器;

hash 改变,不会导致浏览器刷新「请求服务器」:

监听路由对页面作出相应的改变:

window.addEventListener("hashchange", function(){
    //变化后输出当前地址栏中的值
    document.getElementById("show-hash-result").innerHTML = "当前的 hash 值是:  "+location.hash;
    //打印出当前 hash 值
    console.log("当前的 hash 值是:"+window.location.hash) ;
});

js获取hash值:

window.location.hash

2 通过 H5 的 history API 来监听 popState 事件,使用 pushState 和 replaceState 实现

window 的 history 提供了对浏览器历史记录的访问功能,并且它暴露了一些方法和属性,让你在历史记录中自由的前进和后退,并且在 H5 中还可以操作历史记录中的数据。

在 chrome 浏览器的调试窗口中输入 window.history,会得到 history 的一些方法和属性,如下图所示:

back():在历史记录中后退:

history.back() ;

forward:在历史记录中前进:

history.forward();

go():移动到指定的历史记录点:

history.go(-1)
// 其中正数是前进「+1就是前进一个界面」,负责是后退的意思「-1就是后退一个界面」

length: hisgory 的属性,显示 history 的长度。

pushState 给历史记录堆栈顶部添加一条记录:

pushState(data,title[,url]):

从上面了解到,使用 H5 的 history 的 pushState 可以代替 hash,并且更加优雅,效果图:

 源码:

<h4>使用 h5 实现前端路由</h4>
  <ul>
    <li> <a  onclick="home()">首页</a></li>
    <li> <a  onclick="message()">消息</a></li>
    <li> <a  onclick="mine()">我的</a></li>
  </ul>
  <div id="showContent" style="height:240px;width:200px;background-color:red">
    home
  </div>

  <script type="text/javascript">

    function home() {
      // 添加到历史记录栈中
      history.pushState({name:'home',id:1},null,"?page=home#index")
      showCard('home')
    };

    function message() {
      history.pushState({name:'message',id:2},null,"?page=message#haha")
      showCard('message')
    }

    function mine(){
      history.pushState({
        id:3,
        name:'mine'
      },null,"?name=tigerchain&&sex=man")
      showCard('mine')
    }

    // 监听浏览器回退 并且刷新到指定内容
    window.addEventListener('popstate',function (event) {
      var content = "";
       if(event.state) {
         content = event.state.name;
       }
       console.log(event.state)
       console.log("history 中的历史栈中的 name :"+content)
       showCard(content)
    })
    // 此方法和上面的方法是一毛一样的,只是两种不同的写法而已
    // window.onpopstate = function (event) {
    //   var content = "";
    //   if(event.state) {
    //     content = event.state.name;
    //   }
    //   showCard(content);
    // }

    function showCard(name) {
     console.log("当前的 hash 值是:"+location.hash)
     document.getElementById("showContent").innerHTML = name;
    }
  </script>

vue路由

新建router.js,引入vue 和 vue-router:

import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter);

export default new VueRouter({
    routes: [
        {
            path: '/',
            name: 'index',
            meta: {
                title: '首页'
            },
            component: index
        },
        {
            path: '/list',
            name: 'list',
            meta: {
                title: '列表'
            },
            component: list
         }
    ]
})

注入到vue实例中:

import router from './router';

new Vue({
    el: '#app',
    template: '<App/>',
    components: { App },
    router,
    store
});

在App.vue中引用:

<template>
    <div id="app">
        <div class="main" :style="{height:cHeight}">
            <transition :enter-active-class="enterActive" :leave-active-class="leaveActive" >
                <keep-alive include="index,list,city">
                    <router-view id="router"></router-view>
                </keep-alive>
            </transition>
            <!-- toast -->
            <Toast></Toast>
            <!-- 提示框 -->
            <Pop-Up></Pop-Up>
            <!-- 接口loading -->
            <div class="loading-box" v-show="isLoading">
                <loadings :contentLoading="isLoading"></loadings>
            </div>
        </div>
        <iphoneX v-if="isIphoneXShow"></iphoneX>
    </div>
</template>

<router-link>

属性:to 、replace、 append、  tag、  active-class、 exact 、 event、  exact-active-class

to:值为当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象,如 to="home" 或 :to="{path: 'home'}";

tag: <router-link> 渲染成的标签,如 <li>;

event:触发跳转路由的事件,默认为cick,如如鼠标移入事件为event="mouseover";

replace:设置 replace 属性,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录;

<router-view>

router-view是承载路由的容器,它渲染的组件是 vue-router 指定的。即在如下图中文件中设置的每个路由项:

 

嵌套路由

导航组件中有三个导航链接,他们的地址分别为:/food,/rating,/seller,点击每个导航链接都会跳转到相应的组件:

<template>
 <div class="navbar">
 <ul id="main">
 <li><router-link to="/food" >商品</router-link></li>
 <li><router-link to="/rating">评价</router-link></li>
 <li><router-link to="/seller">商家</router-link></li>
 </ul>
   <!-- 路由匹配到的组件将渲染在这里 -->
   <router-view></router-view>
 </div>
</template>

路由配置:

{
    path: '/',
    name: 'index',
    component: index,
    redirect:'/food',
    children:[
        {
        path: 'food',
        name: 'food',
        component: food
        },
        {
        path: 'seller',
        name: 'seller',
        component: seller
        },
        {
        path: 'rating',
        name: 'rating',
        component: rating
        }
    ]
},

路由的过渡动画

想让路由有过渡动画,需要在<router-view>标签的外部添加<transition>标签,在transition标签加上两个类:enter-active-class  和 leave-active-class:

<transition enter-active-class="animated bounce" leave-active-class="animated hinge">
    <router-view></router-view>
</transition>

vue路由钩子函数

全局路由钩子函数

router.beforeEach:全局路由前置守卫,进入每一个路由之前会执行beforeEach里的函数,有next会影响导航:

import router from './router';    // 引入上边的router.js文件

router.beforeEach((to, from, next) => {
     // to是跳转后的页面路由,from是跳转前的页面路由
     // next()是必须要执行的,加上next()路由才会跳转
}); 

router.afterEach:全局后置钩子,在路由跳转结束的时候调用,没有next不会影响导航:

router.afterEach((to, from) => { 
    if( to.meta.title ){
      window.document.title = to.meta.title;   // 每个路由下title
  }else{
    window.document.title = '默认的title';
  }
});

router.beforeResolve(v2,5,0+):全局解析守卫,在 beforeEach 和组件内beforeRouteEnter 之后执行

组件路由钩子函数

beforeRouteEnter:在渲染当前组件的对应路由之前调用,用法和参数与beforeEach类似(在beforeEach之后执行),next需要被主动调用,next中函数的调用在mounted之后:为了确保能对组件实例的完整访问

beforeRouteEnter (to, from, next) {
  // 这里还无法访问到组件实例,this === undefined
  next( vm => {
    // 通过 `vm` 访问组件实例
  })
}

beforeRouteUpdate(v2.2+):

 beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 可以访问组件实例 `this`
  },

beforeRouteLeave:离开当前路由时调用

beforeRouteLeave(to, from, next){
    // 当离开组件时,是否允许离开,可以访问组件实例'this'
  next();
}

$route 和 $router的区别

router是VueRouter的一个对象,通过VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性:

 

 

route是单个的路由对象,每一个路由都会有一个route对象,是一个局部的对象,可以获取对应的name,path,params,query等:

路由跳转

1 router-link

<router-link :to="{name:'home', params: {id:1}}">

2 跳转到指定url路径,并想history栈中添加一个记录,点击后退会返回到上一个页面

this.$router.push({name:'home',params: {id:'1'}})

3 跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面)

this.$router.replace() 
// 用法同push

4 向前或者向后跳转n个页面,n可为正整数或负整数

// 在浏览器中前进一步,等同于history.forward()
this.$router.go(1)

// 在浏览器中后退一步,等同于history.back()
this.$router.go(-1)

// 前进三步
this.$router.go(3)

// 如果history中的记录不够用,默认失败
this.$router.go(100)
this.$router.go(-100)

路由传参

1 路径带参数

// 直接调用$router.push 实现携带参数的跳转
this.$router.push({
    path: `/describe/${id}`,
});

// 需要对应的路由配置
{
     path: '/describe/:id',
     name: 'Describe',
     component: Describe
}

// 获取
this.$route.params.id

2 通过路由属性中的name来确定匹配的路由,通过params来传递参数

// 参数配置
this.$router.push({
          name: 'Describe',
          params: {
            id: id
          }
});
// 路由配置
{
     path: '/describe',
     name: 'Describe',
     component: Describe
}
// 获取
this.$route.params.id

3 使用path来匹配路由,然后通过query来传递参数

// 跳转带参数
this.$router.push({
          path: '/describe',
          query: {
            id: id
          }
});
// 路由配置
{
     path: '/describe',
     name: 'Describe',
     component: Describe
}
// 获取
this.$route.query.id

router的模式

包括三种模式:

Hash: 使用URL的hash值来作为路由。支持所有浏览器;
History: 依赖HTML5 History API 和服务器配置;
Abstract: 支持所有javascript运行模式。如果发现没有浏览器的API,路由会自动强制进入这个模式;

hash:hash模式背后的原理是onhashchange事件,可以在window对象上监听这个事件:

window.onhashchange = function(event){
    console.log(event.oldURL, event.newURL);
}

history:监听onpopstate,包括了pushState、replaceState两个方法,这两个方法接收三个参数:stateObj,title,url

 

 

 

 

 

原文:

https://www.jianshu.com/p/9a7d79249741

https://www.jb51.net/article/149409.htm

https://www.jianshu.com/p/55d41142a147

posted @ 2020-04-08 19:46  seeBetter  阅读(210)  评论(0编辑  收藏  举报