8.1.2 Vue Router原理实现

本文为拉勾网大前端高薪训练营第一期笔记


8.1.2 Vue Router原理实现

Vue router

初始化vue的时候选择router,会自动生成router相关代码

Vue.use(VueRouter)

use传参如果是函数,会调用函数注册组件,如果是对象的话会调用对象的install方法

import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from '../views/Index.vue'
// 1. 注册路由插件
Vue.use(VueRouter)

// 路由规则
const routes = [
  {
    path: '/',
    name: 'Index',
    component: Index
  },
  {
    path: '/blog',
    name: 'Blog',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "blog" */ '../views/Blog.vue')
  },
  {
    path: '/photo',
    name: 'Photo',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "photo" */ '../views/Photo.vue')
  }
]
// 2. 创建 router 对象
const router = new VueRouter({
  routes
})

export default router

//template部分代码
<template>
  <div id="app">
    <div>
      <img src="@/assets/logo.png" alt="">
    </div>
    <div id="nav">
      <!-- 5. 创建链接 -->
      <router-link to="/">Index</router-link> |
      <router-link to="/blog">Blog</router-link> |
      <router-link to="/photo">Photo</router-link>
    </div>
    <!-- 4. 创建路由组件的占位,匹配到的会在这里显示 --> 
    <router-view/>
  </div>
</template>

//main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

new Vue({
  // 3. 注册 router 对象,这里注册的话Vue实例会增加$route和$router属性
	//$route包括路由参数 $router是VueRouter实例提供很多方法,常用push replace go
	//插件里经常拿不到$route,但是能拿到$router,currentRoute可以获取当前路由规则
  router,
  render: h => h(App)
}).$mount('#app')

动态路由

路由配置

const routes = [
  {
    path: '/',
    name: 'Index',
    component: Index
  },
  {
    path: '/blog',
    name: 'Blog',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "blog" */ '../views/Blog.vue')
  },
  {
    path: '/photo',
    name: 'Photo',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "photo" */ '../views/Photo.vue')
  }
]

两种方式获得id,推荐第二个,前面的配置开启props:true

<template>
  <div>
    <!-- 方式1: 通过当前路由规则,获取数据 -->
    通过当前路由规则获取:{{ $route.params.id }}

    <br>
    <!-- 方式2:路由规则中开启 props 传参 -->
    通过开启 props 获取:{{ id }}
  </div>
</template>

嵌套路由

//layout.vue
<router-view></router-view>

//router/index.js
const routes = [
  {
    name: 'login',
    path: '/login',
    component: Login
  },
  // 嵌套路由
  {
    path: '/',
    component: Layout,
    children: [
      {
        name: 'index',
        path: '',
        component: Index
      },
      {
        name: 'detail',
        path: 'detail/:id',
        props: true,
        component: () => import('@/views/Detail.vue')
      }
    ]
  }
]

编程式导航

<template>
  <div class="home">
    <div id="nav">
      <router-link to="/">Index</router-link>
    </div>
    <button @click="replace"> replace </button>

    <button @click="goDetail"> Detail </button>
  </div>
</template>

<script>
export default {
  name: 'Index',
  methods: {
    replace () {
      this.$router.replace('/login')
    },
    goDetail () {
      this.$router.push({ name: 'Detail', params: { id: 1 } })
//可以通过name来跳转
    }
  }
}
</script>

hash模式和history模式区别

  • Hash模式是基于锚点,以及onhashchange事件

  • History模式是基于HTML5中的History API

    • history.pushState() IE10以后才支持
    • history.replaceState()

    history模式如果后端不支持,会出现刷新页面找不到页面的express提醒

    后端express支持的写法

    const path = require('path')
    // 导入处理 history 模式的模块
    const history = require('connect-history-api-fallback')
    // 导入 express
    const express = require('express')
    
    const app = express()
    // 注册处理 history 模式的中间件
    app.use(history())
    // 处理静态资源的中间件,网站根目录 ../web
    app.use(express.static(path.join(__dirname, '../web')))
    
    // 开启服务器,端口是 3000
    app.listen(3000, () => {
      console.log('服务器开启,端口:3000')
    })
    

    静态文件后端nginx支持的方法

    location / {
    	root html;
    	index index.html index.htm;
    	try_files $uri $uri/ /index.html;
    }
    

Vue带编译器版本

会大10K左右,支持template,会把template编译成render函数

//vue.config.js
module.exports = {
	runtimeCompiler: true
}

如果不用带编译版本的

render(h){
    return h("a",{
        attrs:{
            href:this.to
        },
        on:{
            click:this.clickhander
        }
    },[this.$slots.default])
},
methods:{
    clickhander(e){
        history.pushState({},"",this.to)
        this.$router.data.current=this.to
        e.preventDefault()
    }
}

//用带编译器版本的写法 template:"<a :href='to'><slot></slot><>"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值