The popularity of Ajax and the rapid development of front-end MVVM framework bring great convenience to Web development, but also make the Web application experience better and better, in recent years, single-page applications have become popular. The use of Ajax allows web pages to update data without refreshing, but it also causes the browser to be unable to move forward and backward (the physical back button of the browser and the phone). In the early days, this problem was usually solved with iframe. Thanks to HTML5, there are solutions such as PJAX (Ajax +pushState). This article will show you how to switch between single-page application pages using anchors and the History API.

Before explaining the requirements, let’s talk about the results as shown below:

Requirements:

  • Click the phone info TAB and highlight the phone edit page from the right

  • Enter the mobile phone number and verification code to save the Settings and return to the basic information page

  • The browser clicks forward and back to switch between the two pages

  • Support for the phone’s physical back key (equivalent to history.back())

  • The page needs to be partially refreshed to keep the URL consistent

The difficulty of the whole problem should be dealing with the forward and backward, other requirements are briefly described below.

The main HTML structure of the page is as follows:

<div class="main" id="main">
    <div v-show=! "" edit" v-cloak>
      <ul class="list">
        <li @click="toggle(1)">
          <label for="">Mobile phone</label>
           <div class="list-info">{{showPhone}}</div>
        </li>
        <! -- Other basic information -->
      </ul>
      <div class="btn">Log out</div>
    </div>
    <div class="translate" :class="{open: edit}">
        <div class="input-wrap">
          <input type="text" class="input" v-model="phone" placeholder="Please enter your cell phone.">
        </div>
        <div class="input-wrap">
          <input type="text" class="input" placeholder="Please enter the verification code you received." v-model="code">
          <a class="input-btn">Obtaining verification code</a>
        </div>
        <div class="text-right">Don't get? Try the voice captcha</div>
        <div class="btn btn-submit" @click="toggle(0)" :class="{disabled: ! phone || ! code}">submit</div>
    </div>
</div>Copy the code

This includes the basic information page and the edit page in two sibling div tags.

Some of the main CSS styles are as follows (unprefixed) :

.translate {
  position: fixed;
  top: 0;
  bottom: 0;
  width: 100%;
  background: #efeff4;
  -webkit-transform: translateX(100%).-webkit-transition: transform .4s;
}
.translate.open {
  -webkit-transform: translateX(0);
}Copy the code

By default, the edit page is panned to the right where it is not visible. When the edit page is opened, add the open class name to panned to the visible.

Next, use VUE to implement the basic logic of the page. The basic code is as follows:

var vm = new Vue({
  el: '#main'.data: {
    edit: false.phone: ' '.code: ' '
  },
  methods: {
    toggle: function(value){
     // Handle logic here}},computed: {
    showPhone: function(){
      return (this.phone || '13688888888').replace(/(\d{3})(\d{4})(\d{4})/.'$1 $3 * * * *')}}});Copy the code

There are two ways to accomplish the above requirements

Method 1: Use the History API to do this

HTML5 bitHistory provides the following API:

  • Window.history. pushState(stateObj, title, URL) : pushState(stateObj, title, URL) : adds a new history to the current browser history stack.

    StateObj: Object or string describing a new record for later use, available with history.state, such as {id: 0, name: ‘home’}

    Title: A string that represents the title of the page. Most browsers currently ignore this parameter

    Url: A string, the URL of the new page

  • Window. The history. ReplaceState (stateObj, title, url) : agree with pushState, the difference is not to add new record history stack, but rather to replace the current browsing history, often used in landing page.

  • Popstate (e)

This event is triggered when the user clicks the browser’s forward and back buttons, and the event receives a parameter pointing to the current history. The stateObj set earlier is included in this object. E Printed in the following format:

With the above API, according to the requirements, the idea of implementation is roughly as follows:

  1. When entering the page, replace the current browsing history with replaceState. The stateObj value is {page: ‘home’}

  2. After clicking on the phone to edit, use pushState to add a new record to the browser record with the stateObj value {page: ‘edit’} and add the open class to the edit page to make it visible

  3. Listen for popState events as you go forward and backward, and get the current history.state, and switch pages by judging the value of state.page

The final processing logic is as follows:

var vm = new Vue({
  el: '#main'.data: {... },methods: {
    toggle: function(value){
      this.edit = value;// Switch pages
      if(value){// If you switch to the Edit page, add a new browsing record
        history.pushState({page: 'edit'},' ');
      } else {// Return to the basic information page from the edit pagehistory.back(); }}},computed: {...}
});
history.replaceState({page:'home'},' ' );// Replace the current browsing history after entering the page
window.addEventListener('popstate'.function(e){// Listen forward and backward
  if (history.state) {
    vm.edit = history.state.page == 'edit';// Switch pages}})Copy the code

The result is as follows:

This allows us to implement a simple single-page page switch using the History API, which allows for more complex applications, If you also want to change the URL during page switching (which is good for SEO), you can do this by specifying the URL parameters for pushState and replaceState.

Method 2: Use location.hash(anchor points)

Anchor points are used for quick positioning within a page. By specifying an anchor point, you can redirect the page to the location of a specified element. Changing the hash value has the property of not refreshing the page. Using anchors to move the browser forward and backward mainly uses the following two methods:

  • Location. hash: Gets the current anchor value, returning either an empty string or a value in the #detail format

  • Window. onhashchange: new HTML5 event that listens for changes to the hash value of an address, accepts a callback function as an argument, and returns to the function to receive an object of the following format:

The basic idea of implementing our requirements with hash is as follows:

  1. After clicking mobile edit, change the hash value to ‘#edit’

  2. Listen for hash changes and control page transitions by judging the values (in this case, changing vm.edit values)

Therefore, the complete code will look like this:


var vm = new Vue({
  el: '#main'.data: {... },methods: {
    toggle: function(value){
      location.hash = value ? '#edit' : ' '; }},computed: {... }}});window.addEventListener('hashchange'.function(e){
  vm.edit = location.hash == '#edit';
})Copy the code

In this example, the code looks cleaner this way than using the History API

The result is as follows (note the browser address change) :

conclusion

The above two solutions realize the switching of the page before the page in a single page and the ability to operate the browser forward and backward. In fact, the history API and Location.hash are more than just that. In addition, they can be used in scenarios such as round-robin effects, paging, routing, and so on. Master its use, combined with some encapsulation, can be used in a more complete system.

reading

The mechanism, application and problems of PJAX related URL anchor HTML locating technology