zoukankan      html  css  js  c++  java
  • vue-router基本使用

    Vue Router功能

    • 嵌套的路由/视图表
    • 模块化的、基于组件的路由配置
    • 路由参数、查询、通配符
    • 基于 Vue.js 过渡系统的视图过渡效果
    • 细粒度的导航控制
    • 带有自动激活的 CSS class 的链接
    • HTML5 历史模式或 hash 模式,在 IE9 中自动降级
    • 自定义的滚动条行为

    安装

    1. CDN
       <script src="https://unpkg.com/vue/dist/vue.js"></script>
       <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
      
    2. npm
      npm install --save-dev vue-router
      
      import Vue from 'vue';
      import VueRouter from 'vue-router'
      Vue.use(VueRouter)
      

    基本用法

    在html中应用

    <div id="app">
        <h1>Hello App!</h1>
        <p>
            <!-- 使用 router-link 组件来导航. -->
            <router-link to="/foo">Go to Foo</router-link>
            <router-link to="/bar">Go to Bar</router-link>
        </p>
        <!-- 路由出口 路由匹配到的组件将渲染在这里-->
        <router-view></router-view>
    </div>
    

    js部分

    // 1. 定义组件
    const Foo = { template: '<div>foo</div>' }
    const Bar = { template: '<div>bar</div>' }
    
    // 2. 定义路由。每个路由应该映射一个组件
    const router = new VueRouter({
        routes:[
            { path: '/foo', component: Foo },
            { path: '/bar', component: Bar }
        ]
    })
    // 3. 创建和挂载根实例。
    // 记得要通过 router 配置参数注入路由,
    const app = new Vue({
        router
    }).$mount('#app')
    

    模块化应用

    1. vue create一个实例
    2. 创建组件(components文件夹)
    3. router.js
    //1.加载vue与vue-router
    //2.导入相应组件
    //3.编写并导出路由
    
    import VueRouter from 'vue-router'
    Vue.use(VueRouter)
    import Vue from 'vue'
    import PageHome from './components/pages/Home';
    import PageAbout from './components/pages/About';
    const router=new VueRouter({
        routes:[
            {
                path:'/',
                component:PageHome
            },
            {
                path:'/about',
                component:PageAbout
            },
        ]
    })
    export default router
    
    1. main.js导入路由
    2. App.vue呈现路由视图<router-view/>

    嵌套路由

    嵌套路由允许指定子路由,并且用另一个<router-view/>来显示其内容。假设这里有两个单页面,一个为address一个为email,他们共用header和nav:

    image.png

    1. 在common中创建两个共用组件:NavHeaderNavLeft

    2. 在pages创建主页面Settings.vue和两个子组件SettingsAddressSettingsEmail

      image.png

    3. 将公共组件放在主页面Settings.vue中,其中router-view展现的是其子路由。可以适当加样式

      <template>
         <div>
            <NavHeader/>
            <NavLeft/>
            <router-view/>
         </div>
      </template>
      
      <script>
      import NavHeader from '../common/NavHeader'
      import NavLeft from '../common/NavLeft'
      export default{
         name:'Settings',
         components:{
            NavHeader,
            NavLeft
         }
      }
      </script>
      
    4. router.js

      //...
      import PageSettings from './components/pages/Settings';
      import PageSettingsEmail from './components/pages/SettingsEmail';
      import PageSettingsAddress from './components/pages/SettingsAddress';
      
      const router=new VueRouter({
         routes:[
            {
                  path:'/settings',
                  component:PageSettings,
                  children:[
                     {
                        path:'email',
                        component:PageSettingsEmail
                     },
                     {
                        path:'address',
                        component:PageSettingsAddress
                     },
                  ]
            },   
         ]
      })
      export default router
      

      最后呈现:
      image.png

    重定向和别名

    有些时候,你不希望前往/a访问的用户看到一个错误页面,也不希望搜索引擎链接到一堆不存在的页面上。那么可以用上redirect,这个时候任何对/a的访问都会被重定向到/b

    const router=new VueRouter({
       routes:[
          {
                path:'/a',
                redirect:'/b',
          },   
       ]
    })
    

    那么“别名”又是什么呢?

    如下面的例子。/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由其实指向 /a,就像用户访问 /a 一样。

    const router = new VueRouter({
      routes: [
        { 
            path: '/a', 
            alias: '/b' ,
            component: A, 
        }
      ]
    })
    

    命名路由

    //有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接跳转路由的时候,下面的编程式导航会有例子
    const router = new VueRouter({
      routes: [
        {
          path: '/user,
          name: 'user',//命名路由
          component: User
        }
      ]
    })
    

    命名视图

    有时候想同时 (同级) 展示多个视图,而不是嵌套展示。例如一个布局有 sidebarmain两个视图,而你不想嵌套,那么你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default

    <router-view></router-view>
    <router-view name="a"></router-view>
    <router-view name="b"></router-view>
    

    一个视图使用一个组件渲染。因此对于同个路由,多个视图就需要多个组件。注意此时要写成components

    const router = new VueRouter({
      routes: [
        {
          path: '/',
          components: {
            default: Foo,
            a: Bar,
            b: Baz
          }
        }
      ]
    })
    

    HTML5 History模式

    vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。我们可以让vue-router使用这种HTML5 history API,只需要改变路由的模式

    const router=new VueRouter({
      mode:'history',
      routes:[...]
    })
    

    当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id。不过还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 不存在的url 就会返回 404,这就不好看了。所以需要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

    动态路由

    基础应用

    动态路由的使用场景很多。比如你想匹配用户的ID作为路径的一部分,就可以用到动态路由,动态路由用 :标记:

    const router = new VueRouter({
      routes: [
        { 
            path: '/user/:id',
        	component: PageUser 
        }
      ]
    })
    

    路由参数

    在组件实例中,可以通过使用属性this.$route来获取当前的路由对象。其中 this.$route.params可以访问到动态路由参数。

    //访问:`user/1234`:
    {
        "id":'1234'
    }
    
    //如果有多个动态参数如/user/:Id/posts/:pageNumber
    //访问:/user/1234/posts/2 
    {
        "id":"1234",
        "pageNumber":"2"
    }
    

    响应路由变化

    当从 /user/foo 和 /user/bar相互切换时,原来的组件实例会被复用。意味着组件的生命周期钩子不会再被调用。如果想对路由参数的变化作出响应的话:

    • 使用 watch 监测$route 对象:

      const PageUser = {
        template: '...',
        watch: {
            $route(to, from) {
            // 对路由变化作出响应...
            }
        }
      }
      
    • 使用beforeRouteUpdate导航守卫

      const PageUser = {
        template: '...',
        beforeRouteUpdate (to, from, next) {
            // 对路由变化作出响应...
            next()
        }
      }
      

    路由传参

    在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。

    原本:

    const User = {
      template: '<p>user:{{this.$route.params.id}}</p>',
    }
    
    const router = new VueRouter({
      routes: [
        { 
            path: '/user/:id',
        	component: User 
        }
      ]
    })
    

    现在:

    const User = {
      props:['id']
      template: '<p>user:{{id}}</p>',
    }
    
    //在路由中指定props为true
    const router = new VueRouter({
      routes: [
        { 
            path: '/user/:id',
        	component: User,
            props:true
        },
          
    	//对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
        {
          path: '/user/:id',
          components: { default: User, sidebar: Sidebar },
          props: { default: true, sidebar: false }
        }
      ]
    })
    

    导航

    锚点导航

    <!--一个动态跳转路由的例子-->
    <li v-for="(item,index) in phoneList" :key="index">
          <a target="_blank" :href="'/#/product/'+item.id"></a>
    </li>
    

    链接导航

    在起步中已经用到过:<router-link>

    • 通过传入 to 属性指定链接

    • 默认会被渲染成一个 <a> 标签

    • 通过tag属性改变默认标签

      <router-link to="/foo" tag="li">Go to Foo</router-link>
      
    • 优化:可以在<router-link>里面加上锚点标签

      <router-link to="/foo"><a>Go to Foo</a></router-link>
      //这样就可以使用原生浏览器行为
      
    • 原生事件

      <router-link to="/foo" @click.native="handleclick">Go to Foo</router-link>
      

    编程式导航

    我们还可以借助 router 的实例方法实现路由跳转:

    • router.push()

      router.push({ path: 'home' })// ===> /home
      const userId = '123'
      router.push({ path: `/user/${userId}` }) // ===> /user/123
      
      //当路由有名字时
      router.push({ name: 'user'}) // ===> /user
      

      这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

    • router.replace()

      不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。

    • router.go(n)

      //类似 window.history.go(n)
      // 在浏览器记录中前进一步,等同于 history.forward()
      router.go(1)
      // 后退一步记录,等同于 history.back()
      router.go(-1)
      // 前进 3 步记录
      router.go(3)
      

    导航守卫

    导航守卫主要用来通过跳转或取消的方式来控制导航操作

    全局前置守卫

    • router.beforeEach()

    假设你想要限制未登录的用户访问你应用的某些部分,同时有一个userAuthenticated()方法用于当用户登录时返回true。这个时候就可以用到导航守卫

    该守卫有3个参数:tofromnext。其中from和to分别表示导航从哪里来和到哪里去,next则是一个回调,在里面你可以让vue-router去处理导航、取消导航、重定向到其他地方或者注册一个错误。

    const router = new VueRouter({ ... })
    router.beforeEach((to,from,next)=>{
    	if(to.path.startsWidth('/account')&&!userAuthenticated()) next('/login');
    	else next()
    })
    //解析:如果被导向的路由的路径以/account开头,而用户还未登录,则该用户会被重定向到/login;
    //否则,就调用next(),用户就能看到他们所请求的account页面
    

    全局后置钩子

    • router.afterEach()

    这个方法运行在导航之后。只被传入两个参数,to和from,因此不会影响导航

    const router = new VueRouter({
        routes: [
            {
                path: '/blog',
                component:Blog,
                meta:{
                    title:'welcome'
                }
            }
        ]
    })
    
    router.afterEach((to)=>{
    	document.title=to.meta.title
    })
    

    路由独享守卫

    • beforeEnter
    const router = new VueRouter({
        routes: [
            {
                path: '/blog',
                component:Blog,
                beforeEnter(to,from,next){
                    //...
                }
            }
        ]
    })
    

    组件内部守卫

    你可以在路由组件内直接定义以下路由导航守卫:

    • beforeRouteEnter等效于(beforeEach)
    • beforeRouteUpdate
    • beforeRouteLeave
    const Foo = {
      template: `...`,
      beforeRouteEnter (to, from, next) {
        // 在渲染该组件的对应路由被 confirm 前调用
        // 组件实例还没被创建,不能获取组件实例 `this`
         next(vm=>{..})//可用过vm访问组件实例
      },
      beforeRouteUpdate (to, from, next) {
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
        // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
        // 可以访问组件实例 `this`
      },
      beforeRouteLeave (to, from, next) {
        // 导航离开该组件的对应路由时调用
        // 可以访问组件实例 `this`
        //这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。
        const answer = window.confirm('Do you really want to leave? ')
          if (answer) {
            next()
          } else {
            next(false)
          }
      }
    }
    

    完整的导航解析流程

    1. 导航被触发。
    2. 在失活的组件里调用 beforeRouteLeave 守卫。
    3. 调用全局的 beforeEach 守卫。
    4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
    5. 在路由配置里调用 beforeEnter
    6. 解析异步路由组件。
    7. 在被激活的组件里调用 beforeRouteEnter
    8. 调用全局的 beforeResolve 守卫 (2.5+)。
    9. 导航被确认。
    10. 调用全局的 afterEach 钩子。
    11. 触发 DOM 更新。
    12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入

    路由元信息

    定义路由的时候可以配置 meta 字段。

    如果你的网站拥有大量路由,那么一个个检查会很麻烦。这个时候路由元信息(route meta fields)就发挥作用了。现在你只需在需要检查的路由上添加一个meta,里面写一个requiresAuth:true,这时守卫就能在那里获取它了。

    const router = new VueRouter({
        routes: [
            {
                path: '/account',
                component:Account,
                meta:{
                    requiresAuth:true
                }
            }
        ]
    })
    
    router.beforeEach((to,from,next)=>{
        if(to.meta.requiresAuth&&!userAuthenticated()){
            next('/login');
        }else{
            next()
        }
    })
    

    当使用嵌套路由时,to.meta指向的是子路由的元信息,而非其父路由。这个时候可以通过遍历to.matched,它会包含父路由的元信息:

    router.beforeEach((to,from,next)=>{
        const requiresAuth=to.matched.some((record)=>{
            return record.meta.requiresAuth
        })
        if(requiresAuth&&!userAuthenticated()){
            next('/login');
        }else{
            next()
        }
    })
    

    404页面

    路由顺序:vue-router在内部通过遍历路由数组的方式来挑选被显示的路由,并选取其中匹配到当前URL的第一个。这意味着安排好路由的顺序很重要。

    现在,可以利用vue-router会按顺序搜索路由直到与通配符(*)匹配的特点,来渲染一个显示错误页面:

    const router = new VueRouter({
        routes: [
            //...你的其他路由
            {
                path: '*',
                component:NotFound,//其他路由都匹配不到时,就会显示NotFound组件
            }
        ]
    })
    

    在使用嵌套路由时,如果没有匹配到子路由,则路由器会继续往下对其父路由之外的路由列表进行搜寻。如果想让子路由的错误页面也能在父组件中显示,则需要在子路由数组中添加该通配符路由:

    const router = new VueRouter({
        routes: [
            {
                path:'settings',
                component:Settings,
                children:[
                    {
                        path:'address',
                        component:Address,
                    },
                    {
                        path: '*',
                        component:NotFound,//在子路由中添加
                    }
                ]
            }
            {
                path: '*',
                component:NotFound,
            }
        ]
    })
    
  • 相关阅读:
    IntelliJ IDEA ESLint autofix/prettier
    常见电脑屏幕分辨率
    在Vue中使用echarts的两种方式
    升级npm和vue-cli
    挖坑指南:module namespace not found in mapGetters()
    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式
    如何在Vue项目中调试单个组件
    使用jquery的load方法只加载body之间的内容
    固化分组
    占有优先量词
  • 原文地址:https://www.cnblogs.com/sanhuamao/p/13596671.html
Copyright © 2011-2022 走看看