主頁 > 知識庫 > 用Ajax來控制書簽和回退按鈕的代碼

用Ajax來控制書簽和回退按鈕的代碼

熱門標(biāo)簽:遼寧正規(guī)電銷機器人 海南銀行智能外呼系統(tǒng)商家 澳大利亞城市地圖標(biāo)注 遼寧銀行智能外呼系統(tǒng) 電銷機器人違法了嗎 上海浦東騰訊地圖標(biāo)注位置 辰溪地圖標(biāo)注 許昌智能電銷機器人公司 姜堰電銷機器人
這篇文章描述了一個支持Ajax應(yīng)用書簽和回退按鈕的開源的javascript庫。在這個指南的最后,開發(fā)者將會得出一個甚至不是Google Maps 或者 Gmail那樣處理的Ajax的解決方案:健壯的,可用的書簽和向前向后的動作能夠象其他的web頁面一樣正確的工作。

  Ajax:怎樣去控制書簽和回退按鈕 這篇文章說明了一個重要的成果,Ajax應(yīng)用目前面對著書簽和回退按鈕的應(yīng)用,描述了非常簡單的歷史庫(Really Simple History),一個開源的解決這類問題的框架,并提供了一些能夠運行的例子。

  這篇文章描述的主要問題是雙重的,一是一個隱藏的html 表單被用作一個大而短生命周期的客戶端信息的session緩存,這個緩存對在這個頁面上前進(jìn)回退是強壯的。二是一個錨連接和隱藏的iframes的組合用來截取和記錄瀏覽器的歷史事件,來實現(xiàn)前進(jìn)和回退的按鈕。這兩個技術(shù)都被用一個簡單的javascript庫來封裝,以利于開發(fā)者的使用。

  存在的問題

  書簽和回退按鈕在傳統(tǒng)的多頁面的web應(yīng)用上能順利的運行。當(dāng)用戶在網(wǎng)站上沖浪時,他們的瀏覽器地址欄能更新URL,這些URL可以被粘貼到的email或者添加到書簽以備以后的使用?;赝撕颓斑M(jìn)按鈕也可以正常運行,這可以使用戶在他們訪問的頁面間移動。

  Ajax應(yīng)用是與眾不同的,然而,他也是在單一web頁面上成熟的程序。瀏覽器不是為Ajax而做的—Ajax他捕獲過去的事件,當(dāng)web應(yīng)用在每個鼠標(biāo)點擊時刷新頁面。

  在象Gmail那樣的Ajax軟件里,瀏覽器的地址欄正確的停留就象用戶在選擇和改變應(yīng)用的狀態(tài)時,這使得作書簽到特定的應(yīng)用視圖里變得不可能。此外,如果用戶按下了他們的回退按鈕去返回上一個操作,他們會驚奇的發(fā)現(xiàn)瀏覽器將完全離開原來他所在的應(yīng)用的web頁面。

  解決方案

  開源的Really Simply History(RSH)框架解決了這些問題,他帶來了Ajax應(yīng)用的作書簽和控制前進(jìn)后退按鈕的功能。RSH目前還是beta版,在Firefox1.0上,Netscape7及以上,和IE6及以上運行。Safari現(xiàn)在還不支持。

  目前存在的幾個Ajax框架可以幫助我們做書簽和發(fā)布?xì)v史,然而所有的框架都因為他們的實現(xiàn)而被幾個重要的bug困擾。此外,許多Ajax歷史框架集成綁定到較大的庫上,比如Backbase 和 Dojo,這些框架提供了與傳統(tǒng)Ajax應(yīng)用不同的編程模型,強迫開發(fā)者去采用一整套全新的方式去獲得瀏覽器的歷史相關(guān)的功能。

  相應(yīng)的,RSH是一個簡單的模型,能被包含在已經(jīng)存在的Ajax系統(tǒng)中。而且,Really Simple History庫使用了一些技巧去避免影響到其他歷史框架的bug.

  Really Simple History框架由2個javascript類庫組成,分別叫DhtmlHistory 和 HistoryStorage.

  DhtmlHistory 類提供了一個對Ajax應(yīng)用提取歷史的功能。Ajax頁面add() 歷史事件到瀏覽器里,指定新的地址和關(guān)聯(lián)歷史數(shù)據(jù)。DhtmlHistory 類用一個錨的hash表更新瀏覽器現(xiàn)在的URL,比如#new-location ,然后用這個新的URL關(guān)聯(lián)歷史數(shù)據(jù)。Ajax應(yīng)用注冊他們自己到歷史監(jiān)聽器里,然后當(dāng)用戶用前進(jìn)和后退按鈕導(dǎo)航的時候,歷史事件被激發(fā),提供給瀏覽器新的地址和調(diào)用add()持續(xù)保留數(shù)據(jù)。

  第二個類HistoryStorage,允許開發(fā)者存儲任意大小的歷史數(shù)據(jù)。一般的頁面,當(dāng)一個用戶導(dǎo)航到一個新的網(wǎng)站,瀏覽器會卸載和清除所有這個頁面的應(yīng)用和javascript狀態(tài)信息。如果用戶用回退按鈕返回過來了,所有的數(shù)據(jù)已經(jīng)丟失了。HistoryStorage 類解決了這個問題,他有一個api 包含簡單的hashtable方法比如put(),get(),hasKey()。這些方法允許開發(fā)者在離開web頁面時存儲任意大小的數(shù)據(jù),當(dāng)用戶點了回退按鈕返回時,數(shù)據(jù)可以通過HistoryStorage 類被訪問。我們通過一個隱藏的表單域(a hidden form field),利用瀏覽器即使在用戶離開web頁面也會自動保存表單域值的這個特性,完成這個功能。

  讓我們立即進(jìn)入一個簡單的例子吧。

  示例1

  首先,任何一個想使用Really Simple History框架的頁面必須包含(include)dhtmlHistory.js 腳本。
復(fù)制代碼 代碼如下:

!-- Load the Really Simple 
     History framework -->
script type="text/javascript"
        src="../../framework/dhtmlHistory.js">
/script>

DHTML History 應(yīng)用也必須在和AJAX web頁面相同的目錄下包含一個叫blank.html 的指定文件,這個文件被Really Simple History框架綁定而且對IE來說是必需的。另一方面,RSH使用一個hidden iframe 來追蹤和加入IE歷史的改變,為了正確的執(zhí)行功能,這個iframe需要指向一個真正的地址,不需要blank.html。

  RSH框架創(chuàng)建了一個叫dhtmlHistory 的全局對象,作為操作瀏覽器歷史的入口。使用dhtmlHistory 的第一步需要在頁面加載后初始化這個對象。
復(fù)制代碼 代碼如下:

window.onload = initialize; 

function initialize() {
  // initialize the DHTML History
  // framework
  dhtmlHistory.initialize();

然后,開發(fā)者使用dhtmlHistory.addListener()方法去訂閱歷史改變事件。這個方法獲取一個javascript回調(diào)方法,當(dāng)一個DHTML歷史改變事件發(fā)生時他將收到2個自變量,新的頁面地址,和任何可選的而且可以被關(guān)聯(lián)到這個事件的歷史數(shù)據(jù)。
復(fù)制代碼 代碼如下:

window.onload = initialize; 
function initialize() {
  // initialize the DHTML History
  // framework
  dhtmlHistory.initialize();

  // subscribe to DHTML history change
  // events
  dhtmlHistory.addListener(historyChange);

historyChange()方法是簡單易懂得,它是由一個用戶導(dǎo)航到一個新地址后收到的新地址(newLocation)和一個關(guān)聯(lián)到事件的可選的歷史數(shù)據(jù)historyData 構(gòu)成的。
復(fù)制代碼 代碼如下:

/** Our callback to receive history change
     events. */
function historyChange(newLocation, 
                       historyData) {
  debug("A history change has occurred: "
        + "newLocation="+newLocation
        + ", historyData="+historyData, 
        true);
}

上面用到的debug()方法是例子代碼中定義的一個工具函數(shù),在完整的下載例子里有。debug()方法簡單的在web頁面上打一條消息,第2個Boolean變量,在代碼里是true,控制一個新的debug消息打印前是否要清除以前存在的所有消息。

  一個開發(fā)者使用add()方法加入歷史事件。加入一個歷史事件包括根據(jù)歷史的改變指定一個新的地址,就像"edit:SomePage"標(biāo)記, 還提供一個事件發(fā)生時可選的會被存儲到歷史數(shù)據(jù)historyData值.
復(fù)制代碼 代碼如下:

window.onload = initialize; 

function initialize() { 
  // initialize the DHTML History 
  // framework 
  dhtmlHistory.initialize(); 

  // subscribe to DHTML history change 
  // events 
  dhtmlHistory.addListener(historyChange); 

  // if this is the first time we have 
  // loaded the page... 
  if (dhtmlHistory.isFirstLoad()) { 
    debug("Adding values to browser " 
          + "history", false); 
    // start adding history 
    dhtmlHistory.add("helloworld",  
                     "Hello World Data"); 
    dhtmlHistory.add("foobar", 33); 
    dhtmlHistory.add("boobah", true); 

    var complexObject = new Object(); 
    complexObject.value1 =  
                  "This is the first value"; 
    complexObject.value2 =  
                  "This is the second data"; 
    complexObject.value3 = new Array(); 
    complexObject.value3[0] = "array 1"; 
    complexObject.value3[1] = "array 2"; 

    dhtmlHistory.add("complexObject",  
                     complexObject); 

在add()方法被調(diào)用后,新地址立刻被作為一個錨值顯示在用戶的瀏覽器的URL欄里。例如,一個AJAX web頁面停留在http://codinginparadise.org/my_ajax_app,調(diào)用了dhtmlHistory.add("helloworld", "Hello World Data" 后,用戶將在瀏覽器的URL欄里看到下面的地址
復(fù)制代碼 代碼如下:

http://codinginparadise.org/my_ajax_app#helloworld

然后他們可以把這個頁面做成書簽,如果他們使用這個書簽,你的AJAX應(yīng)用可以讀出#helloworld值然后使用她去初始化web頁面。Hash里的地址值被Really Simple History 框架顯式的編碼和解碼(URL encoded and decoded) (這是為了解決字符的編碼問題)

  對當(dāng)AJAX地址改變時保存更多的復(fù)雜的狀態(tài)來說,historyData 比一個更容易的匹配一個URL的東西更有用。他是一個可選的值,可以是任何javascript類型,比如Number, String, 或者 Object 類型。有一個例子是用這個在一個多文本編輯器(rich text editor)保存所有的文本,例如,如果用戶從這個頁面漂移(或者說從這個頁面導(dǎo)航到其他頁面,離開了這個頁面)走。當(dāng)一個用戶再回到這個地址,瀏覽器會把這個對象返回給歷史改變偵聽器(history change listener)。

  開發(fā)者可以提供一個完全的historyData 的javascript對象,用嵌套的對象objects和排列arrays來描繪復(fù)雜的狀態(tài)。只要是JSON (JavaScript Object Notation) 允許的那么在歷史數(shù)據(jù)里就是允許的,包括簡單數(shù)據(jù)類型和null型。DOM的對象和可編程的瀏覽器對象比如XMLHttpRequest ,不會被保存。注意historyData 不會被書簽持久化,如果瀏覽器關(guān)掉,或者瀏覽器的緩存被清空,或者用戶清除歷史的時候,會消失掉。

  使用dhtmlHistory 最后一步,是isFirstLoad() 方法。如果你導(dǎo)航到一個web頁面,再跳到一個不同的頁面,然后按下回退按鈕返回起始的網(wǎng)站,第一頁將完全重新裝載,并激發(fā)onload事件。這樣能產(chǎn)生破壞性,當(dāng)代碼在第一次裝載時想要用某種方式初始化頁面的時候,不會再刷新頁面。isFirstLoad() 方法讓區(qū)別是最開始第一次裝載頁面,還是相對的,在用戶導(dǎo)航回到他自己的瀏覽器歷史中記錄的網(wǎng)頁時激發(fā)load事件,成為可能。

  在例子代碼中,我們只想在第一次頁面裝載的時候加入歷史事件,如果用戶在第一次裝載后,按回退按鈕返回頁面,我們就不想重新加入任何歷史事件。
window.onload = initialize;

function initialize() {
  // initialize the DHTML History
  // framework
  dhtmlHistory.initialize();

  // subscribe to DHTML history change
  // events
  dhtmlHistory.addListener(historyChange);

  // if this is the first time we have
  // loaded the page...
  if (dhtmlHistory.isFirstLoad()) {
    debug("Adding values to browser "
          + "history", false);
    // start adding history
    dhtmlHistory.add("helloworld",
                     "Hello World Data");
    dhtmlHistory.add("foobar", 33);
    dhtmlHistory.add("boobah", true);

    var complexObject = new Object();
    complexObject.value1 =
                  "This is the first value";
    complexObject.value2 =
                  "This is the second data";
    complexObject.value3 = new Array();
    complexObject.value3[0] = "array 1";
    complexObject.value3[1] = "array 2";

    dhtmlHistory.add("complexObject",
                     complexObject);


  讓我們繼續(xù)使用historyStorage 類。類似dhtmlHistory ,historyStorage通過一個叫historyStorage的單一全局對象來顯示他的功能,這個對象有幾個方法來偽裝成一個hash table, 象put(keyName, keyValue), get(keyName), and hasKey(keyName).鍵名必須是字符,同時鍵值可以是復(fù)雜的javascript對象或者甚至是xml格式的字符。在我們源碼source code的例子中,我們put() 簡單的XML 到historyStorage 在頁面第一次裝載時。

程序代碼 程序代碼

window.onload = initialize;

function initialize() {
  // initialize the DHTML History
  // framework
  dhtmlHistory.initialize();

  // subscribe to DHTML history change
  // events
  dhtmlHistory.addListener(historyChange);

  // if this is the first time we have
  // loaded the page...
  if (dhtmlHistory.isFirstLoad()) {
    debug("Adding values to browser "
          + "history", false);
    // start adding history
    dhtmlHistory.add("helloworld",
                     "Hello World Data");
    dhtmlHistory.add("foobar", 33);
    dhtmlHistory.add("boobah", true);

    var complexObject = new Object();
    complexObject.value1 =
                  "This is the first value";
    complexObject.value2 =
                  "This is the second data";
    complexObject.value3 = new Array();
    complexObject.value3[0] = "array 1";
    complexObject.value3[1] = "array 2";

    dhtmlHistory.add("complexObject",
                     complexObject);

    // cache some values in the history
    // storage
    debug("Storing key 'fakeXML' into "
          + "history storage", false);
    var fakeXML =
      '?xml version="1.0" '
      +      'encoding="ISO-8859-1"?>'
      +      'foobar>'
      +         'foo-entry/>'
      +      '/foobar>';
    historyStorage.put("fakeXML", fakeXML);
  }


  然后,如果用戶從這個頁面漂移走(導(dǎo)航走)又通過返回按鈕返回了,我們可以用get()提出我們存儲的值或者用haskey()檢查他是否存在。

程序代碼 程序代碼

window.onload = initialize;

function initialize() {
  // initialize the DHTML History
  // framework
  dhtmlHistory.initialize();

  // subscribe to DHTML history change
  // events
  dhtmlHistory.addListener(historyChange);

  // if this is the first time we have
  // loaded the page...
  if (dhtmlHistory.isFirstLoad()) {
    debug("Adding values to browser "
          + "history", false);
    // start adding history
    dhtmlHistory.add("helloworld",
                     "Hello World Data");
    dhtmlHistory.add("foobar", 33);
    dhtmlHistory.add("boobah", true);

    var complexObject = new Object();
    complexObject.value1 =
                  "This is the first value";
    complexObject.value2 =
                  "This is the second data";
    complexObject.value3 = new Array();
    complexObject.value3[0] = "array 1";
    complexObject.value3[1] = "array 2";

    dhtmlHistory.add("complexObject",
                     complexObject);

    // cache some values in the history
    // storage
    debug("Storing key 'fakeXML' into "
          + "history storage", false);
    var fakeXML =
      '?xml version="1.0" '
      +      'encoding="ISO-8859-1"?>'
      +      'foobar>'
      +         'foo-entry/>'
      +      '/foobar>';
    historyStorage.put("fakeXML", fakeXML);
  }

  // retrieve our values from the history
  // storage
  var savedXML =
              historyStorage.get("fakeXML");
  savedXML = prettyPrintXml(savedXML);
  var hasKey =
           historyStorage.hasKey("fakeXML");
  var message =
    "historyStorage.hasKey('fakeXML')="
    + hasKey + "br>"
    + "historyStorage.get('fakeXML')=br>"
    + savedXML;
  debug(message, false);
}


  prettyPrintXml() 是一個第一在例子源碼full example source code中的工具方法。這個方法準(zhǔn)備簡單的xml顯示在web page ,方便調(diào)試。

  注意數(shù)據(jù)只是在使用頁面的歷史時被持久化,如果瀏覽器關(guān)閉了,或者用戶打開一個新的窗口又再次鍵入了ajax應(yīng)用的地址,歷史數(shù)據(jù)對這些新的web頁面是不可用的。歷史數(shù)據(jù)只有在用前進(jìn)或回退按鈕時才被持久化,而且在用戶關(guān)閉瀏覽器或清空緩存的時候會消失掉。想真正的長時間的持久化,請看Ajax MAssive Storage System (AMASS).

  我們的簡單示例已經(jīng)完成。演示他(Demo it)或者下載全部的源代碼(download the full source code.)

  示例2

  我們的第2個例子是一個簡單的模擬ajax email 應(yīng)用的示例,叫O'Reilly Mail,類似Gmail. O'Reilly Mail描述了怎樣使用dhtmlHistory類去控制瀏覽器的歷史,和怎樣使用historyStorage對象去緩存歷史數(shù)據(jù)。

  O'Reilly Mail 用戶接口(user interface)有兩部分。在頁面的左邊是一個有不同email文件夾和選項的菜單,例如 收件箱,草稿,等等。當(dāng)一個用戶選擇了一個菜單項,比如收件箱,我們用這個菜單項的內(nèi)容更新右邊的頁面。在一個實際應(yīng)用中,我們會遠(yuǎn)程取得和顯示選擇的信箱內(nèi)容,不過在O'Reilly Mail里,我們簡單的顯示選擇的選項。

  O'Reilly Mail使用Really Simple History 框架向瀏覽器歷史里加入菜單變化和更新地址欄,允許用戶利用瀏覽器的回退和前進(jìn)按鈕對應(yīng)用做書簽和跳到上一個變化的菜單。

  我們加入一個特別的菜單項,地址簿,來描繪historyStorage 能夠怎樣被使用。地址簿是一個由聯(lián)系的名字電子郵件和地址組成的javascript數(shù)組,在一個真實的應(yīng)用里我們會取得他從一個遠(yuǎn)程的服務(wù)器。不過,在O'Reilly Mail里,我們在本地創(chuàng)建這個數(shù)組,加入幾個名字電子郵件和地址,然后把他們存儲在historyStorage 對象里。如果用戶離開了這個web頁面以后又返回的話,O'Reilly Mail應(yīng)用重新從緩存里得到地址簿,勝過(不得不)再次訪問遠(yuǎn)程服務(wù)器。

  地址簿是在我們的初始化initialize()方法里存儲和重新取得的
程序代碼 程序代碼

/** Our function that initializes when the page
    is finished loading. */
function initialize() {
   // initialize the DHTML History framework
   dhtmlHistory.initialize();

   // add ourselves as a DHTML History listener
   dhtmlHistory.addListener(handleHistoryChange);

   // if we haven't retrieved the address book
   // yet, grab it and then cache it into our
   // history storage
   if (window.addressBook == undefined) {
      // Store the address book as a global
      // object.
      // In a real application we would remotely
      // fetch this from a server in the
      // background.
      window.addressBook =
         ["Brad Neuberg 'bkn3@columbia.edu'",
          "John Doe 'johndoe@example.com'",
          "Deanna Neuberg 'mom@mom.com'"];

      // cache the address book so it exists
      // even if the user leaves the page and
      // then returns with the back button
      historyStorage.put("addressBook",
                         addressBook);
   }
   else {
      // fetch the cached address book from
      // the history storage
      window.addressBook =
               historyStorage.get("addressBook");
   }


  處理歷史變化的代碼是簡單的。在下面的代碼中,當(dāng)用戶不論按下回退還是前進(jìn)按鈕handleHistoryChange 都被調(diào)用。我們得到新的地址(newLocation) 使用他更新我們的用戶接口來改變狀態(tài),通過使用一個叫displayLocation的O'Reilly Mail的工具方法。

程序代碼 程序代碼

** Handles history change events. */
function handleHistoryChange(newLocation,
                             historyData) {
   // if there is no location then display
   // the default, which is the inbox
   if (newLocation == "") {
      newLocation = "section:inbox";
   }

   // extract the section to display from
   // the location change; newLocation will
   // begin with the word "section:"
   newLocation =
         newLocation.replace(/section\:/, "");

   // update the browser to respond to this
   // DHTML history change
   displayLocation(newLocation, historyData);
}

/** Displays the given location in the
    right-hand side content area. */
function displayLocation(newLocation,
                         sectionData) {
   // get the menu element that was selected
   var selectedElement =
            document.getElementById(newLocation);

   // clear out the old selected menu item
   var menu = document.getElementById("menu");
   for (var i = 0; i menu.childNodes.length;
                                          i++) {
      var currentElement = menu.childNodes[i];
      // see if this is a DOM Element node
      if (currentElement.nodeType == 1) {
         // clear any class name
         currentElement.className = "";
      }                                      
   }

   // cause the new selected menu item to
   // appear differently in the UI
   selectedElement.className = "selected";

   // display the new section in the right-hand
   // side of the screen; determine what
   // our sectionData is

   // display the address book differently by
   // using our local address data we cached
   // earlier
   if (newLocation == "addressbook") {
      // format and display the address book
      sectionData = "p>Your addressbook:/p>";
      sectionData += "ul>";

      // fetch the address book from the cache
      // if we don't have it yet
      if (window.addressBook == undefined) {
         window.addressBook =
               historyStorage.get("addressBook");
      }

      // format the address book for display
      for (var i = 0;
               i window.addressBook.length;
                     i++) {
         sectionData += "li>"
                        + window.addressBook[i]
                        + "/li>";                  
      }

      sectionData += "/ul>";
   }

   // If there is no sectionData, then
   // remotely retrieve it; in this example
   // we use fake data for everything but the
   // address book
   if (sectionData == null) {
      // in a real application we would remotely
      // fetch this section's content
      sectionData = "p>This is section: "
         + selectedElement.innerHTML + "/p>";  
   }

   // update the content's title and main text
   var contentTitle =
         document.getElementById("content-title");
   var contentValue =
         document.getElementById("content-value");
   contentTitle.innerHTML =
                        selectedElement.innerHTML;
   contentValue.innerHTML = sectionData;
}


  演示(Demo)O'Reilly Mail或者下載(download)O'Reilly Mail的源代碼。

  結(jié)束語

  你現(xiàn)在已經(jīng)學(xué)習(xí)了使用Really Simple History API 讓你的AJAX應(yīng)用響應(yīng)書簽和前進(jìn)回退按鈕,而且有代碼可以作為創(chuàng)建你自己的應(yīng)用的素材。我熱切地期待你利用書簽和歷史的支持完成你的AJAX創(chuàng)造。

版權(quán)聲明:Techtarget獲Matrix授權(quán)發(fā)布,如需轉(zhuǎn)載請聯(lián)系Matrix
作者:Brad Neuberg;boool
原文地址:http://www.onjava.com/pub/a/onjava/2005/10/26/ajax-handling-bookmarks-and-back-button.html
中文地址:http://www.matrix.org.cn/resource/article/43/43972_AJAX.html

資源

·onjava.com:onjava.com

·Matrix-Java開發(fā)者社區(qū):http://www.matrix.org.cn/

·Download all sample code for this article.
http://www.onjava.com/onjava/2005/10/26/examples/downloads/examples.zip

·Download the Really Simple History framework.
http://codinginparadise.org/projects/dhtml_history/latest.zip

·Demo O'Reilly Mail or download the O'Reilly Mail source code. The full example download also includes more examples for you to play with.

·Coding in Paradise: The author's weblog, covering AJAX, DHTML, and Java techniques and new developments in collaborative technologies, such as WikiWikis.
http://codinginparadise.org/

感謝
特別的要感謝每個檢閱這篇文章的the Really Simple History框架的人:
Michael Eakes, Jeremy Sevareid, David Barrett, Brendon Wilson, Dylan Parker, Erik Arvidsson, Alex Russell, Adam Fisk, Alex Lynch, Joseph Hoang Do, Richard MacManus, Garret Wilson, Ray Baxter, Chris Messina, and David Weekly.

標(biāo)簽:崇左 伊春 銅川 西藏 晉城 深圳 威海 撫州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《用Ajax來控制書簽和回退按鈕的代碼》,本文關(guān)鍵詞  用,Ajax,來,控制,書簽,和,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《用Ajax來控制書簽和回退按鈕的代碼》相關(guān)的同類信息!
  • 本頁收集關(guān)于用Ajax來控制書簽和回退按鈕的代碼的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章