Vue框架(二)-Vue-Router原理篇

66 阅读1分钟

Vue-Router原理篇

设计思路

  • 构建单页应用
    • hash模式: 基于location对象
    • history模式: 基于history对象
  • 显示对应的组件
    • 路由和组件的映射关系
    • router-view告诉我们在哪里渲染组件
  • 路由跳转
    • router-link

实现思路

  • 定义一个插件,createRouter返回的对象
  • 实现两个组件router-view和router-link
  • 实现创建路由实例的createRouter
  • 实现创建执行模式的createWebHashHistory()

代码实现

// router.js
export function createRouter(options) {
    const router = {
        options,
        current: ref(window.location.hash.slice(1) || '/'),
        install(app) {
            const this = router

            // 注册全局组件
            app.component('RouterLink', RouterLink)
            app.component('RouterView', RouterView)

            // 注册$router
            app.config.globalProperties = this
        }
    }
    
    window.addeventlistener('hashchange', () => {
        // 保存到current,触发RouterView更新
        router.current.value = window.location.hash.slice(1)
    })

    return router
}
// RouterLink.js
export default defineComponent({
    props: {
        to: {
            type: String,
            required: true
        }
    },
    setup(props, { slots }) {
        const to = unref(props.to)
        return () => h('a', {
            href: '#' + to
        }, slots.default())
    }
})
// RouterView.js
export default defineComponent({
    setup(props, { slots }) {
        return () => {
            // 获取组件实例
            const { proxy: { $router } } = getCurrentInstance()
            
            let component
            const route = $router.options.routes.find(
                (route) => route.path === unref($router.current)
            )
            
            // 找到匹配的组件
            if(route) {
                component = route.component
                return h(component, "router-view")
            }
            
            console.warn("no match component")
            return h("div", "")
        }
    }
})