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

  • 相关阅读:
    Meten Special Activities II
    Meten Special Activities II
    Meten Special Activities II
    Meten Special Activities II
    Meten Special Activities
    Meten Special Activities
    Meten Special Activities
    Meten Special Activities
    Meten Special Activities
    冒泡排序和选择排序
  • 原文地址:https://www.cnblogs.com/xjy20170907/p/12662103.html
Copyright © 2011-2022 走看看