前端学习-Vue Router

166 阅读2分钟

Vue Router是 Vue.js 官方的路由管理器,让构建单页面应用变得易如反掌。

基本使用

  • Vue Router 提供了用于进行路由设置的组件 <router-link><router-view>
  • 定义路由中需要的组件
  • 进行路由规则设置。
  • 创建 Vue Router 实例,通过 routes 属性配置路由。
  • 创建 Vue 实例,通过 router 属性注入路由。
<div id="app">
    <!-- 设置用于进行路由操作的组件 -->
    <router-link to="/">首页</router-link>
    <router-link to="/user">用户</router-link>
    <router-link to="/category">分类</router-link>

    <!-- 根据路由规则显示对应的视图 -->
    <router-view></router-view>
</div>

<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
    //设定组件
    var Index = {
      template: `<div>首页功能</div>`
    };
    var User = {
      template: `<div>用户功能</div>`
    };
    var Category = {
      template: `<div>分类功能</div>`
    };

    // 定义路由规则
    var routes = [
      { path: '/', component: Index },
      { path: '/user', component: User },
      { path: '/category', component: Category }
    ];

    // 创建 Vue Router 实例
    var router = new VueRouter({
      routes : routes
    });

    // 创建 Vue 实例,注入 router
    var vm = new Vue({
      el: '#app',
      router: router
    });

    
</script>

命名视图

  • 如果导航后,希望同时在同级展示多个视图(组件),这时就需要进行命名视图。
  • 路由中通过 components 属性进行设置不同视图的对应组件。
<div id="app">
    <router-link to="/">首页</router-link>
    <router-link to="/user">用户</router-link>

    <router-view name="sidebar"></router-view>
    <!-- 没有设置 name 的 router-view 默认 name 为 default-->
    <router-view></router-view>
</div>

<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
    var SideBar1 = {
      template: `<div>侧边栏1功能</div>`
    };

    var SideBar2 = {
      template: `<div>侧边栏2功能</div>`
    };

    var Index = {
      template: `<div>首页功能</div>`
    };

    var User = {
      template: `<div>用户功能</div>`
    };

    // 定义路由规则
    var routes = [
      {
        path: '/',
        components: {
          // router-view 的 name : 组件配置对象
          default: Index,
          sidebar: SideBar1
        }
      },
      {
        path: '/user',
        components: {
          default: User,
          sidebar: SideBar2
        }
      }
    ];

    // 创建 Vue Router 实例
    var router = new VueRouter({
      routes
    });

    // 创建 Vue 实例
    new Vue({
      el: '#app',
      router
    });
</script>

动态路由

  • 当我们需要将某一类 URL 都映射到同一个组件,就需要使用动态路由。
  • 定义路由规则时,将路径中的某个部分使用 : 进行标记,即可设置为动态路由。
  • 设置为动态路由后,动态部分为任意内容均跳转到同一组件。
  • : 部分对应的信息称为路径参数,存储在 vm.$route.params 中。
<div id="app">
    <router-link to="/user/1">用户1</router-link>
    <router-link to="/user/2">用户2</router-link>
    <router-link to="/user/3">用户3</router-link>

    <router-view></router-view>
</div>

<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
    // 设置组件 
    var User = {
      template: `<div>这是用户 {{ $route.params.id }} 的功能</div>`
    };

    // 设置路由规则
    var routes = [
      {
        path: '/user/:id', component: User
      }
    ];

    var router = new VueRouter({ routes });
    var vm = new Vue({
      el: '#app',
      router
    });
</script>

侦听路由参数

如果要响应路由的参数变化,可以通过 watch 监听 $route。

// 设置组件 
var User = {
  template: `
    <div>
      这是用户 {{ $route.params.id }} 的功能
      <input type="text">
    </div>`,
  watch: {
    $route (route) {
      console.log(route.params.id)
    }
  }
};

路由传参处理

这里通过路由的 props 设置数据,并通过组件 props 接收。

// 组件的配置对象
var Category = {
  props: ['id'],
  template: `<div>这是分类 {{ id }} 功能</div>`
};

// 设置路由规则
var routes = [
  {
    path: '/category/:id',
    component: Category,
    props: true
  }
];

其他设置方式

包含多个命名视图时,需要将路由的 props 设置为对象。
如果希望设置静态数据,可将 props 中的某个组件对应的选项设置为对象,内部属性会绑定给组件的 props。

<router-view></router-view>
<router-view name="sidebar"></router-view>
<router-view name="sidebar2"></router-view>


// 组件的配置对象
var Category = {
  props: ['id'],
  template: `<div>这是分类 {{ id }} 功能</div>`
};

var SideBar = {
  template: `<div>侧边栏功能</div>`
};

var SideBar2 = {
  props: ['a', 'b'],
  template: `
  <div>
    侧边栏2功能: {{ a }} {{ b }}
  </div>`
};

// 设置路由规则
var routes = [
  {
    path: '/category/:id',
    components: {
      default: Category,
      sidebar: SideBar,
      sidebar2: SideBar2
    },
    props: {
      //需要传递数据
      default: true,
      //不需要传递数据
      sidebar: false,
      //传递静态数据
      sidebar2: {
        a: '状态1',
        b: '状态2'
      }
    }
  }
];

嵌套路由

  • 实际场景中,路由通常由多层嵌套的组件组合而成,这时需要使用嵌套路由配置。
  • 使用 children 来进行嵌套路由中的子路由设置。
<div id="app">
    <router-link to="/user">用户功能</router-link>
    <router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
    //组件
    var User = {
      template: `
        <div>
          <h3>这是 User 组件的功能</h3>
          <router-link to="/user/hobby">爱好功能</router-link>
          <router-link to="/user/info">用户信息</router-link>
          <router-view></router-view>
        </div>
      `
    };

    var UserHobby = {
      template: `<div> UserHobby 组件</div>`
    };

    var UserInfo = {
      template: `
        <div> 
          UserInfo 组件
          <router-link to="/user/info/school">学校信息</router-link>
          <router-view></router-view>
        </div>`
    };

    var UserInfoSchool = {
      template: `<div> UserInfoSchool 组件</div>`
    };

    //路由规则配置
    var routes = [
      {
        path: '/user',
        component: User,
        children: [
          {
            path: 'hobby',
            component: UserHobby
          },
          {
            path: 'info',
            component: UserInfo,
            children: [
              {
                path: 'school',
                component: UserInfoSchool
              },
            ]
          }
        ]
      }
    ];

    //创建实例
    var router =  new VueRouter({ routes });
    var vm = new Vue({
      el: '#app',
      router
    });
</script>

编程式导航

编程式导航指的是通过方法设置导航。

  • router.push() 用来导航到一个新 URL。
vm.$router.push('/user');
vm.$router.push({path: '/user'});
vm.$router.push({path: '/user/123'});

  • <router-link> 的 to 属性使用绑定方式时也可属性对象结构。
<div id="app">
    <!-- 声明式导航 -->
    <!-- <router-link to="/user/200">用户200</router-link> -->
    <!-- 编程式导航 -->
    <router-link :to="{ path: '/user/700' }">用户700</router-link>

    <router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
    var User = {
      template: `<div> 这是用户 {{ $route.params.id }} </div>`
    };

    var routes = [
      {
        path: '/user/:id',
        component: User
      }
    ];

    var router = new VueRouter({ routes });
    var vm = new Vue({
      el: '#app',
      router
    });
</script>

命名路由

  • 设置路由时添加 name 属性。
  • 在 push() 中通过 name 导航到对应路由,参数通过 params 设置。
  • 也可以在 <router-link> 中使用。
<div id="app">
    <router-link :to="{ name: 'school', params: { id: 10 } }">学校10</router-link>

    <router-view></router-view>
</div>

<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
    var School = {
      template: `<div>School 组件的功能: {{ $route.params }}</div>`
    };

    var routes = [
      {
        path: '/user/:id/info/school',
        name: 'school',
        component: School
      }
    ];

    var router = new VueRouter({ routes });
    var vm = new Vue({
      el: '#app',
      router
    });
    
</script>
vm.$router.push({ name: 'school', params: { id: 10 } });

重定向

当用户访问某个url的时候会跳转到另一个指定的url

<div id="app">
    <router-link to="/">首页</router-link>
    <router-link to="/category/2">分类2</router-link>
    <router-link to="/category"> /category </router-link>

    <router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
    var Index = {
      template: `<div>首页功能</div>`
    };

    var Category = {
      template: `<div>分类 {{ $route.params.id }} 功能</div>`
    };

    var router = new VueRouter({
      routes: [
        {
          path: '/',
          component: Index
        },
        {
          path: '/category/:id',
          component: Category
        },
        {
          path: '/category',
          //重定向到'/'
          redirect: '/'
        }
      ]
    });

    var vm = new Vue({
      el: '#app',
      router
    });
</script>

别名

用于简化显示的url内容

<div id="app">
    <router-link :to="{ name: 'school', params: { id: 10, date: '0612'} }">学校信息</router-link>
    <router-link to="/20/1234">学校信息2</router-link>
    <router-view></router-view>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
    // 组件
    var School = {
      template: `
        <div>School 组件</div>
      `
    };

    // 路由规则
    var router = new VueRouter({
      routes: [
        {
          path: '/user/:id/info/school/:date',
          name: 'school',
          component: School,
          //等价于path
          alias: '/:id/:date'
        }
      ]
    });

    var vm = new Vue({
      el: '#app',
      router
    });
</script>

导航守卫

用于决定是否可以访问某个地址

<div id="app">
    <router-link to="/">首页</router-link>
    <router-link to="/user">用户</router-link>
    <router-link to="/category">分类</router-link>
    <router-view></router-view>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
    var Index = {
      template: `<div>这是首页功能</div>`
    };
    var User = {
      template: `<div>这是用户功能</div>`
    };
    var Category = {
      template: `<div>这是分类功能</div>`
    };

    var router = new VueRouter({
      routes: [
        { path: '/', component: Index },
        { path: '/user', component: User },
        { path: '/category', component: Category },
      ]
    });

    // 设置导航守卫
    router.beforeEach(function (to, from, next) {
      
      //当需要访问/user时会跳转到/category
      if (to.path === '/user') {
        next('/category');
      } else {
        next();
      }
    });

    var vm = new Vue({
      el: '#app',
      router
    })
  </script>

history模式

需要通过 Vue Router 实例的 mode 选项来设置,这样 URL 会更加美观,但同样需要后端支持避免问题。

<div id="app">
    <router-link to="/">首页</router-link>
    <router-link to="/user">用户</router-link>
    <router-link to="/category">分类</router-link>
    <router-view></router-view>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
    var Index = {
      template: `<div>这是首页功能</div>`
    };
    var User = {
      template: `<div>这是用户功能</div>`
    };
    var Category = {
      template: `<div>这是分类功能</div>`
    };

    var router = new VueRouter({
      mode: 'history',
      routes: [
        { path: '/', component: Index },
        { path: '/user', component: User },
        { path: '/category', component: Category },
      ]
    });

    var vm = new Vue({
      el: '#app',
      router
    })
</script>