Front end routing (history+hash)

Keywords: Javascript Session PHP JSP

Blog address changed before, republish!

In traditional website development, we usually use technologies such as asp, php and jsp to develop. After the development is completed, we will deploy them on the server. When we visit, we will send them with '. asp', '. php' in the browser, For url requests with suffix paths such as'. jsp ', the server will find the page we requested and render it as HTML according to the corresponding route mapping table, and then return the HTML page directly to the browser for display, which is called Server Side Render.

However, with the improvement of the complexity of front-end pages and the rise of front-end technology (especially the rise of Ajax Technology), the industry increasingly advocates the development mode of front-end and back-end separation. So that the server-side does not pay attention to the rendering of HTML pages, but only focuses on the development of logic and provides data through Api; the front-end only focuses on the development of UI and inserts DOM generated from the data requested by the server into the page. The way to request data from the server and generate presentation pages by the client through front-end technology is Client Side Render.

Client-side rendering separates the front and back ends, focusing on their own parts, and improves user experience. User interaction does not need to refresh the page every time. Based on these advantages, the development model of SPA (Single Page Web Application) is very popular. You can dynamically rewrite the current page to interact with users without reloading the entire page. However, in order to realize the single page application and realize the experience of interaction and jump without refreshing, an important problem needs to be solved, that is, the routing problem. So there is a front-end route. In fact, the front-end route is the appellation of the server-side route. The front-end controls and maintains the mapping relationship between the url and the UI. After the url changes, the UI updates without refreshing the page.

Let's implement front-end routing in two ways:

The overall idea of realizing front-end Routing:
First, maintain a route mapping table containing path and corresponding page content. When the route changes, filter out the corresponding route information from the route mapping table, and add the corresponding content page rendering in the route information to the html page for display. Before you start, learn the basics of the two ways.

1.window.history

Window.history is a read-only property used to get the History object containing the operation browser session History.
Main methods:
back()
Go to the previous page, the user can click the back button in the upper left corner of the browser to simulate this method. It is equivalent to history.go(-1)
forward()
In the browser history to the next page, the user can click the forward button in the upper left corner of the browser to simulate this method. It is equivalent to history.go(1)
go()
Load a page from browser history (Session History) through the relative position of the current page
pushState()
push the data into the session history stack by the specified name and URL (if this parameter is provided), and the data is opaque by DOM; you can specify any javascript object that can be serialized.
replaceState()
Update the latest entry on the history stack with the specified data, name, and URL (if provided). This data is opaque by DOM. You can specify any javascript object that can be serialized.

2.location.hash

The hash property is a readable and writable string that is the anchor part of the URL (the part starting with the #).

The implementation code is as follows:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>window.history Route</title>
</head>

<body>
  <div>
    <div id="routerLink">
      <div>
        <button onclick="historyChange('home')">home page(history)/button>
          <button onclick="historyChange('about')">about(history)</button>
      </div>
      <div>
        <button onclick="hashChange('home')">home page(hash)</button>
        <button onclick="hashChange('about')">about(hash)</button>
      </div>
    </div>
    <div>
      <div id="routerView">

      </div>
    </div>
  </div>
  <!-- 2.Create subview template -->
  <template id="home">
    <div>hello,I'm home</div>
  </template>
  <template id="about">
    <div>hello,I'm about</div>
  </template>
  <script>
    //1. Create a routing table first
    const routerTable = [
      {
        path: 'home',
        component: '#home'
      },
      {
        path: 'about',
        component: '#about'
      }
    ]

    //***********Mode 1: window.history**************
    //3. (window.history) listens for route changes and loads corresponding contents according to the new route path
    function historyChange(path) {
      render({ path: path })
    }
    //Add popstate status listening
    window.addEventListener('popstate', function (e) {
      if (e) {
        render({ path: e.state, isPush: false })
      }
    })

    //**************Mode 2: location.hash***************
    function hashChange(path) {
      render({ path: path, mode: 'hash' })
    }
    //Add hashchange listening
    window.addEventListener('hashchange', function () {
      let path = location.hash
      //path remove started#
      render({ path: path.substring(1, path.length - 2), mode: 'hash' })
    })

    //**************Public method*******************
    //rendering method 
    function render(data) {
      //The default value is history, isPush=true, isReplace=false,path=home
      data = Object.assign({ mode: 'history', isPush: true, isReplace: false, path: 'home' }, data)
      if (data.path) {
        //Query route information
        const route = routerTable.find(p => p.path == data.path);
        if (route) {
          if (data.mode == 'history') {
            if (data.isPush) {
              //Change url --- back and forward do not change
              if (data.isReplace) {
                window.history.replaceState(data.path, '', data.path)
              } else {
                window.history.pushState(data.path, '', data.path)
              }
            }
          } else if (data.mode == 'hash') {
            location.hash = data.path
          }
          //Update html
          document.querySelector("#routerView").innerHTML = document.querySelector(route.component).innerHTML
        }
      }
    }
  </script>
</body>
</html>

 

PS: you need to run the page in http mode, otherwise pushState cannot be used, and an error of "cannot be created in a document with origin 'null' will be reported.
However, if vscode is already installed on your computer, you can download the Live Server plug-in to run the html file.

Posted by maybl8r03 on Tue, 28 Apr 2020 23:08:35 -0700