Two routing modes of vue

Posted by mdub2112 on Fri, 25 Feb 2022 12:53:50 +0100

Two routing modes of vue

The two routing modes of vue are hash and history respectively. Why in the development environment, when using the history mode, the refresh does not report an error, but when packaged into a static file and online, open the blank page of the project (most of this can be solved in the configuration file configuration: publicPath: '. /'), or the display is normal when opening and the jump is normal, but the refresh will report 404? Because after the project is packaged as a static file and launched online, it is just a static file, which is managed by your nginx or other proxy server. F5 refresh in this project will still be equal to the request url. If the corresponding path cannot be matched, it will still report 404 In the development environment, there is a service (Port 8080) hosted. My personal guess is that vue scaffold should do a lot of processing, such as jump / when the path cannot be matched when refreshing, so 404 will not be reported in the development environment. The hash mode is different. No matter when it is developed or packaged into a dist static file, it will not report 404. For example, directly find the index in the packaged dist file HTML open access and then refresh will not report 404, because the refresh will only find the url in front of the # number, that is, no matter what is behind the # number, the refresh is the original path in front of the # number

hash routing

Configure nginx

After configuring nginx, create a hashDeom folder in the root directory of nginx, and create an index HTML, and then open the localhost:5001 port in the browser for debugging. For example, my nginx root directory is D:\phpstudy_pro\Extensions\Nginx1.15.11, create a hashDeom folder here, and then create an index HTML can be accessed through localhost:5001 port

server {
    listen       5001;
    server_name  localhost;
    gzip on;
    # The type of file to compress.
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    # Whether to add vary: accept encoding in http header. It is recommended to enable it
    gzip_vary on;
    location / {
        root   hashDemo;
        index  index.html index.htm;
    }
    location /profile {
        default_type application/json ;
        return 200  '{"name":"profile","result":"profile-success"}';
    }
    location /homeAjax {    #Case insensitive, homeajax and homeajax can be matched
        default_type application/json ;
        return 200  '{"name":"homeAjax","result":"homeAjax-success"}';
    }
    location /profileAjax {
        default_type application/json ;
        return 200  '{"name":"profileAjax","result":"profileAjax-success"}';
    }

}

hash

In the hash mode, only the contents before the hash symbol will be included in the request. For example, enter: localhost:5001/#home or localhost:5001/#profile in the address bar, and then press enter. The actual requested address is still: localhost:5001. Therefore, for the backend, as long as the path of localhost:5001 / is matched, 404 will not be reported

<body>
    <h1 style="color: red;">hash pattern</h1>
    <div>
        <h1>use location.href Method change url,No network requests will be initiated</h1>
        <button onClick="goHome()">home</button>
        <button onClick="goProfile()">profile</button>
        <button onClick="goLogin()">login</button>
        <button onClick="goNotFount()">404</button>
    </div>
    <div>
        <h1>use history Other method changes url,No network requests will be initiated</h1>
        <button onClick="go(1)">Next history url:go(1)</button>
        <button onClick="go(-1)">Previous history url: go(-1)</button>
        <button onClick="go(2)">Next two histories url:go(2)</button>
        <button onClick="go(-2)">Last two histories url:go(-2)</button>
        <button onClick="back()">Previous history url:back()</button>
        <button onClick="forward()">Next history url:forward()</button>
    </div>
    <div>
        <h1>Initiate network request</h1>
        <button onClick="getData('profileAjax')">profileAjax</button>
        <button onClick="getData('homeAjax')">homeAjax</button>
        <span class="ajaxdata"></span>
    </div>
    <h1 style="color: red;">
        Current route:<span class="view"></span>
    </h1>


    <script>
        var view = document.getElementsByClassName('view')[0]
        var ajaxdata = document.getElementsByClassName('ajaxdata')[0]
        // Monitor url changes
        window.addEventListener("hashchange", (e) => {
            console.log('hash The address bar has changed');
            hashchange()
        });

        // The first time I came in, I couldn't hear the url change, so I need to execute it first
        hashchange()

        function hashchange() {
            // update the view
            // view.innerHTML = location.href
            switch (location.hash) {
                case "":
                    view.innerHTML = 'It is currently the home page of the website'
                    // view.innerHTML = location
                    break;
                case "#home":
                    view.innerHTML = location.hash
                    // view.innerHTML = location
                    break;
                case "#profile":
                    view.innerHTML = location.hash
                    // view.innerHTML = location
                    break;
                case "#login":
                    view.innerHTML = location.hash
                    // view.innerHTML = location
                    break;
                default:
                    // view.innerHTML = '404'
                    view.innerHTML = '404 Cannot match:' + location.hash
            }
        }

        function goHome() {
            // console.log('goHome');
            window.location.href = "#home"
        }
        function goProfile() {
            // console.log('goProfile');
            window.location.href = "#profile"
        }
        function goLogin() {
            // console.log('goLogin');
            window.location.href = "#login"
        }
        function goNotFount() {
            // console.log('goNotFount');
            window.location.href = "#404" + Math.floor((Math.random() * 99) + 1)
        }
        // Request data
        function getData(url) {
            fetch(url).then(function (response) {
                return response.json();
            }).then(function (res) {
                // console.log(res);
                ajaxdata.innerHTML = JSON.stringify(res)
            }).catch(function (err) {
                console.log(err);
            })
        }
        function go(num) {
            history.go(num)
        }
        function back() {
            // The back() method loads the previous URL (if any) in the history list.
            history.back()  // === history(-1)
        }
        function forward() {
            // The forward() method loads the next URL in the history list.
            history.forward()  // === history(1)
        }
    </script>
</body>

history routing

Configure nginx

Add server under http module

server {
    listen       5002;
    server_name  localhost;
    gzip on;
    # The type of file to compress.
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    # Whether to add vary: accept encoding in http header. It is recommended to enable it
    gzip_vary on;
    location / {
        root   historyDemo;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
    location /profile {
        default_type application/json ;
        return 200  '{"name":"profile","result":"profile-success"}';
    }
    location /homeAjax {    #Case insensitive, homeajax and homeajax can be matched
        default_type application/json ;
        return 200  '{"name":"homeAjax","result":"homeAjax-success"}';
    }
    location /profileAjax {
        default_type application/json ;
        return 200  '{"name":"profileAjax","result":"profileAjax-success"}';
    }
}

history

In the history mode, the path of the address bar must be matched by the back-end. For example, enter localhost:5002/home in the address bar, and the actual requested address is localhost:5002/home. The back-end must process the matching / home route. If the back-end does not match / home, the front-end enters localhost:5002/home in the address bar, and then press enter to refresh, and 404 will be reported. Because the front end can enter the address bar to jump freely, if the back end wants to match all routes, it can use nginx to add a location / record and add: try_files uri uri/ /index.html; In this way, if / home cannot be matched when the front-end address bar is refreshed, it will be matched by / and then redirected to jump to index html

<body>
    <h1 style="color:green;">history pattern</h1>
    <div>
        <h1>use history.pushState Method change url,No network requests will be initiated</h1>
        <button onClick="goHome()">home</button>
        <button onClick="goProfile()">profile</button>
        <button onClick="goLogin()">login</button>
        <button onClick="goNotFount()">404</button>
    </div>
    <div>
        <h1>use history Other method changes url,No network requests will be initiated</h1>
        <button onClick="go(1)">Next history url:go(1)</button>
        <button onClick="go(-1)">Previous history url: go(-1)</button>
        <button onClick="go(2)">Next two histories url:go(2)</button>
        <button onClick="go(-2)">Last two histories url:go(-2)</button>
        <button onClick="back()">Previous history url:back()</button>
        <button onClick="forward()">Next history url:forward()</button>
    </div>
    <div>
        <h1>Initiate network request</h1>
        <button onClick="getData('profileAjax')">profileAjax</button>
        <button onClick="getData('homeAjax')">homeAjax</button>
        <span class="ajaxdata"></span>
    </div>
    <h1 style="color: red;">
        Current route:<span class="view"></span>,
        Current routing data:<span class="routermeta"></span>
    </h1>

    <script>
        // Get view
        var view = document.getElementsByClassName('view')[0]
        var routermeta = document.getElementsByClassName('routermeta')[0]
        var ajaxdata = document.getElementsByClassName('ajaxdata')[0]

        // Call the first time you come in.
        popstate()

        // Monitor url changes
        window.addEventListener("popstate", (e) => {
            console.log('Click forward/back off, history The address bar has changed');
            popstate()
        });

        // Monitor url changes and update view
        function popstate() {
            routermeta.innerHTML = JSON.stringify(history.state)
            console.log(location)
            switch (location.pathname) {
                case "/":
                    view.innerHTML = 'It is currently the home page of the website'
                    view.innerHTML = location
                    break;
                case "/home":
                    view.innerHTML = 'home'
                    // view.innerHTML = location
                    break;
                case "/profile":
                    view.innerHTML = 'profile'
                    // view.innerHTML = location
                    break;
                case "/login":
                    view.innerHTML = 'login'
                    // view.innerHTML = location
                    break;
                default:
                    // view.innerHTML = '404'
                    view.innerHTML = '404 Cannot match:' + location.pathname
            }
        }

        // Request data
        function getData(url) {
            fetch(url).then(function (response) {
                return response.json();
            }).then(function (res) {
                // console.log(res);
                ajaxdata.innerHTML = JSON.stringify(res)
            }).catch(function (err) {
                console.log(err);
            })
        }
        function go(num) {
            history.go(num)
        }
        function back() {
            // The back() method loads the previous URL (if any) in the history list.
            history.back()  // === history(-1)
        }
        function forward() {
            // The forward() method loads the next URL in the history list.
            history.forward()  // === history(1)
        }
        function goHome() {
            // console.log('goHome');
            history.pushState({ message: 'I am home' }, "", '/home');
            popstate()
        }
        function goProfile() {
            // console.log('goProfile');
            history.pushState({ message: 'I am profile' }, "", '/profile');
            popstate()
        }
        function goLogin() {
            // console.log('goLogin');
            history.pushState({ message: 'I am login' }, "", '/login');
            popstate()
        }
        function goNotFount() {
            // console.log('goNotFount');
            history.pushState({ message: 'I'm 404' }, "", '/404' + Math.floor((Math.random() * 99) + 1));
            popstate()
        }
    </script>
</body>

The above history case uses nginx hosting. You can simulate the online environment by directly opening localhost:5002 in the browser. After opening, except clicking the initiate network request button, clicking other buttons will not initiate a request. For example, clicking home will change the url address to localhost:5002/home, but will not initiate a localhost:5002/home request. At this time, if you click home to change the address bar and press F5 to refresh, a localhost:5002/home request will be initiated, However, nginx cannot match / home, so it will match /, and then redirect to the original index html;

An exception here is that if you click the profile button from the browser, the address bar will change to localhost:5002/profile, and the network request will not be initiated. However, if you directly press F5 to refresh the address bar when it is localhost:5002/profile, the network request will be initiated, and then nginx just has a / profile routing record matching, so the data returned by / profile will be returned, Instead of matching to / for redirection!

difference

Common ground: you can change the route (address bar) without refreshing the page

difference:

  • If the problem is displayed, hash will be marked with # number in the address bar, but history will not
  • history can add any type of data and title to the record through pushState, while hash can only add a short string after the # number (because the url length on the address bar is limited)
  • When the hash is refreshed, only the content before the # number will be used as the request url to initiate the request, such as ABC COM #home, only ABC Com as a url. The backend only needs to match ABC COM is OK; history will send the full path request, such as ABC COM / home, ABC COM / home as the url to initiate the request. The backend needs to add a match / covering the full path. If / home cannot be matched, redirect it to an ABC Com page (such as index.html), so it won't report 404