Skip to content

Latest commit

 

History

History
171 lines (160 loc) · 4.22 KB

自定义实现简单路由.md

File metadata and controls

171 lines (160 loc) · 4.22 KB
  • hash路由
<body>
  <ul>
    <li><a href="#/">pink</a></li>
    <li><a href="#/yellowgreen">yellowgreen</a></li>
    <li><a href="#/indianred">indianred</a></li>
  </ul>
  <button class="btn1">back</button>
  <button class="btn2">forward</button>
</body>
class Routers {
  constructor() {
    // 储存hash与callback键值对
    this.routes = {};
    // 当前hash
    this.currentUrl = '';
    // 记录出现过的hash
    this.history = [];
    // 作为指针,默认指向this.history的末尾,根据后退前进指向history中不同的hash
    this.currentIndex = this.history.length - 1;
    this.refresh = this.refresh.bind(this);
    this.back = this.back.bind(this);
    this.forward = this.forward.bind(this);
    // 默认不是后退操作
    this.isBack = false;
    // 默认不是前进操作
    this.isForward = false;
    // IE9+
    window.addEventListener('load', this.refresh, false);
    // IE8+,浏览器导航的前进和后退按钮可触发此事件
    window.addEventListener('hashchange', this.refresh, false);
  }
  route(path, callback) {
    this.routes[path] = callback || function() {};
  }
  refresh() {
    this.currentUrl = location.hash.slice(1) || '/';
    console.log(this.currentUrl);
    if (!this.isBack && !this.isForward) {
      this.history.push(this.currentUrl)
      this.currentIndex++
    } else {
      this.isBack = false;
      this.isForward = false;
    }
    this.routes[this.currentUrl]();
  }
  // 后退功能
  back() {
    // 后退操作设置为true
    this.isBack = true;
    if (this.currentIndex !== 0) {
      this.currentIndex = this.currentIndex - 1;
    }
    location.hash = `#${this.history[this.currentIndex]}`;
  }
  forward() {
    // 前进操作设置为true
    this.isForward = true;
    if (this.currentIndex !== this.history.length - 1) {
      this.currentIndex = this.currentIndex + 1;
    }
    location.hash = `#${this.history[this.currentIndex]}`;
  }
}
// 使用
window.Router = new Routers();
const content = document.querySelector('body');
const btn1 = document.querySelector('.btn1');
const btn2 = document.querySelector('.btn2');
function changeBgColor(color) {
  content.style.backgroundColor = color;
}

Router.route('/', function() {
  changeBgColor('pink');
});
Router.route('/yellowgreen', function() {
  changeBgColor('yellowgreen');
});
Router.route('/indianred', function() {
  changeBgColor('indianred');
});

btn1.addEventListener('click', Router.back, false);
btn2.addEventListener('click', Router.forward, false);
  • browser路由

借助 HTML5 History API

<body>
  <ul>
    <li><a href="/">pink</a></li>
    <li><a href="/yellowgreen">yellowgreen</a></li>
    <li><a href="/indianred">indianred</a></li>
  </ul>
  <button class="btn1">back</button>
  <button class="btn2">forward</button>
</body>
class Routers {
  constructor() {
    this.routes = {};
    this._bindPopState();
  }
  init(path) {
    history.replaceState({path: path}, null, path);
    this.routes[path] && this.routes[path]();
  }

  route(path, callback) {
    this.routes[path] = callback || function() {};
  }
  back() {
    history.back();
  }
  forward() {
    history.forward();
  }
  go(path) {
    history.pushState({path: path}, null, path);
    this.routes[path] && this.routes[path]();
  }
  _bindPopState() {
    // IE10+
    window.addEventListener('popstate', e => {
      const path = e.state && e.state.path;
      this.routes[path] && this.routes[path]();
    });
  }
}
// 使用
window.Router = new Routers();
Router.init(location.pathname);
const content = document.querySelector('body');
const ul = document.querySelector('ul');
const btn1 = document.querySelector('.btn1');
const btn2 = document.querySelector('.btn2');
function changeBgColor(color) {
  content.style.backgroundColor = color;
}

Router.route('/', function() {
  changeBgColor('pink');
});
Router.route('/yellowgreen', function() {
  changeBgColor('yellowgreen');
});
Router.route('/indianred', function() {
  changeBgColor('indianred');
});
ul.addEventListener('click', e => {
  if (e.target.tagName === 'A') {
    e.preventDefault();
    Router.go(e.target.getAttribute('href'));
  }
});

btn1.addEventListener('click', Router.back, false);
btn2.addEventListener('click', Router.forward, false);