vue 路由进阶

2019-06-16 admin

路由可向路由匹配的组件传递参数,不同情况向组件传递不同的参数,从而实现组件的复用。

路由向组件传递参数

和路由匹配的组件可以在组件中使用 $route 获取路由上的参数:

传参方式

:paramsquery

:在路径传递参数

{
    path: "/argu/:id/book",
    name: "argu",
    component: () => import("@/views/ArguPage")
}

路径中的一部分是参数,必须传递该参数:

<!--路径跳转-->
<router-link to="/argu/123/book">path跳转</router-link>
<!--路由名跳转-->
<router-link :to="{name:'argu',params:{id:'test'}}" tag="button">name+params跳转</router-link>
<!--获取参数-->
<h1>{{$route.params.id}}</h1><!--params的名字路径中的的参数名一致-->

此时 path+ parmas传递参数,params会被忽略。

params+name传递参数

路由:

{
    path: "/argu",
    name: "argu",
    component: () => import("@/views/ArguPage")
}

跳转方式是 name+params+(query),通过path跳转,params 会被忽略。

<router-link :to="{name:'argu', params:{name:'hangge'}}">
  跳转到 hello
</router-link>
// path + params ,params 会被忽略,因为路径中没有定义参数
<router-link :to="{path:'/argu', params:{name:'hangge'}}">
  跳转到 hello
</router-link>

query 参数

query 参数参数,表现为查询字符串,和localtion.serach一样的。

不需要先在路径中先定义,可通过pathpath+query 或者 name + query 传递参数。

<router-link to="/argu?queryName=value">跳转到 hello</router-link>
<router-link :to="{path:'/argu',query:{queryName:value}}">跳转到 argu</router-link>
<router-link :to="{name:'argu',query:{queryName:value}}">跳转到 argu</router-link>
<h1>{{ $route.query.queryName }}</h1>

函数传递 query

// 主要是  $router 不是 $route
go() {
    this.$router.push({
        name: 'argu',
        query: {
                queryName: "你好"
            }
        })
    }
}

但是这样使得 $route 和组件耦合在一起,不方便组件的复用,如果能将路由中的参数传递到 组件的props 就好了,恰恰是可以这样设置的。

props 接收路由的 params

路由传参数的三种方式:

  1. 布尔模式
{
    path: '/user/:id', 
    component: User, 
    props: true //表明 将 id 作为 proos 传递到匹配的组件 User 中。
}

User 中定义 props 接收 id:

export default {
    props:{
        id:{
            type:String,
            default:'jackzhou'//默认值
        }
    }
}
  1. 对象模式

将路由的 props 属性设置一个对象,也可在组件中获取到该值,这种方式往往用于传递静态值,即 name 值不会变化。

路由对象:

{
    name: 'home',
    alias:'/home_page',
    path: '/',
    props:{name:'jack jack'},
    component: Home
}

Home 组件:

props:{
    name:{
        type:String,
    }
}
  1. 函数模式

以上两种方式,params 参数的名字必须和组件中的props 属性名字相同,如果想对 params 进行改造后传递到组件,就可将 props 设置成函数,在函数内获取路由中的 params 或者 query,或者其他属性值,对其进行处理后再传递给组件。

注意:这种方式函数必须返回一个对象。

路由:

{
    name: 'about',
    path: '/about/:years', //params 有一个参数 years
    props:(route) {
          const now = new Date()
          return {
        // 将 years 改造成 name
        name: (now.getFullYear() + parseInt(route.params.years)) + '!'
        }
        },
    component: () => import('@/views/AboutPage'),
}

组件中的 props:

props: {
    name: {
        type: String
    }
}

命名视图的路由,要为每个命名视图添加 props

{
    path:'/name/:view',
    name:'name_view',
    components:{
        default:()=>import('@/views/ChildPage'),
        sister:()=>import('@/views/SisterPage'),
        brother:()=>import('@/views/BrotherPage'),
    },
    props:{
        default:true,
        sister:false,
        brother:(route)=>({view:route.params.view.toUpperCase()})
    }
}

完整的例子

{% raw %} <p class=“codepen” data-height=“573” data-theme-id=“0” data-default-tab=“js,result” data-user=“JackZhouMine” data-slug-hash=“JqBzWE” style=“height: 573px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;” data-pen-title=“route 的 params 传递组件”> <span>See the Pen route 的 params 传递组件 by JackZhouMine (@JackZhouMine) on CodePen.</span> </p> <script async src="https://static.codepen.io/ass…;></script> {% endraw %}

HTML5 History 模式

路由配置里有一个属性 mode ,默认值是 hash,以hash来模拟一个url,url改变时,页面不会重新加载。

先使用普通模式,可将 mode 设置成 history,这种模式会使用 history.pushSate 来完成url跳转而页面不会重新加载。这种模式需要服务器设置一下

使用 history 模式,因为web应用往往是单页应用,当用户访问一个不存在的路径时,需要提供一个后备页面。

在路由配置的最后增加一个404路由:

{
    path:'*',
    component:NotFoundPage// 前面没有匹配的路由,最后会匹配该路由。
}

meta 元信息

可在路由对象中配置 meta 属性,meta 是一个对象。

比如,根据不同页面显示不同的 title。

{
    name: "about",
    path: "/about",
    meta: {
        title: "关于"
    },
       component: () => import("@/views/AboutPage")    
}

在路由配置文件中,设置各个页面的 title:

const router= new Router({
    routes
})
router.beforeEach((to,from,next)=>{
    //setTitle 函数用于设置页面标题
    to.meta&&setTitle(to.meta.title) //这是简化if语句的简写
    console.table(to)
    console.table(from)
    next()
})
export default router

导航守卫

全局守卫

  1. 全局前置守卫
const router = new Router({
    {
        path:"/",
        name:"heom_page"
        component:Home,
        //路由独享守卫
        beforeEnter:(to,from,next)=>{
            //处理逻辑
            next()
        }
    }
})
//每次路由进入都会调用
router.beforeEach((to,from,next)=>{
    //处理逻辑,比如登录判断,可跳转到任意页面
    //不要忘记调用 next,不调用 next,页面不会跳转
})
  1. 后置钩子
//路由跳转之后做一些操作,比如去掉登录样式
router.afterEach((to,form)=>{
    //逻辑处理
})
  1. 路由独享守卫

只在匹配某个路由时执行。

  1. 组件内守卫

beforeRouteEnter, 组件创建之前调用,组件不具备thisbeforeRouteUpdate,路由更新,而组件被复用时调用,可使用thisbeforeRouteLeave,离开路由时调用,可使用this

export default{
    name:'Home',
    data(){
        return {}
    },
    /**
    * 组件内路由守卫
    * 1\. 该函数在路由进入时执行
    * 2\. 此时 组件还未渲染,不可用 this,当可在  next 中用 vm
    * 3\. next 晚于 mounted 执行,next 之前的代码,早于beforeCreate       *       执行
    * 4\. 最后需要调用 next 使得路由跳转
    */
    beforeRouteEnter(to, from, next) {
        console.log("①,home 组件内路由守卫,beforeRouteEnter");
        // next 晚于 mounted 执行,next 之前的代码,早于beforeCreate 执行
        next((vm)=>{
            console.log('vm')
            console.log(vm)//有值
            console.log('this')
            console.log(this)// undefined
            console.log('②,home 组件内路由守卫,beforeRouteEnter');
        });
    },
    /**
    * 组件内路由守卫
    * 1\. 该函数在路由离开时执行,最先调用,然后在调用全局守卫,再调用        *     beforeDestroy
    * 2\. 此时,该路由守卫所在组件已渲染,可用 this
    * 3\. 最后需要调用 next 使得路由跳转
     */
    beforeRouteLeave(to, from, next) {
        console.log("①,home 组件内路由守卫,beforeRouteLeave");
        let leave = confirm("你确定要离开 home 页吗?");
        if (leave) {
        // console.log(to.name, from.name);
        // console.log(this);
        next(() => {
            console.log('②,home 组件内路由守卫,beforeRouteLeave');
            }); //给 next 传递 false ,路由不会跳转
        } else {
            next(false);
        }
    },
    /*
    * 当路由发生变化,而组件被复用时调用
    * 1\. 此时该复用组件已被渲染,可用 this
    * 2\. 需要调用 next,组件才能渲染
    */
    beforeRouteUpdate(to, from, next) {
        console.log('①,argu,组件内路由守卫,beforeRouteUpdate');
        next(() => {
            console.log('next,argu,组件内路由守卫,beforeRouteUpdate');
        });
    },
    beforeCreate() {
        console.log('beforeCreate')
    },
    created() {
        console.log('created')
    },
    beforeMount() {
        console.log('beforeMount')
    },
    mounted() {
        console.log('mounted')
    },
    beforeUpdate() {
        console.log('beforeUpdate')
    },
    updated() {
        console.log('updated')
    },
    beforeDestroy() {
        console.log('beforeDestroy')
    },
    destroyed() {
        console.log('destroyed')
    }
}

路由全过程:

  1. 导航被触发
  2. 离开页面(失活的组件)里调用离开守卫 beforeRouteLeave
  3. 调用全局前置守卫 beforeEach
  4. 在重用的组件里调用 beforeRouteUpdate (非重用组件,没有这个步骤)
  5. 调用路由独享守卫 beforeEnter
  6. 解析异步路由组件
  7. 在进入页面(激活组件)调用 beforeRouteEnter
  8. 调用全局解析守卫 beforeResolve (导航被确认之前,组件内守卫和异步路由组件被解析之后,调用 beforeResolve)
  9. 导航被确认(什么时候被确认,全部钩子执行完了,是被确认的)
  10. 调用全局后置守卫 afterEach
  11. 触发 DOM 更新
  12. 在 vue 实例中(此时页面解析完毕了吗?是的)调用 beforeRouterEnter 守卫里传给 next 的回调。nextmounted之后被调用。

过渡效果

可以给路由匹配的组件设置过渡效果,让页面平滑地显示,提升用户体验。 需要用到 transition 标签,如果有多个视图需要过渡,则用 transition-group

<transition-group name='router-view'>
<!-- 视图渲染组件,该组件内不需要房子任何内容,可写成只闭合标签-->
    <router-view  key='default'/>
    <!-- 有多个路由视图需要匹配,则用命名视图 -->
    <router-view key='sister' name="sister"></router-view>
    <router-view key='brother' name="brother"></router-view>
</transition-group>

css 过渡效果:

    .router-view-enter{
        opacity: 0;
    }
    .router-view-enter-active{
        transition: opacity 1s ease;
    }

    .router-view-enter-to{
        opacity: 1;
    }
    .router-view-leave{
        opacity: 1;
    }
    .router-view-leave-active{
        transition: opacity 1s ease;
    }

    .router-view-leave-to{
        opacity: 0;
    }

这些设置,每个页面的效果都是一样的,要为不同的页面设置不同的效果,可用路由传递相应的参数来,让动态绑定到 transition 的 name 属性上。

或者监听路由变化:

watch: {
    '$route'(to){
        console.log(to);
        to.params&&to.params.view&&(this.effect = to.params.view)
    },
}

参考

Vue.js - 路由 vue-router 的使用详解2(参数传递)

[转载]原文链接:https://segmentfault.com/a/1190000019492529

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-67455.html

文章标题:vue 路由进阶

相关文章
vuejs通过filterBy、orderBy实现搜索筛选、降序排序数据
直接贴代码了: 先上输入前的样子: &lt;style&gt; #example{margin:100px auto;width:600px;} .show{margin:10px;} #searchText{display: block...
2017-03-17
最细致的vue.js基础语法 值得收藏!
介绍 前段时间接触到一个库叫做Vue.js, 个人感觉很棒,所以整理了一篇博文做个介绍。 Vue读音/vju:/,和view类似。是一个数据驱动的web界面库。Vue.js只聚焦于视图层,可以很容易的和其他库整合。代码压缩后只有24kb。 ...
2017-03-21
mpvue 小程序如何开启下拉刷新,上拉加载?
https://developers.weixin.qq.com/miniprogram/dev/api/pulldown.html#onpulldownrefresh 小程序API 微信小程序之下拉加载和上拉刷新 微信小程序下拉加载和上拉...
2018-05-25
JavaScript正则进阶之路——活学妙用奇淫正则表达式
有些童鞋肯定有所疑惑,花了大量时间学习正则表达式,却发现没有用武之地,正则不就是验证个邮箱嘛,其他地方基本用不上,其实,大部分人都是这种感觉,所以有些人干脆不学,觉得又难又没多大用处。殊不知,想要成为编程大牛,正则表达式必须玩转,GitH...
2017-05-31
vue使用watch 观察路由变化,重新获取内容
问题背景: 点击用户头像 =&gt; 进入用户个人中心,在用户个人中心里点击其他用户的头像,我希望显示被点击用户的个人中心,但只看到了路由参数在发生变化,页面内容并没有更新。如图: 页面代码如下: &lt;script&gt; exp...
2017-03-13
在 mpvue 使用 echarts 小程序组件
具体操作 下载 echarts-for-weixin 。 把其 ec-canvas 目录移动到 mpvue 项目的 static 目录下。 对 ec-canvas/ec-canvas.js 进行小调整,考虑提 pr 到 ec-c...
2018-03-11
mpvue 小程序如何自定义tabBar,不使用navigateTo跳转,模拟redirectTo跳转
原生tabBar tabBar: { &quot;list&quot;: [ { pagePath: &quot;pages&#x2F;index&#x2F;main&quot;, iconPath: &...
2018-05-25
VuePress 快速踩坑
最近有个开源项目非常火,那就是尤小右开发的 VuePress,VuePress 可以让您非常方便的在 Markdown 文档中编写 Vue 代码,并且 VuePress 对编译后的 HTML 文件做了一些针对搜索引擎的优化。另外 VuePr...
2018-04-27
Vue 短信验证码组件开发详解
Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据驱动的 web 界面的库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。 Vue.js 自身不是一个全能框架——它只聚焦于视图层。因此...
2017-03-17
vue-video-player 更改视频源
背景:根据用户的信息来显示不同的视频源 &lt;template&gt; &lt;div class=&quot;video-box-wrap&quot; v-show=&quot;video.show&quot;&gt; ...
2018-05-05
回到顶部