久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      Javascript PJAX 原理和使用

      Javascript PJAX 原理和使用

      pjax 即 pushState + ajax,它被封裝成了一個(gè) jQuery 擴(kuò)展以方便使用。pjax 主要用來解決 HTML 頁面局部刷新 url 不更新和不支持后退和前進(jìn)的問題,提升用戶體驗(yàn)。

      pjax原理

      pjax 的實(shí)現(xiàn)是利用 HTML5 的 pushState() 和 replaceState() 新特性和 ajax 結(jié)合實(shí)現(xiàn)。pushState() 和 replaceState() 用來操作 State(狀態(tài))對象,即可添加和修改歷史記錄,進(jìn)而更新 url 和提供前進(jìn)、后退操作 ajax 實(shí)現(xiàn)數(shù)據(jù)的異步加載進(jìn)而局部刷新。

      工作流程圖

      Javascript PJAX 原理和使用

      源碼分析

      • pjax支持判斷
      (function($){     $.support.pjax =        window.history && window.history.pushState && window.history.replaceState &&        // pushState isn't reliable on iOS until 5.        !navigator.userAgent.match(/((iPod|iPhone|iPad).+bOSs+[1-4]D|WebApps/.+CFNetwork)/)     if ($.support.pjax){        enable()   //啟用     } else {        disable()  //禁用     } })(jQuery)
      • enable()
      function enable() {     $.fn.pjax = fnPjax             //注冊jQuery的pjax方法     $.pjax = pjax                  //注冊pjax對象     $.pjax.enable = $.noop     $.pjax.disable = disable     $.pjax.click = handleClick     //注冊click回調(diào)     $.pjax.submit = handleSubmit   //注冊submit回調(diào)     $.pjax.reload = pjaxReload     //注冊reload回調(diào)     $.pjax.defaults = {}           //設(shè)置默認(rèn)值     $(window).on('popstate.pjax', onPjaxPopstate)  //綁定popstate事件回調(diào) }

      $.noop是一個(gè)空方法,不做任何事,即function(){}popstate.pjax是 JS 事件的命名空間寫法,popstate是事件類型,每當(dāng)激活的歷史記錄發(fā)生變化時(shí)(瀏覽器操作前進(jìn)、后退按鈕、調(diào)用 back() 或者 go() 方法),都會(huì)觸發(fā) popstate 事件,但調(diào)用 pushState()、replaceState() 不會(huì)觸發(fā) popstate 事件。.pjax是該事件的命名空間,這樣方便解綁指定命名空間的事件響應(yīng),在綁定匿名函數(shù)時(shí)常使用,例如:this.on('click.pjax', selector, function(event){})。

      • fnPjax()

      該方法返回一個(gè) jQuery 對象,等同于 $.fn.pjax。

      return this.on('click.pjax', selector, function(event) {     //獲取pjax配置信息     options = optionsFor(container, options)     //自動(dòng)綁定click事件響應(yīng)     return this.on('click.pjax', selector, function(event) {        var opts = options        if (!opts.container) {            opts = $.extend({}, options)            //如果不配置container,則默認(rèn)獲取data-pjax屬性值對應(yīng)的            opts.container = $(this).attr('data-pjax')        }        handleClick(event, opts)     //調(diào)用click回調(diào)     }) }
      • pjax()
      // Use it just like $.ajax: // //   var xhr = $.pjax({ url: this.href, container: '#main' }) //   console.log( xhr.readyState ) // // Returns whatever $.ajax returns. function pjax(options) {     //獲取設(shè)置     options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)     //判斷檢測     if (containerType !== 'string')        /**      * ajax響應(yīng)回調(diào)注冊      */     //beforeSend     options.beforeSend = function(xhr, settings) {         //設(shè)置pjax頭信息,供后端做兼容處理         xhr.setRequestHeader('X-PJAX', 'true')         xhr.setRequestHeader('X-PJAX-Container', options.container)         //設(shè)置超時(shí)     }     //complete     options.complete = function(xhr, textStatus) {        //綁定pjax:complete事件        fire('pjax:complete', [xhr, textStatus, options])        //綁定pjax:end事件        fire('pjax:end', [xhr, options])     }     //error     options.error = function(xhr, textStatus, errorThrown) {        //綁定pjax:error事件        fire('pjax:error', [xhr, textStatus, errorThrown, options])     }     //success,重點(diǎn)     options.success = function(data, status, xhr) {        //判斷檢測        if (currentVersion && latestVersion && currentVersion !== latestVersion)        ... ...        window.history.replaceState(pjax.state, container.title, container.url)        //綁定pjax:beforeReplace事件        fire('pjax:beforeReplace', [container.contents, options], {            state: pjax.state,            previousState: previousState        })        //渲染頁面        context.html(container.contents)        //綁定pjax:success事件        fire('pjax:success', [data, status, xhr, options])     }     //初始化ajax     var xhr = pjax.xhr = $.ajax(options)     if (xhr.readyState > 0) {        //緩存頁面cache        cachePush(pjax.state.id, [options.container, cloneContents(context)])        //pushState        window.history.pushState(null, "", options.requestUrl)        //綁定pjax:start事件        fire('pjax:start', [xhr, options])        //綁定pjax:send事件        fire('pjax:send', [xhr, options])     }     //返回jQuery對象     return pjax.xhr }
      • 回調(diào)函數(shù)

      1) handleClick()

      // Examples // //   $(document).on('click', 'a', $.pjax.click) //   // is the same as //   $(document).pjax('a') // // Returns nothing. function handleClick(event, container, options) {     options = optionsFor(container, options)     //環(huán)境檢測     if (link.tagName.toUpperCase() !== 'A')     ... ...     //綁定pjax:click事件     var clickEvent = $.Event('pjax:click')     $link.trigger(clickEvent, [opts])     //執(zhí)行pjax     pjax(opts)     //成功則阻止默認(rèn)行為     event.preventDefault()     //綁定pjax:clicked事件     $link.trigger('pjax:clicked', [opts]) }

      2)handleSubmit()

      // Examples // //  $(document).on('submit', 'form', function(event) { //    $.pjax.submit(event, '[data-pjax-container]') //  }) // // Returns nothing. function handleSubmit(event, container, options) {     options = optionsFor(container, options)     //環(huán)境檢測     if (form.tagName.toUpperCase() !== 'FORM')     ... ...     //默認(rèn)配置     var defaults = {         type: ($form.attr('method') || 'GET').toUpperCase(),         url: $form.attr('action'),         container: $form.attr('data-pjax'),         target: form     }     if (defaults.type !== 'GET' && window.FormData !== undefined) {         //POST時(shí)data域         defaults.data = new FormData(form)     }     //執(zhí)行pjax     pjax($.extend({}, defaults, options))     //成功則阻止默認(rèn)行為     event.preventDefault() }

      3)pjaxReload()

      // Reload current page with pjax. function pjaxReload(container, options) {     var defaults = {         //當(dāng)前url         url: window.location.href,         push: false,         replace: true,         scrollTo: false     }     //執(zhí)行pjax     return pjax($.extend(defaults, optionsFor(container, options))) }

      4)onPjaxPopstate()

      // popstate handler takes care of the back and forward buttons function onPjaxPopstate(event) {      //環(huán)境監(jiān)測      if (state && state.container)      ... ...      //獲取頁面cache      var cache = cacheMapping[state.id] || []      //綁定pjax:popstate事件      var popstateEvent = $.Event('pjax:popstate', {          state: state,          direction: direction      })      container.trigger(popstateEvent)      if (contents) {          //有頁面cache,直接渲染頁面          //綁定pjax:start事件      container.trigger('pjax:start', [null, options])      //綁定pjax:beforeReplace事件      var beforeReplaceEvent = $.Event('pjax:beforeReplace', {               state: state,               previousState: previousState          })          container.trigger(beforeReplaceEvent, [contents, options])          //渲染頁面          container.html(contents)          //綁定pjax:end事件          container.trigger('pjax:end', [null, options])      } else {          //無頁面cache,執(zhí)行pjax          pjax(options)      } }

      pjax使用

      經(jīng)過上述分析,就可以很容易使用 pjax 了。

      客戶端

      pjax 支持 options 配置和事件機(jī)制。

      • options配置
      參數(shù)名 默認(rèn)值 說明
      timeout 650 ajax 超時(shí)時(shí)間(單位 ms),超時(shí)后會(huì)執(zhí)行默認(rèn)的頁面跳轉(zhuǎn),所以超時(shí)時(shí)間不應(yīng)過短,不過一般不需要設(shè)置
      push true 使用 window.history.pushState 改變地址欄 url(會(huì)添加新的歷史記錄)
      replace false 使用 window.history.replaceState 改變地址欄 url(不會(huì)添加歷史記錄)
      maxCacheLength 20 緩存的歷史頁面?zhèn)€數(shù)(pjax 加載新頁面前會(huì)把原頁面的內(nèi)容緩存起來,緩存加載后其中的腳本會(huì)再次執(zhí)行)
      version 是一個(gè)函數(shù),返回當(dāng)前頁面的 pjax-version,即頁面中 標(biāo)簽內(nèi)容。使用 response.setHeader(“X-PJAX-Version”, “”) 設(shè)置與當(dāng)前頁面不同的版本號,可強(qiáng)制頁面跳轉(zhuǎn)而不是局部刷新
      scrollTo 0 頁面加載后垂直滾動(dòng)距離(與原頁面保持一致可使過度效果更平滑)
      type “GET” ajax 的參數(shù),http 請求方式
      dataType “html” ajax 的參數(shù),響應(yīng)內(nèi)容的 Content-Type
      container 用于查找容器的 CSS 選擇器,[container] 參數(shù)沒有指定時(shí)使用
      url link.href 要跳轉(zhuǎn)的連接,默認(rèn) a 標(biāo)簽的 href 屬性
      fragment 使用響應(yīng)內(nèi)容的指定部分(css 選擇器)填充頁面,服務(wù)端不進(jìn)行處理導(dǎo)致全頁面請求的時(shí)候需要使用該參數(shù),簡單的說就是對請求到的頁面做截取
      • pjax事件

      為了方便擴(kuò)展,pjax 支持一些預(yù)定義的事件。

      事件名 支持取消 參數(shù) 說明
      pjax:click options 點(diǎn)擊按鈕時(shí)觸發(fā)??烧{(diào)用 e.preventDefault() 取消 pjaxa
      pjax:beforeSend xhr, options ajax 執(zhí)行 beforeSend 函數(shù)時(shí)觸發(fā),可在回調(diào)函數(shù)中設(shè)置額外的請求頭參數(shù)??烧{(diào)用 e.preventDefault() 取消 pjax
      pjax:start xhr, options pjax 開始(與服務(wù)器連接建立后觸發(fā))
      pjax:send xhr, options pjax:start之后觸發(fā)
      pjax:clicked options ajax 請求開始后觸發(fā)
      pjax:beforeReplace contents, options ajax請求成功,內(nèi)容替換渲染前觸發(fā)
      pjax:success data, status, xhr, options 內(nèi)容替換成功后觸發(fā)
      pjax:timeout xhr, options ajax 請求超時(shí)后觸發(fā)。可調(diào)用 e.preventDefault() 繼續(xù)等待 ajax 請求結(jié)束
      pjax:error xhr, textStatus, error, options ajax 請求失敗后觸發(fā)。默認(rèn)失敗后會(huì)跳轉(zhuǎn) url,如要阻止跳轉(zhuǎn)可調(diào)用 e.preventDefault()
      pjax:complete xhr, textStatus, options ajax請求結(jié)束后觸發(fā),不管成功還是失敗
      pjax:end xhr, options pjax所有事件結(jié)束后觸發(fā)
      pjax:popstate forward / back(前進(jìn)/后退)
      pjax:start null, options pjax開始
      pjax:beforeReplace contents, options 內(nèi)容替換渲染前觸發(fā),如果緩存了要導(dǎo)航頁面的內(nèi)容則使用緩存,否則使用pjax加載
      pjax:end null, options pjax結(jié)束

      客戶端通過以下 2 個(gè)步驟就可以使用 pjax :

      1. 引入jquery 和 jquery.pjax.js
      2. 注冊事件

      JS

      <script src="jquery.pjax.js"></script>  /**  * 方式1 監(jiān)聽按鈕父節(jié)點(diǎn)事件  */ $(document).pjax(selector, [container], options); /**  * 方式2 直接監(jiān)聽按鈕,可以不用指定容器,默認(rèn)使用按鈕的data-pjax屬性值查找容器  */ $("a[data-pjax]").pjax(); /**  * 方式3 主動(dòng)綁定點(diǎn)擊事件監(jiān)聽  */ $(document).on('click', 'a', $.pjax.click); $(document).on('click', 'a', function(event) {     //獲取container     var container = $(this).closest('[data-pjax-container]');     //click回調(diào)     $.pjax.click(event, container); }); /**  * 方式4 主動(dòng)綁定表單提交事件監(jiān)聽  */ $(document).on('submit', 'form', function(event) {     //獲取container     var container = $(this).closest('[data-pjax-container]');     //submit回調(diào)     $.pjax.submit(event, container); }); /**  * 方式5 加載內(nèi)容到指定容器  */ $.pjax({url: this.href, container: '#main'}); /**  * 方式6 重新加載當(dāng)前頁面容器的內(nèi)容  */ $.pjax.reload('#container');

      YII

      在 Yii 中,已經(jīng)將 pjax 封裝成了 widgets,故在渲染時(shí)如下使用即可:

      //view <?php Pjax::begin(); ?> ... ... <?php Pjax::end(); ?>

      pjax 封裝成的 widgets 源碼文件widgets/Pjax.php ,事件注冊部分如下:

      public function registerClientScript() {     //a標(biāo)簽的click     if ($this->linkSelector !== false) {         $linkSelector = Json::htmlEncode($this->linkSelector !== null ? $this->linkSelector : '#' . $id . ' a');         $js .= "jQuery(document).pjax($linkSelector, "#$id", $options);";     }     //form表單的submit     if ($this->formSelector !== false) {         $formSelector = Json::htmlEncode($this->formSelector !== null ? $this->formSelector : '#' . $id . ' form[data-pjax]');         $submitEvent = Json::htmlEncode($this->submitEvent);         $js .= "njQuery(document).on($submitEvent, $formSelector, function (event) {jQuery.pjax.submit(event, '#$id', $options);});";     }     $view->registerJs($js); }

      服務(wù)端

      由于只是 HTML5 支持 pjax,所以后端需要做兼容處理。通過 X-PJAX 頭信息可得知客戶端是否支持 pjax,如果支持,則只返回局部頁面,否則 a 鏈接默認(rèn)跳轉(zhuǎn),返回整個(gè)頁面。

      /**  * IndexController示例  */ public function actionIndex() {     $dataProvider = new CActiveDataProvider('Article', array(         'criteria' => array('order' => 'create_time DESC')     ));     //存在X-Pjax頭,支持pjax     if (Yii::$app->getRequest()->getHeaders()->get('X-Pjax')) {         //返回局部頁面         $this->renderPartial('index', array(             'dataProvider' => $dataProvider,         ));     } else {         //返回整個(gè)頁面         $this->render('index', array(             'dataProvider' => $dataProvider,         ));     } }

      pjax失效情況

      在以下 9 種情況時(shí)候 pjax 會(huì)失效,源碼部分如下:

      //click回調(diào) function handleClick(event, container, options) {     ...     // 1. 點(diǎn)擊的事件源不是a標(biāo)簽。a標(biāo)簽可以對舊版本瀏覽器的兼容,因此不建議使用其他標(biāo)簽注冊事件     if (link.tagName.toUpperCase() !== 'A')         throw "$.fn.pjax or $.pjax.click requires an anchor element"     // 2. 使用鼠標(biāo)滾輪點(diǎn)擊、點(diǎn)擊超鏈接的同時(shí)按下Shift、Ctrl、Alt和Meta     if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)         return     // 3. 跨域     if (location.protocol !== link.protocol || location.hostname !== link.hostname)         return     // 4. 當(dāng)前頁面的錨點(diǎn)定位     if (link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location))         return     // 5. 已經(jīng)阻止元素發(fā)生默認(rèn)的行為     if (event.isDefaultPrevented())         return     ...     var clickEvent = $.Event('pjax:click')     $(link).trigger(clickEvent, [opts])     // 6. pjax:click事件回調(diào)中已經(jīng)阻止元素發(fā)生默認(rèn)的行為     if (!clickEvent.isDefaultPrevented()) {         pjax(opts)     } } //pjax function pjax(options) {     options.beforeSend = function(xhr, settings) {         //7. ajx超時(shí)        timeoutTimer = setTimeout(function() {        if (fire('pjax:timeout', [xhr, options]))            xhr.abort('timeout')        }, settings.timeout)     }     options.success = function(data, status, xhr) {     //8. 當(dāng)前頁面和請求的新頁面版本不一致     if (currentVersion && latestVersion && currentVersion !== latestVersion) {        return     }     //9. ajax失敗     context.html(container.contents) }

      其他方案

      除了使用 pjax 解決局部刷新并支持前進(jìn)和后退問題外,也可以使用 browserstate/history.js + ajax 方案來實(shí)現(xiàn)

      推薦教程:《PHP》《JS教程》

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號