zoukankan      html  css  js  c++  java
  • 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;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

  • 相关阅读:
    深入理解多态..............................
    走过路过 不要错过..
    进军C#..
    员工打卡....
    MySQL
    MySQL
    MySQL
    MySQL
    MySQL
    MySQL
  • 原文地址:https://www.cnblogs.com/xjy20170907/p/12662103.html
Copyright © 2011-2022 走看看