image.png

    1. class EventBus{
    2. events = {}
    3. on(event, cb){
    4. let cbs = this.events[event] || [];
    5. this.events[event] = [...cbs, cb]
    6. }
    7. off(event, cb){
    8. let cbs = this.events[event] || [];
    9. let index = cbs.indexOf(cb);
    10. if (index !== -1){
    11. this.events[event].splice(index, 1);
    12. }
    13. }
    14. emit(event){
    15. let cbs = this.events[event] || [];
    16. cbs.forEach(cb=>cb())
    17. }
    18. }
    19. --------------------------------------------------------------------------
    20. <!DOCTYPE html>
    21. <html lang="en">
    22. <head>
    23. <meta charset="UTF-8">
    24. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    25. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    26. <title>SPA的原生实现</title>
    27. </head>
    28. <body>
    29. <!-- 导航区域 -->
    30. <div class="router_box">
    31. <a href="/home" class="router" replace="true">主页</a>
    32. <a href="/news" class="router">新闻</a>
    33. <a href="/team" class="router">团队</a>
    34. <a href="/about100" class="router">关于</a>
    35. </div>
    36. <!-- 路由区域 -->
    37. <div id="router-view"></div>
    38. <script src='./EventBus.js'></script>
    39. <script>
    40. let event = new EventBus();
    41. function Router(options){
    42. this.mode = options.mode || 'hash';
    43. this.routes = options.routes || [];
    44. this.init = function(){
    45. var eles = document.querySelectorAll('.router');
    46. var that = this;
    47. [...eles].forEach(item=>{
    48. item.addEventListener('click', function(e){
    49. e.stopPropagation();
    50. e.preventDefault();
    51. var path = e.target.getAttribute('href');
    52. var isReplace = e.target.getAttribute('replace');
    53. console.log('path...', path, isReplace);
    54. if (that.mode == 'hash'){
    55. if (isReplace){
    56. let index = window.location.href.indexOf('#');
    57. window.location.replace(`${window.location.href.slice(0, index)}#${path}`);
    58. }else{
    59. window.location.hash = `#${path}`;
    60. }
    61. }else{
    62. if (isReplace){
    63. window.history.replaceState('', '', path);
    64. }else{
    65. window.history.pushState('', '', path);
    66. }
    67. event.emit('popstate');
    68. }
    69. })
    70. })
    71. // 监听相关事件
    72. if (this.mode === 'hash'){
    73. window.addEventListener('hashchange', this.routeChange.bind(this))
    74. }else{
    75. window.addEventListener('popstate', this.routeChange.bind(this))
    76. event.on('popstate', this.routeChange.bind(this));
    77. }
    78. // 初始化routeChange
    79. this.routeChange();
    80. }
    81. // 响应路由变化
    82. this.routeChange = function(){
    83. let routerView = document.querySelector('#router-view');
    84. console.log('routeChange...');
    85. if (this.mode === 'hash'){
    86. let path = window.location.hash.slice(1);
    87. let index = this.routes.findIndex(item=>item.path === path);
    88. if (index !== -1){
    89. routerView.innerHTML = this.routes[index].component;
    90. }else{
    91. let matchAllIndex = this.routes.findIndex(item=>item.path === '*')
    92. if (matchAllIndex !== -1){
    93. let index = window.location.href.indexOf('#');
    94. window.location.replace(`${window.location.href.slice(0, index)}#${this.routes[matchAllIndex].redirect}`);
    95. }
    96. }
    97. }else{
    98. let path = window.location.pathname;
    99. let index = this.routes.findIndex(item=>item.path === path);
    100. if (index !== -1){
    101. routerView.innerHTML = this.routes[index].component;
    102. }else{
    103. let matchAllIndex = this.routes.findIndex(item=>item.path === '*')
    104. if (matchAllIndex !== -1){
    105. let index = window.location.href.indexOf('#');
    106. window.history.replaceState('', '', this.routes[matchAllIndex].redirect);
    107. }
    108. }
    109. }
    110. }
    111. this.init();
    112. }
    113. new Router({
    114. mode: 'hash',
    115. routes:[
    116. { path: '/home', component: '<h1>主页</h1><h4>新一代前端工程师:我们啥都会</h4>' },
    117. { path: '/news', component: '<h1>新闻</h1><h4>今天2018-11-5,上课还得穿工装</h4>' },
    118. { path: '/team', component: '<h1>团队</h1><h4>WEB前端工程师</h4>' },
    119. { path: '/about', component: '<h1>关于</h1><h4>一面而高薪就业</h4>' },
    120. { path:'*', redirect:'/home'}
    121. ]
    122. })
    123. </script>
    124. </body>
    125. </html>