zoukankan      html  css  js  c++  java
  • Vue 路由

    在单页应用中常常要用到路由。

    传统的页面跳转是浏览器请求新的页面,渲染整个新的页面。

    单页应用是把要跳转的页面的以组件的形式集成在当前页面中,跳转时浏览器不用发起新请求,因为目标页面是当前页面的一部分,直接显示目标页面那一部分即可。

    demo  在单页应用中使用路由

    1、下载路由插件

    npm install vue-router -S

    install可以简写为i

    我们要使用的是里面的vue-router.js文件

    2、写一个test.html

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title></title>
            <!-- 引入vue.js -->
            <script src="js/vue.js"></script> 
            <!-- 引入路由插件。上线时均要换为xxx.min.js -->
            <script src="js/vue-router.js"></script>
        </head>
        <body>
            
        <div id="app"></div>
        
        <script>
            // 首页组件
            var Index={
                template:`
                    <div>
                        <p>this is the index page</p>
                        <p><a href="#/login">login</a></p>  <!-- 注意url写法,#/开头 -->
                        <p><a href="#/register">register</a></p>
                    </div>
                `
            }
            
            // 登录组件
            var Login={
                template:`
                    <div>
                        <p>this is the login page</p>
                        <p><a href="#/index">index</a></p>
                        <p><a href="#/register">register</a></p>
                    </div>
                `
            }
            
            // 注册组件
            var Register={
                template:`
                    <div>
                        <p>this is the register page</p>
                        <p><a href="#/index">index</a></p>
                        <p><a href="#/register">register</a></p>
                    </div>
                `
            }
                
            // 安装路由插件
            Vue.use(VueRouter);
            
            // 创建路由对象
            var router=new VueRouter({
                // 配置路由规则
                routes:[  //对象数组
                    {path:'/index',name:'index',component:Index}, //path指定映射地址,注意没有#,component指定对应的组件
                    {path:'/login',name:'login',component:Login},
                    {path:'/register',name:'register',component:Register},
                ]
            });
            
            new Vue({
                el:'#app',
                router,  //启用路由。原本是router:router,可以简写
                template:`
                    <div>
                        <!--路由页面只是当前页面的一部分,当前页面可以写一些其他内容,写的内容是所有路由页面-->
                        <p>this is common area</p>
                        <router-view></router-view>  <!--引入路由页面。路由到哪个页面,就用对应的组件替换这部分-->
                    </div>
                `
            })
        </script>        
            
        </body>
    </html>

    3、运行

    假设test.html的地址是:http://127.0.0.1:8848/vue/test.html#/      注意后面有个#

    则index的地址是:http://127.0.0.1:8848/vue/test.html#/index

    login的地址是:http://127.0.0.1:8848/vue/test.html#/login

    register的地址是:http://127.0.0.1:8848/vue/test.html#/register

    3个页面,但实际上路由的3个页面都在test.html中。

    <router-view></router-view>是一个路由容器,用来容纳路由页面。

    单页应用的两种路由模式

    • 哈希模式(利用hashchange 事件监听 url的hash 的改变)
    • history模式(需要后台配合把接口都打到我们打包后的.html文件上,比如上用test.html打包路由页面,test.html相当于一个容器)

    demo中使用的是哈希模式

    哈希模式实现路由跳转的原理

        // 监听地址栏url的改变,haschange是预定义事件
        window.addEventListener("hashchange",function(e){  //haschange事件发生时,会封装事件以参数的形式传给处理函数
            console.log(e);  //这个对象的部分信息: {..., oldURL: "http://127.0.0.1:8848/vue/test.html#/index", newURL: "http://127.0.0.1:8848/vue/test.html#/register", type: "hashchange", …}
            console.log(location.hash); //地址栏的url已改变,获取新的url的hash。带有#/,比如#/index,#/login
            // console.log(location); //location是不带#/的,比如index、login
            
            switch(location.hash){  //根据路由配置决定和哪些常量比较。这些常量就是路由配置中的path
                case '#/index':
                    //...   //如果匹配就用对应的组件替换<router-view></router-view>部分
                    break;
                case '#/login':
                    break;
                case '#/register':
                    break;
            }
        })

    路由跳转的3种方式

    • <a>链接
    • <router-link>标签
    • $router对象
        new Vue({
            el:'#app',
            router,
            template:`
                <div>
                    <p>
                        <a href="#/index">index</a>  <!-- 要带# -->
                        <router-link to="/login">login</router-link>  <!-- 不带# -->
                        <button @click="goRegister">register</button>
                    </p>
                    <router-view></router-view> 
                </div>
            `,
            methods:{
                goRegister(){
                    this.$router.push({path:'/register'});  //不带#
                }
            }
        })
        

    <router-link>、$router都是路由插件里的东西,都用路由了,那url中指定有#号,它自己会加#号,所以我们写路径的时候不加#号。

    <a>是html的标签,不知道url中有没有#号,所以需要我们自己加上。

    $router的常用方法

    • push()  跳转到指定的页面,会往history中插入一条新纪录
    • replace()   和push()的用法、作用相同,只是replace()不会往history中插入一条新纪录
    • go(-1)   跳转到history中的上一条记录,相当于点击浏览器的后退箭头。
    • forward(1)  跳转到history中的下一条记录,相当于点击浏览器的前进箭头。

    $router还有个兄弟$route,和$router不同,$route封装了路由信息,只有属性(可以理解为是只读的),常用的属性比如hash、path、query、params。

    路由的传参和取参

    1、<a>链接方式

        // 首页组件
        var Index={
            template:`
                <div>
                    <p>this is the index page</p>
                    <p>{{this.$route.query.username}}  {{this.$route.query.username}}</p>  <!-- 如果只在载入此组件时使用,直接取就行了 -->
                    <p>{{username}} {{password}}</p>  <!-- 如果后续还要使用,需要保存到内存变量中 -->
                </div>
            `,
            data(){
                return{
                    username:'',
                    password:''
                }
            },
            created(){  //路由到此组件|页面时,会新建此组件的实例,在created()中获取传来的数据
                this.username=this.$route.query.username;  //$route,没有r,a链接只能用query来取
                this.password=this.$route.query.password;
            }
        }
            
        // 安装路由插件
        Vue.use(VueRouter);
        
        // 创建路由对象
        var router=new VueRouter({
            // 配置路由规则
            routes:[ 
                {path:'/index',name:'index',component:Index}, 
            ]
        });
        
        new Vue({
            el:'#app',
            router,
            template:`
                <div>
                    <a href="#/index?username=chy&password=abcd">index</a>  <!-- 传递参数 -->
                    <router-view></router-view> 
                </div>
            `
        })

    参数以查询字符串的形式拼接在url中:http://127.0.0.1:8848/vue/test.html#/index?username=chy&password=abcd

    2、<router-link>方式有2种

    (1)query

       <!-- to前面有冒号,我这里使用的是路由配置里的name。query -->
       <router-link :to="{name:'index',query:{username:'chy',password:'abcd'}}">index</router-link>  

    查询字符串的形式拼接参数,获取时也是$route.query的方式,url中会带有参数:http://127.0.0.1:8848/vue/test.html#/index?username=chy&password=abcd

    (2)params

    <!--params,post方式-->
    <router-link :to="{name:'index',params:{username:'chy',password:'abcd'}}">index</router-link> 

    要用$route.params来接收,用什么传递就用什么接收。

    url中不显示参数,更安全:http://127.0.0.1:8848/vue/test.html#/index

    params方式的路由配置还可以这样写:

        // 创建路由对象
        var router=new VueRouter({
            // 配置路由规则
            routes:[ 
                {path:'/index/:username',name:'index',component:Index},
            ]
        });

    :参数名  可以获取对应的参数值,http://127.0.0.1:8848/vue/test.html#/index/chy,url是RESTful风格

    3、$router对象方式

        new Vue({
            el:'#app',
            router,
            template:`
                <div>
                    <button @click="goIndex">index</button>
                    <router-view></router-view> 
                </div>
            `,
            methods:{
                goIndex(){
                    this.$router.push({name:'index',query:{username:'chy',password:'abcd'}});
                }
            }
        })

    说明

    <router-link>、$router对象方式,都可以使用query或params来传递参数,都可以使用path或name来指定路由页面,

    如果路由配置的path是:  {path:'/index/:username',name:'index',component:Index}   这种随参数的变化而变化的,那就使用name。

    路由传参参数不刷新的问题

    现象

      <router-link :to="{name:'index',params:{username:'chy1',password:'abcd1'}}">index</router-link>  
      <router-link :to="{name:'index',params:{username:'chy2',password:'abcd2'}}">index</router-link>  

    比如第一次路由到index页面,携带的参数是{username:'chy1',password:'abcd1'},

    后续再路由到此页面时,比如要携带的参数是{username:'chy2',password:'abcd2'},新的参数传过去了,但使用的参数是第一次路由到此页面时携带的参数。

    即传到同一路由页面的参数不会刷新,3种方式都存在这个问题。

    原因

    Vue路由会复用组件,我把变量赋值写在created()中,这个钩子函数只在组件创建时执行,就是说变量赋值只执行1次(第一次路由到此页面时)。

    后续再次路由到此页面时,新的参数是传过去了,但变量赋值不会再执行,新的参数也就没有赋给变量。

    如果只在传过去的时候使用参数,后面不再使用参数,可以  {{this.$route.query|params.参数名}}  直接取。

    如果要把参数赋给变量,方便后续使用,该怎么做?

    2种解决方案

    1、使用  :key 唯一标识一次路由

        // 创建路由对象
        var router=new VueRouter({
            // 配置路由规则
            routes:[ 
                {path:'/index',name:'index',component:Index},
            ]
        });
            
        new Vue({
            el:'#app',
            router,
            template:`
                <div>
                    <router-link :to="{name:'index',query:{username:'chy1',password:'abcd1'}}">index</router-link>  
                    <router-link :to="{name:'index',query:{username:'chy2',password:'abcd2'}}">index</router-link>  
                    <router-view :key="$route.fullPath"></router-view> 
                </div>
            `,
    
        })

    query方式(<a>链接也是query方式),路由配置的写为/index的形式

    因为根据url的hash来判断是否是同一个路由页面,默认的:key是/index这种形式,会认为是同一个路由页面;

    现在设置:key="$route.fullPath"(注意P是大写),以完整的url来判断,query方式会在url中拼接参数,能区分不同的参数传递。

      // 创建路由对象
        var router=new VueRouter({
            // 配置路由规则
            routes:[ 
                {path:'/index/:username',name:'index',component:Index},
            ]
        });
            
        new Vue({
            el:'#app',
            router,
            template:`
                <div>
                    <router-link :to="{name:'index',params:{username:'chy1',password:'abcd1'}}">index</router-link>  
                    <router-link :to="{name:'index',params:{username:'chy2',password:'abcd2'}}">index</router-link>  
                    <router-view :key="$route.fullPath"></router-view> 
                </div>
            `,
    
        })

    params方式,因为使用post传递参数,url中不带参数,url(的hash)都是一样的,怎么区别?

    路由配置的 path:'/index/:username' 中带上唯一的参数标识,比如username、uid等,这样url就不同了

    说明

    (1)此种方式,:key能唯一标识一次参数传递即可,不一定要是$route.fullPath,比如可以是:

    :key="$route.fullPath"   //完整的url
    :key="$route.query|params.username|uid"  //能唯一标识一次参数传递的参数  
    :key="new Date().getTime()"  //时间戳(这个是毫秒级的)。使用时间戳时,就算2次路由的参数完全相同,也会重新创建路由页面的组件

    (2)此种方式,只要:key的值不同,就会重新创建路由页面的组件,性能影响大,不太推荐。

    2、数据监听

        // 首页组件
        var Index={
            template:`
                <div>
                    <p>this is the index page</p>
                    <p>{{username}}  {{password}}</p>
    
                </div>
            `,
            data(){
                return{
                    username:'',
                    password:'',
                }
            },
            // created(){  //可以不要created()
            //     this.username=this.$route.params.username;
            //     this.password=this.$route.params.password;
            // },
            watch:{  //监听$route.query|params,当然直接监听$route也行
                '$route.params'(){ //因为有.号,所以要要引起来,不然识别不了
                    this.username=this.$route.params.username;  //参数变化时就重新获取参数
                    this.password=this.$route.params.password;
                }
            },    
        }
                
            
        // 安装路由插件
        Vue.use(VueRouter);
            
        // 创建路由对象
        var router=new VueRouter({
            // 配置路由规则
            routes:[ 
                {path:'/index/:username',name:'index',component:Index},  //query方式写成/inedx,params方式写成/index/:username
            ]
        });
            
        new Vue({
            el:'#app',
            router,
            template:`
                <div>
                    <router-link :to="{name:'index',params:{username:'chy1',password:'abcd1'}}">index</router-link>  
                    <router-link :to="{name:'index',params:{username:'chy2',password:'abcd2'}}">index</router-link>  
                    <router-view></router-view>  <!--不需要使用:key-->
                </div>
            `,
        })

    这种方式,路由到同一个页面时,会复用组件,不重新创建组件,开销小,推荐。

  • 相关阅读:
    "SoftwareHex-RaysIDA" exists, but no "Python3TargetDLL" value found No Python installations were found
    visual studio修改安装位置
    ror13hash
    IMAGE_DIRECTORY_ENTRY_SECURITY【证书属性表
    华为云自动学习物体检测(滑动窗口)
    Java BigInteger中的oddModPow
    vue 动态路由传参三种方式
    git根据项目地址使用不同代理服务器
    关于MySQL8的WITH查询学习
    有1、2、3、4个数字,能组成多少个互不相同 且无重复数字的三位数?都是多少?
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/12621141.html
Copyright © 2011-2022 走看看