I am learning backbone recently. To understand backbone, you must first understand spa. To understand spa, you must first understand how a single-page application can change the URL without refreshing the page.
Compared with jumping to different pages, AJAX can be said to have greatly improved the user's browsing experience. It is very pleasant to not have to see the white screen between page switches. However, many early AJAX applications did not support the browser's forward and backward functions. This resulted in the user no matter where they browsed on the website, they would immediately return to the original position once refreshed, and the user was unable to use the browser's forward and backward functions. button to switch browsing history.
For the first problem, it is relatively easy to solve. Just use cookies or localStorage to record the status of the application, read this status when refreshing the page, and then send the corresponding ajax request to change the page. But the second problem is very troublesome. Let’s talk about the solution of modern browsers first.
HTML5 Solution
To understand how HTML5 implements forward and backward, you must first understand the history object and location object.
history object
History object properties
1.length: Returns the number of URLs in the browser history list. Each time the user visits a page in the current tab, this number is increased by 1. For privacy reasons, the specific content of the URL is not visible.
2.state: Object related to the current URL, which can only be added or modified through pushState and replaceState. We can use it to store information related to the url.
History object method
1.history.back()
This method has no parameters. After being triggered, it will return to the previously browsed page, which is equivalent to clicking the browser's back button.
2.history.forward()
This method has no parameters. When triggered, it will return to the page you browsed before going back, which is equivalent to clicking the browser's forward button.
3.history.go(number)
This method accepts an integer variable parameter. history.go(-1) is equivalent to going back one page, history.go(1) is equivalent to going one page forward, and history.go(0) will refresh the current page.
4.history.pushState(state, title, url)
The key to changing the URL without refreshing the page is this. This method will change the location.href of the current page and modify the current history.state object. After execution, history.length will increase by 1. This method accepts three parameters,
1.state: Object related to the current URL.
2.title: The page title, but all browsers ignore it. To change the title, you still need to use document.title.
3.url: A URL in the same domain as the current page, location.href will become this value.
5.history.replaceState(state, title, url)
This method is the same as above, but it will not change history.length, but will only modify history.state and location.href.
Note that the third parameter of pushState and replaceState cannot cross domains, and will not trigger the browser's popstate event and onhashchange event (tested under chrome33).
location object
In addition to clicking the forward/back button and history event, you can also change the Url through the location method and modify the location properties:
Attributes of location object (read and write):
1.host: domain name port number
2.hostname: domain name
3.port: port number
4.protocol: protocol
5.href: full path
6.origin: protocol domain name port
7.hash: URL(hash) starting with pound sign (#)
8.pathname: document path document name
9.search:The content after (?)
You can achieve the purpose of no refresh by changing location.href or location.hash.
Methods of location object:
1.assign: Change the value of url, and adding the current url to the history history.length will increase by 1. location.asig(‘#’ x) will change the url but not refresh the page.
2.reload: Refresh the page.
3.replace: Change the value of url, but history.length remains unchanged. The usage method is the same as assign.
popstate event
When the URL changes, for example, the user clicks the forward/back button, history.go(n) (n is not equal to 0), location.hash = x (x is not equal to the current location.hash) will trigger this event. You can use it to monitor URLs to implement various functions.
onhashchange event
Changing the hash value will trigger the popstate event, but triggering the popstate event will not necessarily trigger the onhashchange event. Tested:
1.hash changes but location.pathname remains unchanged will trigger the onhashchange event, such as history.pushState(”, ”, ‘#abc’);
2. It will not trigger if hash and location.pathname are changed together, such as history.pushState(”, ”, ‘a#abc’);
How to write in old browsers
Old browsers also do not support pushState and replaceState, so monitoring url changes through popstate (in fact, this method is not supported) is not feasible. Then you can only achieve no refresh by changing the content after url#, but they do not support onhashchange, so they are indifferent to changes in the url (except that the page will scroll to the position corresponding to the id of the page). Then you can only resort to the big trick: polling, set a setInterval to monitor the value of the url. Like this:
Of course, writing this way is very frustrating. If you don’t consider clicking on the a tag with an ID on the page to change the hash, you can use design patterns to elegantly implement monitoring urls. For example, in the classic observer pattern, a class is specifically used to implement the function of changing the hash, and then all classes (observers) that want to monitor URL changes subscribe to this (observed) class.