VUE原理深度解析/Vue Router实现原理过程

本文深入探讨Vue Router的实现原理,包括嵌套路由、编程式导航、History与Hash模式的区别及使用。重点讲解History模式,强调其需要后台支持,详细解释了如何在nginx中配置以支持History模式。同时,提到了Vue Router的安装问题及其解决方法,通过initEvent方法实现浏览器的前进和后退功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

{
    path:'/detail/:id',
    name:'Detail',
    // 非动态路由
    //compontent:'details',
    // 开启prop传参功能
    props:true,
    //实现懒加载 用户点击才进行加载
    compontent = ()=>{'../views/Details.vue'}
}

// 获取方式

  • 第一种 $route.params.id
  • 第二种通过props进行接收
export default{
    name:'Detail',
    props:['id']; 
}

嵌套路由

  • 使用场景
    // layout.vue
Header
router view
footer

// index.vue 首页
// details.vue 详情页

  • 文件结构
src
    components 文件夹
        layout.vue
    views 文件夹
        Details.vue
        Index.vue
        Login.vue
  • 路由配置
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/Details.vue')
        }
    ]
}
]

编程式导航

  • 路由跳转
1)、this.$router.push('/');
2)、this.$router.push({name:'Home'})
3)、this.$router.replace('/login') //和push的区别不记录历史记录
4)、this.$router.push({name:'Detail',params:{id:1}})
5)、this.$router.go(-2) //退回2步

History 模式

  • 通过history.pushState()方法改变地址栏
  • 监听popstate事件
  • 根据当前路由地址找到对应组建重新渲染

Hash模式

  • URL中#后面的内容作为路径地址
  • 监听hashchange事件
  • 根据当前路由地址找到对应的组建进行重新渲染

Hash和history的区别

不管那种模式 都是客户端的模式

  • Hash模式 # 基于锚点以及onhashchange事件
  • History 需要服务端配合
    • history模式基于HTML5中的historyAPI
    • history.oushState() IE10以后才支持 路径放生变化像服务器发生请求
    • history.replaceState() 不会发生请求 只会在路由发生变化

history的使用

//router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from './views/Home.vue'
Vue.use(VueRouter)
const routes = [
    {
        path:'/',
        name:'Home',
        component:Home
    },
    {
        path:'/about',
        name:'About',
        component:()=>import('./view/about.vue')
    },
    {
        path:'*',
        name:'404',
        component:()=>import('./view/404.vue')
    }
]

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

export default router

//App.vue
<template>
    <div id="app">
        <div id="nav">
            <router-link to="/">Home</router-link>
            <router-link to="/about">About</rout-link>
            <rout-link to="/video">Video</router-link>
        </div>
        <router-view/>
    </div>
</template>

history需要后台支持

  • node中需要配置
const app = express();
app.use(history())

*nginx服务配置

  • 从官网下载nginx的压缩包
  • 把压缩包解压到c盘目录,
  • 打开命令行,切换到英文目录下进行启动
  • 修改配置文件
server{
    listen:80; //监听端口号
    server_name localhost;  //服务器的域名
    location / {
        root html;
        index index.html index.htm  //回车所访问的文件
        try_files $uri $uri/ /index.html;  //$uri 当前请求的路径 $uri/ 请求文件夹下的默认文件
    }
}
//启动
start nginx.exe
开启loglhost可查看是否成功启动 默认80端口号
//重启
nginx -s reload
//停止
nginx -s stop
解说nginx文件夹
  • html存放静态文件
  • conf中可以配置nginx.conf进行配置

Vue Router实现原理过程

  • 创建VueRouter的类
VueRouter
    //属性
    options  //参数
    data     //记录当前地址 响应式对象 vue.observer
    routeMap  //将路由规则记录在里面
    // 方法
    Constructor(Options):VueRouter //初始化属性
    _install(Vue):void //静态方法 构建插件机制
    init():void   //调用下面三个方法
    initEvent():void  //监听浏览器地址发生变化
    createRouteMap():void  // 初始化routeMap转化键值对
    initComponents(Vue):void //创建routevue routlink组建
  • 实现VueRouter-install
export defaule class VueRouter{
var _Vue;
    static install(Vue){
        //1、判断当前插件是否已经被安装
        if(VueRouter.install.installed){
            return
        }
        VueRouter.install.installed=true
        //2、把Vue构造器记录到全局变量
        _Vue=Vue
        //3、把创建Vue实例时候传入的router对象注入到Vue实例上
        _Vue.mixin({
            beforecreat(){
               if(this.$option.router){ this.prototype.$router = this.$option.router;
               //调用写好的init方法
               this.$option.router.init();
            }
        })
    }
    constructor(options){
        this.options=options;
        this.routeMap={};
        this.data=_Vue.observable({
            current:"/"
        })
    }
    
    createRouteMap(){
        this.options.routes.filter(route=>{
            this.routeMap[route.path] = route.comonpent
        })
    }
    init(_Vue){
        this.createRouteMap();
        this.initComponent(_Vue);
        this.initEvent(); //此内容在下面
    }
    
    //创建initComponent 创建router-link组建
    initComponent(Vue){
      
        Vue.component('router-link',{
            props:{
                to:String
            },
            template:'<a :href="to"><slot></slot></a>'
        })
        //实现 router-view 根据路由地址渲染对应的路由组建不进行请求后台只是前台进行路由切换 不刷新页面
         let self = this;
        Vue.compontent('router-view',{
            render(h){
                //当前的路由地址
                let component = self.routeMap[self.data.current]
                return component;
            }
        })
    }
}
  • 运行报错 原因是cli没有预编译解析以下是解决办法
  • 在根目录下创建vue.config.js进行配置
module.exports={
    runtimeCompiler:true
}
  • 使用render函数 如果你有疑问,为什么平时写单页面没有报错不需要写render,因为打包的过程中把component解析成render函数 预编译。
将router-link中的template直接用render来进行书写
render(h){
    // h是虚拟dom
    // a选择器/是标签名称,第二个参数 一些属性,attrs:{href:this.to}  attrs代表dom的属性 第三个参数接受数组形式代表子元素插槽没有名称就是default 调用方法 this.$slots.default
    return h('a',{
        attrs:{
            href:this.to
        },
        on:{
            click:this.clickHandler
        }
        }
        ,[this.$slots.default]
    })
},
methods:{
    clickHandler(e){
        //data,title,超链接跳转的地址
        history.pushState({},'',this.to)
        this.$router.data.current = this.to
        e.preventDefault()
    }
}
  • 实现initEvent方法实现浏览器前进和后退的功能 触发popState当历史发生变化
initEvent(){
    window.addEventListener('popstate',()=>{
        this.data.current = window.localhost.pathname
    })
}

别忘接在init中调用偶!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值