VueRouter

115 阅读1分钟

1. Hash和History的区别

  • 表现形式的不同:Hash带#号
  • 原理的区别
    • 1.Hash模式是基于锚点,以及onhashchange事件。通过锚点的值,作为路由地址,当地址发生变化后,触发onhashchange事件。根据路径决定页面上实现的内容
    • 2.history模式是基于HTML5中的 History API
      • history.pushState() IE10以后才支持
      • History.replaceState()

2.History模式的使用

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服务器配置,修改nginx.conf配置文件
location / {
	root	html;
  index	index.html	index.htm;
  //配置这个
  try_files	$uri $uri/	/index.hmtl 
}

3.简单模仿实现history模式的VueRouter

  • Vue Router的使用
// 注册插件
Vue.use(VueRouter)
//创建路由对象
const router = new VueRouter({
    routes:[
	{name: 'home', path: '/', component: homeCpn}
    ]
})
//创建Vue实例,注册VueRouter对象
new Vue({
    router,
    render: h => h(App)
}).$mount('#app')
<tempalte>
    <div id="app">
        <div class="nav">
          <router-link to="/">home</router-link>
          <router-link to="/about">about</router-link>
        </div>
        <router-view></router-view>
    </div>
</tempalte>
  • VueRouter的模拟实现
let _Vue = null;
class VueRouter {
  static install(Vue) {
    //1 判断当前插件是否被安装
    if (VueRouter.install.installed) {
      return;
    }
    VueRouter.install.installed = true;
    //2 把Vue的构造函数记录在全局
    _Vue = Vue;
    //3 把创建Vue的实例传入的router对象注入到Vue实例
    // _Vue.prototype.$router = this.$options.router
    _Vue.mixin({
      beforeCreate() {
        if (this.$options.router) {
          _Vue.prototype.$router = this.$options.router;
        }
      }
    });
  }
  constructor(options) {
    this.options = options;
    this.routeMap = {};
    // observable 创建响应式对象 data用来存放路由地址
    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);
          this.$router.data.current = this.to;
          e.preventDefault();
        }
      }
      //运行时版本不支持template
      // template:"<a :href='to'><slot></slot></a>"
    });
    const self = this;
    Vue.component("router-view", {
      render(h) {
        // self.data.current
        const cm = self.routeMap[self.data.current];
        return h(cm);
      }
    });
  }
  initEvent() {
    //注册popstate事件,
    window.addEventListener("popstate", () => {
      this.data.current = window.location.pathname;
    });
  }
}