Hello, talk about your understanding of front-end routing

Preface

Well, do not install, and today I embodiment of sexy interviewer asks you a question online, "talk about your understanding of front-end route" . Seeing this question, there are too many answers. But think about it from another perspective. When you ask the candidate this question, what answer do you want? In my humble opinion, I hope that candidates can interpret this issue from the overall perspective, roughly the following three points.

  • Why is there front-end routing
  • What problem does the front-end routing solve
  • What is the principle of front-end routing

With these three questions, we continue to look down.

Traditional page

We don't entangle the name here DOM. We call it a "traditional page" where the entire project is a straight-out page (SSR belongs to the first screen straight-out, here I don't think it is a traditional page). So what is DOMstraight out of it? It simply is a request to initiate the browser enter the URL, return to the HTMLpage is the final presentation of the results, that is, DOMstraight out. And page-per-click jump, will be re-requested HTMLresources. seeing is believing. Let’s take this address as an example to verify the following statement
https://www.cnblogs.com/han-1034683568/p/14126727.html#4773138

Insert picture description here
At a glance, you can understand what the picture above is describing. Yes, the blog is a traditional garden structures made website page, each time the page is loaded, returns HTMLresources and inside the CSSstatic resources, combined into a new page.

"Blind" classmates, I will teach another method, which is to right-click on the browser page and click "Show webpage source code". After opening it, it will look like the following:
Insert picture description here
What pictures or text can you see on the webpage? find the corresponding HTMLstructure, that belong to the traditional page, that is, DOMstraight out.

Single Page

The times are advancing and technology is developing. Faced with the increasing demand for web pages, web pages have begun to move towards modularization and componentization. What follows is that the code is difficult to maintain, uncontrollable, and difficult to iterate. Faced with this situation, gave birth to a lot of good modern front-end framework, bore the brunt of React, Vue, Angularwaiting lists page application framework. And these frameworks have a common feature, which is "rendering pages through JS".

For example, we used straight out DOM, but now after a single use of these page frame, HTMLthe page is basically only a DOMinlet, shown generally as follows:
Insert picture description here
all the page components are run through the bottom of FIG app.jsscript, to mount <div id="root"></div>this node the following. Use an extremely simple JS to show the step of mounting:

<body>
  <div id="root"></div>
  <script>
    const root = document.getElementById('root') // 获取根节点
    const divNode = document.createElement('div') // 创建 div 节点
    divNode.innerText = '你妈贵姓?' // 插入内容
    root.appendChild(divNode) // 插入根节点
  </script>
</body>

Insert picture description here
Get rid of all the mundane, the most authentic one-page project operation form is like this. Attention, I want to make a point! ! !
Insert picture description here
Since the single page is rendered in this way, if I have more than a dozen pages to switch to each other, what a complete! ! ? ? At this time 前端路由came into being, it appears to solve a single page website, by switching the browser address path to match the corresponding page components. Through an ugly picture to understand this process:
Insert picture description here
front-end routing based on the browser address bar pathnamechange to match the corresponding page components. Then by creating DOMas nodes, into the root node <div id="root"></div>. This effect is achieved without refreshing the page to switch from the side can also explain because no refresh, so React, Vue, Angularand other modern framework when creating the page components, each component has its own life cycle.

principle

Front-end routing plug two more fire corresponding framework is Vue-Routerand React-Router, but their logic, in the final analysis is the same, the same thing with words, very appropriate.

By analyzing the implementation principles of hash mode and historical mode, let everyone have a deeper understanding of the principle of front-end routing.

Hash mode

aAnchor tag we should not be unfamiliar, but the browser address #behind the changes can be monitored, the browser provides us with native event listener hashchange, it can listen to the following changes:

  • Click on athe tab, change the browser's address
  • Browser's forward and backward behavior
  • By window.locationway change the browser address

Next we take advantage of these features, to achieve a hashmodel of simple route: online operation

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Hash 模式</title>
</head>
  <body>
    <div>
      <ul>
        <li><a href="#/page1">page1</a></li>
        <li><a href="#/page2">page2</a></li>
      </ul>
      <!--渲染对应组件的地方-->
      <div id="route-view"></div>
    </div>
  <script type="text/javascript">
    // 第一次加载的时候,不会执行 hashchange 监听事件,默认执行一次
    // DOMContentLoaded 为浏览器 DOM 加载完成时触发
    window.addEventListener('DOMContentLoaded', Load)
    window.addEventListener('hashchange', HashChange)
    // 展示页面组件的节点
    var routeView = null
    function Load() {
     
     
      routeView = document.getElementById('route-view')
      HashChange()
    }
    function HashChange() {
     
     
      // 每次触发 hashchange 事件,通过 location.hash 拿到当前浏览器地址的 hash 值
      // 根据不同的路径展示不同的内容
      switch(location.hash) {
     
     
      case '#/page1':
        routeView.innerHTML = 'page1'
        return
      case '#/page2':
        routeView.innerHTML = 'page2'
        return
      default:
        routeView.innerHTML = 'page1'
        return
      }
    }
  </script>
  </body>
</html>

Of course, this is a very simple implementation. For the real hash mode, many complicated situations must be taken into consideration. If you are interested, please check the source code.

The browser display effect is as follows:
Insert picture description here

Historical mode

historyMode than hasha little trouble mode, because the historymodel relies on the native event popstate, here is an explanation from the MDN:
Insert picture description here

Tips: pushState and replaceState are both new APIs of HTML5. They are very powerful and can change the browser address without refreshing the page. This is an important way to change the address bar without refreshing the page.

Including alabel click event is not popstatelistening. We need to find a way to solve this problem, in order to achieve historymode.
Insert picture description here
Solutions : We can iterate through all the pages on the alabel to prevent athe default event tags at the same time, with the click event of a callback function to get the callback function in the alabel hrefattribute value, and then through pushStateto change the browser's location.pathnameproperty values. And then manually execute popstateevent callback function to match the appropriate route. It may be a bit forgiving in logic, let's use code to explain: online address

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>History 模式</title>
</head>
<body>
  <div>
    <ul>
      <li><a href="/page1">page1</a></li>
      <li><a href="/page2">page2</a></li>
    </ul>
    <div id="route-view"></div>
  </div>
  <script type="text/javascript">
    window.addEventListener('DOMContentLoaded', Load)
    window.addEventListener('popstate', PopChange)
    var routeView = null
    function Load() {
     
     
      routeView = document.getElementById('route-view')
      // 默认执行一次 popstate 的回调函数,匹配一次页面组件
      PopChange()
      // 获取所有带 href 属性的 a 标签节点
      var aList = document.querySelectorAll('a[href]')
      // 遍历 a 标签节点数组,阻止默认事件,添加点击事件回调函数
      aList.forEach(aNode => aNode.addEventListener('click', function(e) {
     
     
        e.preventDefault() //阻止a标签的默认事件
        var href = aNode.getAttribute('href')
        //  手动修改浏览器的地址栏
        history.pushState(null, '', href)
        // 通过 history.pushState 手动修改地址栏,
        // popstate 是监听不到地址栏的变化,所以此处需要手动执行回调函数 PopChange
        PopChange()
      }))
    }
    function PopChange() {
     
     
      console.log('location', location)
      switch(location.pathname) {
     
     
      case '/page1':
        routeView.innerHTML = 'page1'
        return
      case '/page2':
        routeView.innerHTML = 'page2'
        return
      default:
        routeView.innerHTML = 'page1'
        return
      }
    }
  </script>
</body>
</html>

Note here that you cannot open static files directly in the browser, you need to start the port to browse the URL through the web service.

to sum up

The main knowledge points of this article focus on the front-end routing. If you can read it completely, and go through the implementation principles, I think you should have a new understanding of modern front-end frameworks.


There is a WeChat mini program course design, complete design needs, contact personal QQ: 505417246

Pay attention to the following WeChat public account, you can receive WeChat applet, Vue, TypeScript, front-end, uni-app, full stack, Nodejs, Python and other practical learning materials. The
latest and most complete front-end knowledge summary and project source code will be released to the WeChat public as soon as possible No., please pay attention, thank you!

Insert picture description here

Guess you like

Origin blog.csdn.net/m0_46171043/article/details/112796220