(一)Vue-路由

路由使用

  1. 静态路由
// 路由规则
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')
  }
]
  1. 动态路由
    通过当前路由规则获取 或者 通过开启 props 获取, 建议通过props来解耦
// 路由规则
const routes = [
  {
    path: '/',
    name: 'Index',
    component: Index
  },
  {
    path: '/detail/:id',
    name: 'Detail',
    // 开启 props,会把 URL 中的参数传递给组件
    // 在组件中通过 props 来接收 URL 参数
    //  
    props: true,
    // 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: "detail" */ '../views/Detail.vue')
  }
]

// 页面





3.嵌套路由

const routes = [
  {
    name: 'login',
    path: '/login',
    component: Login
  },
  // 嵌套路由
  {
    path: '/',
    component: Layout,
    children: [
      {
        name: 'index',
        // 外面的path 和 这里path拼接起来
        // 可以加/,也可以不加
        path: '',
        // 外面的Layout 和 这里Index拼接起来
        component: Index
      },
      {
        name: 'detail',
        path: 'detail/:id',
        props: true,
        component: () => import('@/views/Detail.vue')
      }
    ]
  }
]
  1. 路由跳转replace、push、go


  1. hash VS History
  • hash 模式
    Vue Router 默认使用的是 hash 模式,使用 hash 来模拟一个完整的 URL,通过onhashchange 监听路径的变化。 有一个#号。
  • History 模式
    基于 History API ,没有#
// 改变地址栏,同时记录,但是不会跳转指定路径, IE10后支持
// 可以实现客户端路由
history.pushState() 
// 会发起服务端请求
history.replaceState() 
history.go()

需要开启 History 模式

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

History 需要服务器的支持
单页应用中,服务端不存在 http://www.testurl.com/login 这样的地址会返回找不到该页面
在服务端应该除了静态资源外都返回单页应用的 index.html

服务端开启history,刷新的时候。 其实是先给前端返回index页面,然后再跳转到对应login页面

路由基础实现

let _Vue = null
class JerryVueRouter {
    // 接收一个参数,也就是Vue类
    // Vue.use(你的插件)自动调用
    static install(Vue){
        console.log('Srs==>', Vue)
        //1 判断当前插件是否被安装
        if(JerryVueRouter.install.installed){
            return;
        }
        JerryVueRouter.install.installed = true
        //2 把Vue的构造函数记录在全局
        _Vue = Vue
        //3 把创建Vue的实例传入的router对象注入到Vue实例
        // _Vue.prototype.$router = this.$options.router
        _Vue.mixin({
            beforeCreate(){
                // 实例化为Vue 类时,会将 VueRouter 的实例传入,这个变量放在this.$options.router中
                // 判断是Vue实例才设置
                if(this.$options.router){
                    _Vue.prototype.$router = this.$options.router
                    
                }
            }
        })
    }
    constructor(options){
        // 包含路由规则
        this.options = options
        // 路由规则对下
        this.routeMap = {}
        // observable
        this.data = _Vue.observable({
            current:"/"
        })
        this.init()
    }
    init(){
        this.createRouteMap()
        this.initComponent(_Vue)
        this.initEvent()
    }
    createRouteMap(){
        //遍历所有的路由规则 吧路由规则解析成键值对的形式存储到routeMap中
        this.options.routes.forEach(route => {
            this.routeMap[route.path] = route.component
        });
    }
    initComponent(Vue){
        Vue.component("router-link",{
            props:{
                to:String
            },
            render(h){
                return h("a",{
                    attrs:{
                        href: this.to
                    },
                    on:{
                        click:this.clickhander
                    }
                }, [this.$slots.default])
            },
            methods:{
                // 重置点击事件, 默认会请求后台数据
                clickhander(e){
                    history.pushState({}, "", this.to)
                    // 响应事件,会重复view刷新
                    this.$router.data.current = this.to
                    e.preventDefault()
                }
            },
            // slot是插槽
            // 使用template需要完整版编译
            // 需要配置vue.config.js里面的runtimeCompiler
                // module.exports = {
                //     // 完整版view,默认是false。完整版带编译器,多10K
                //     runtimeCompiler: true
                // } 
            // template: "<>"
        })
        const self = this
        Vue.component("router-view",{
            render(h){
                // self.data.current
                const cm = self.routeMap[self.data.current]
                return h(cm)
            }
        })
        
    }
    initEvent(){
        // 处理浏览器上返回 前进按钮
        window.addEventListener("popstate",()=>{
            this.data.current = window.location.pathname
        })
    }
}

export default JerryVueRouter

你可能感兴趣的:((一)Vue-路由)