3.Vue-Router

vue-router

路由作用

背景:传统开发模式中,每个页面对应着唯一的url,如www.XXX.com/home对应着home页,此类多页应用在切换页面时,整个页面需要整体刷新重绘,极大影响性能。因此,SPA单页面应用模式出现,极大地提高了性能;
SPA:单页面应用,其主要的支撑技术包括:1,ajax实现了局部数据刷新;2,路由跳转不请求页面情况下实现页面的更新;

扩展

  • 什么是重绘?
    重绘:当元素外观,样式发生改变,但是不影响布局,则称为重绘(如backgorund颜色改变等),即重新将改变后的元素绘制到屏幕上,但是该操作本身不影响文档流的结构;
  • 什么是回流?
    回流:renderTree中的元素因为规模尺寸,隐藏,布局等改变,导致整个结构重新调整(比如:添加或者删除可见的DOM元素,元素位置改变,元素尺寸改变——边距、填充、边框、宽度和高度,内容改变),则称为回流,因此回流必定重绘,重绘不一定回流

详细见:13.重绘和回流详解

Vue中路由

  • 作用
    1. 监听url变化,并在变化前后执行相应的逻辑
    2. 不同的url对应着不同的组件;
    3. 提供多种路由API进行局部刷新前后的操作;
基本路由
  1. 初始化路由器实例对象,new VueRouter()
new VueRouter({
	// 路由配置项
})
  1. 配置路由列表,每个路由对应一个组件
routes: [{
    // 一般路由
    path: '/about',
    component: AboutComponent,
}, {
    // 可以设置默认跳转的页面
    path: '/',   // '/'表示根路径
    component: AboutComponent,// 默认跳转到about对应的页面
}]
  1. 注册路由器,将路由对象实例挂载到vue对象实例中;
import router from './routes'
new Vue(
    {
        router
    })
  1. 使用路由组件
//<router-link>  用于触发跳转,指定跳转的页面
<router-link to="/about">点击跳转到about页面</router-link>
//<router-view>  用于显示路由跳转过来的组件
<router-view></router-view>

详细见:官网Vue-router

  • 定义/配置/注册路由
// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)

// 1. 定义 (路由) 组件。
// 可以从其他文件 import 进来
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写) 相当于 routes: routes
})

// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
  router
}).$mount('#app')

// 现在,应用已经启动了!
  • router/route使用路由
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用 router-link 组件来导航. -->
    <!-- 通过传入 `to` 属性指定链接. -->
    <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</div>
动态路由
const User = {
  template: '<div>User</div>'
}

const router = new VueRouter({
  routes: [
    // 动态路径参数 以冒号开头
    { path: '/user/:id', component: User }
  ]
})

现在像 /user/foo 和 /user/bar 都将映射到相同的路由

嵌套路由
  • 嵌套路由就是在基本路由上可以下钻,路由对象中有children属性,可以配置下级路由;
const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
      children: [
        {
          // 当 /user/:id/profile 匹配成功,
          // UserProfile 会被渲染在 User 的 <router-view> 中
          path: 'profile',
          component: UserProfile
        },
        {
          // 当 /user/:id/posts 匹配成功
          // UserPosts 会被渲染在 User 的 <router-view> 中
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})

1.路由以 / 开头的嵌套路径会被当作根路径
2.如果子路由中path没有配置/则表示当前路径可以直接拼接在父路由上

编程式导航

// 在浏览器记录中前进一步,等同于 history.forward()
this.$router.go(1)

// 后退一步记录,等同于 history.back()
this.$router.go(-1)

// 相当于点击<router-link>,跳转至path页面
this.$router.push(path)

 // 新路由替代当前路由,回退不再显示当前路由页面
this.$router.replace(path)

 // 请求返回上一页面
this.$router.back()

路由传参

this.$route.param.id方式获取参数
  • 通过动态路由传递参数,此处的id值,通过this.$route.param.id获取;
const router = new VueRouter({
  routes: [
    // 动态路径参数 以冒号开头
    { path: '/user/:id', component: User }
  ]
})
  • 通过路由视图传参 ,同样可以通过this.$route.param.id获取;
<router-view :msg="message"><router-view>

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

props方式获取参数
const User = {
  props: ['id'],
  template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
  routes: [
    // 路由props传递布尔值
    { path: '/user/:id', component: User, props: true },

    // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
    {
      path: '/user/:id',
      components: { default: User, sidebar: Sidebar },
      props: { default: true, sidebar: false }
    }// props传递对象
	 {
      path: '/promotion/from-newsletter',
      component: Promotion,
      props: { newsletterPopup: false }
    }// props函数式传参
    {
      path: '/search',
      component: SearchUser,
      props: route => ({ query: route.query.q })
    }
  ]
})
  • props传布尔值参数,如果 props 被设置为 true,route.params 将会被设置为组件属性;
  • props可以传递对象或者通过函数式传递参数;
  • 注意当动态传参时,对于包含命名视图的路由,你必须分别为每个命名视图添加 props 选项:

命名视图

  • 一个<router-view>表示一个视图,如果想多个同级而非嵌套视图一起展示,则需要多个视图,比如CMS系统中侧边栏和内容栏部分;此时需要给不同的视图命名以作区分,不命名则默认default。
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

缓存路由组件

背景:默认情况下,路由切换后之前的路由组件对象会被内存会被释放,再次切回时会重新创建路由组件,因此先前数据会被刷新【例子,两个tab页,切换之后,先前tab对应的数据会被清除】,如果想数据可以保留;可以使用<keep-alive>组件将需要混存的视图包裹起来,即:

<keep-alive>
	<router-view></router-view>
</keep-alive>

重定向和别名

  • 重定向:就是将原本路由指定到另一个路由上;
const router = new VueRouter({
  routes: [
    // 路由路径
    { path: '/a', redirect: '/b' }// 命名路由
    { path: '/bar', redirect: { name: 'foo' }},
    // 函数返回重定向路由
    { path: '/a', redirect: to => {
      // 方法接收 目标路由 作为参数
      // return 重定向的 字符串路径/路径对象
    }}
  ]
  ]
})
  • 别名:/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。意思是,/b就是一个别名,但是本质上还是访问/a,触发二者效果一样,别名作用在于可以使用任意URL当成/a使用,而不需要考虑嵌套的路由结构;
const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})

路由懒加载

路由中映射的组件,可以异步导入,如此,可以实现代码的组件化分割,当被访问时加载对应的组件,提高效率。【注意:需要vue2.4以上,需要用到异步组件

  • 结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。
const Foo = () =>
  Promise.resolve({
    /* 组件定义对象 */
  })
  • 在 Webpack 2 中,我们可以使用动态 import语法来定义代码分块点 (split point)
import('./Foo.vue') // 返回 Promise
const Foo = () => import('./Foo.vue')


const router = new VueRouter({
  routes: [{ path: '/foo', component: Foo }]
})

路由原理

SPA中路由变化时,会更新视图但是不会请求页面;这是路由的核心原理之一;其实现方法包括:

  • hash路由,利用URL中的hash("#");
  • 利用History interface在HTML5中新增的方法;

二者对比:

  • pushState设置的新url可以是与当前url同源的任意url,而hash只可修改#后面的部分,故只可设置与当前同文档的url
  • pushState设置的新url可以与当前url一模一样,这样也会把记录添加到栈中,而hash设置的
  • 新值必须与原来不一样才会触发记录添加到栈中
  • pushState通过stateObject可以添加任意类型的数据记录中,而hash只可添加短字符串
  • pushState可额外设置title属性供后续使用

详细参考:
路由原理1
路由原理2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值