整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JQuery實現瀏覽器點擊后退,iframe頁面空白

          JQuery實現瀏覽器點擊后退,iframe頁面空白處理

          frame頁面在點擊瀏覽器后退功能后,直接空白,體驗不佳!

          ------處理方案如下------

          在對應的JSP頁面中直接加上:

          $(document).ready(function($) {

          if (window.history && window.history.pushState)

          {

          $(window).on('popstate', function ()

          {

          var hashLocation=location.hash;

          var hashSplit=hashLocation.split("#!/");

          var hashName=hashSplit[1];

          if (hashName !=='')

          {

          var hash=window.location.hash;

          if (hash==='')

          {

          //在瀏覽器點擊后退時,固定在當前頁

          window.history.pushState('forward', null, '');

          return;

          }

          }

          });

          window.history.pushState('forward', null, '');

          }

          });

          2年之前碰到的處理方案,希望對大家有用。

          、跨域請求痛點

          最近網站新增了一個域名B用于分離不同的功能。但是需要復用服務器的高防等服務,但是服務和原有域名A綁定,所以新域名B需要直接去調用域名A。

          一開始想使用CNAME的方式,讓B直接指向A。但是Https支持性有點問題,需要多域名證書。也考慮過反向代理,但是代理服務器的性能和高防等又是一個問題。

          最終決定在域名B的網頁中,所有請求都直接去調用域名A的接口。于是就遇到了跨域請求的問題。

          二、跨域請求的實現方式

          網上找了許多資料來實現跨域請求。最終預估下來,有兩種方案比較靠譜:通過iframe實現和CORS方案

          三、通過iframe實現

          初步設想是加載一個域名A的iframe頁面,然后通過postMessage將所有Ajax請求,轉發給這個頁面,通過這個頁面來進行請求,最終將結果通過postMessage回發給外層的域名B頁面。

          于是開始實現:

          前端使用的是React,所以實現了一個FrameHttp.js專門用法封裝ajax調用。調用FrameHttp.ajax將所有外部Jquery請求轉發給iframe中域名A的/util/ajaxrequest頁面。

          import Tools from "../Tools"
          
          const FrameHttpCmd={
              INIT: 1,
              REQUEST: 2,
              REQUEST_CALLBACK: 3,
          }
          
          class FrameHttp {
              static isInit=false
              static _request_buffer=[]
              static frame=null
              static message_key=0
              static message_key_max=10000000
              static request_map={}
          
              static init(domain) {
                  var the_frame=document.createElement('iframe')
                  let url_obj=new URL(domain)
                  url_obj.pathname=Tools.getUrl('/util/ajaxrequest')
                  the_frame.src=url_obj.toString()
                  the_frame.style.visibility='hidden'
                  the_frame.style.position='absolute'
                  the_frame.style.width=0
                  the_frame.style.height=0
          
                  FrameHttp.frame=the_frame
                  document.body.appendChild(the_frame)
                  window.addEventListener('message', this.onMessage)
              }
          
              static _initFrame() {
                  FrameHttp.isInit=true
                  console.log('(INFO)FrameHttp._initFrame')
                  for (let i=0; i < FrameHttp._request_buffer.length; i++) {
                      let arg=FrameHttp._request_buffer[i]
                      FrameHttp.ajax(arg)
                  }
                  FrameHttp._request_buffer=[]
              }
          
              static getMessageKey() {
                  let message_key=FrameHttp.message_key
                  FrameHttp.message_key=(FrameHttp.message_key+1)%FrameHttp.message_key_max 
                  return message_key
              }
          
              static ajax(arg) {
                  if (FrameHttp.isInit) {
                      // console.log(arg)
                      const { success, error, ...others }=arg
                      let message_key=FrameHttp.getMessageKey()
                      FrameHttp.request_map[message_key]={ success, error }
                      FrameHttp.frame.contentWindow.postMessage({
                          cmd: FrameHttpCmd.REQUEST,
                          data: others,
                          key: message_key,
                      }, '*')
                      console.log('(INFO)FrameHttp.ajax', others)
                  }
                  else {
                      FrameHttp._request_buffer.push(arg)
                      console.log('(INFO)FrameHttp.ajax:push buffer')
                  }
              }
          
              static onMessage(e) {
                  const { data }=e
                  if (data.cmd==FrameHttpCmd.INIT) {
                      FrameHttp._initFrame()
                  }
                  else if (data.cmd==FrameHttpCmd.REQUEST_CALLBACK) {
                      // console.log(data.key, data.success)
                      let item=FrameHttp.request_map[data.key]
                      if (data.error) {
                          if (item.error) {
                              item.error(data.error)
                          }
                      }
                      else {
                          if (item.success) {
                              item.success(data.success)
                          }
                      }
                      delete FrameHttp.request_map[data.key]
                  }
              }
          }
          
          export default FrameHttp
          export { FrameHttpCmd }
          

          然后域名A中的/util/ajaxrequest頁面處理請求:

          import React, { Component } from 'react'
          import { FrameHttpCmd } from '../../../common_js/web_frame/FrameHttp'
          import jquery from '../../../common_js/jquery.min'
          
          class AjaxRequest extends Component {
              constructor(props) {
                  super(props)
          
                  this.onMessage=this.onMessage.bind(this)
              }
          
              onMessage(e) {
                  const { cmd, data, key, cookie }=e.data
                  if (cmd==FrameHttpCmd.REQUEST) {
                      // console.log(key, data)
                      console.log(document.cookie)
                      jquery.ajax({
                          ...data,
                          success: (data)=>{
                              window.parent.postMessage({
                                  cmd: FrameHttpCmd.REQUEST_CALLBACK,
                                  key,
                                  success: data,
                              }, '*')
                          },
                          error: ()=>{
                              window.parent.postMessage({
                                  cmd: FrameHttpCmd.REQUEST_CALLBACK,
                                  key,
                                  error: 'error',
                              }, '*')
                          },
                      })
                  }
              }
          
              componentDidMount() {
                  window.parent.postMessage({
                      cmd: FrameHttpCmd.INIT,
                  }, '*')
                  window.addEventListener('message', this.onMessage)
              }
          
              render() {
                  return null
              }
          }
                          
          export default AjaxRequest
          

          如此實現后,發現iframe因為跨域問題無法加載

          因為后端是由Django實現的,經過查閱發現,在views中需要進行處理,添加xframe_options_exempt裝飾器,實現跨域加載iframe。

          @xframe_options_exempt
          def indexCross(request, *args, **kwargs):
              return render(request, 'index.html', {})
          

          功能能夠正常請求,但是請求中cookie并沒有正常傳送。

          經過排查發現,對于跨域的iframe,google瀏覽器默認對于cookie中SameSite這個參數是LAX,會導致只有同源才能設置服務器返回的Set-Cookie。所以需要將服務器返回的Set-Cookie中指定SameSite為None,這樣前端才能成功設置Cookie。

          于是服務端Django引入了中間件django-cookies-samesite。settings.py進行如下修改:

          INSTALLED_APPS=[
              ...
              'corsheaders',
              ...
          ]
          
          # 中間件request按照注冊順序順序執行,response按照注冊順序倒序執行
          MIDDLEWARE=[
              'django_cookies_samesite.middleware.CookiesSameSite', # 此處response需要最后執行
              ...
          ]
          
          SESSION_COOKIE_SECURE=True
          SESSION_COOKIE_SAMESITE='None'
          

          至此實現了iframe方式跨域。

          四、CORS方案

          這個需要前端Jquery加入兩個參數:

          jquery.ajax({
              ...
              xhrFields: {
                  withCredentials: true
              },
              crossDomain: true,
          })
          

          然后服務端需要開啟跨域請求支持。Django下引入中間件django-cors-headers。settings.py下如下設置:

          MIDDLEWARE=[
              ...
              'corsheaders.middleware.CorsMiddleware', # 這個位置越高越好,至少要高于CommonMiddleware
              ...
          ]
          
          # 跨域配置
          CORS_ALLOW_CREDENTIALS=True
          # CORS_ORIGIN_ALLOW_ALL=True
          CORS_ORIGIN_WHITELIST=[
              'https://www.xxx.com',# 域名B
          ]
          CORS_ALLOW_METHODS=[
              'DELETE',
              'GET',
              'OPTIONS',
              'PATCH',
              'POST',
              'PUT',
              'VIEW',
          ]
          CORS_ALLOW_HEADERS=[
              'XMLHttpRequest',
              'X_FILENAME',
              'accept-encoding',
              'authorization',
              'content-type',
              'dnt',
              'origin',
              'user-agent',
              'x-csrftoken',
              'x-requested-with',
              'Pragma',
              'cache-control',
          ]
          

          此方案也需要和iframe一樣,解決cookie中SameSite的問題。

          至此CORS方案跨域也實現了。

          最近在項目中遇到了一個需要動態添加 select option 選項的問題,大概功能就是iframe不同子頁面之間,將iframe3選中的checkbox內容作為iframe4中一個select下拉框的選項。上網查閱資料后發現有js實現的,也有jquery實現的,根據自己的要求我"添加"采用js方式實現,"刪除"采用jquery方式實現(js也可以實現刪除,是根據選中內容的索引下標實現的),根據自己的實際需求我選擇了jquery,其中有個方法是根據value值刪除的。

          1.js動態添加option

          2.jquery 動態刪除option

          根據value值刪除option

          3.js動態刪除option

          根據下標索引刪除option

          4.js刪除所有option

          刪除所有option

          上面提及到了iframe,實際項目中獲取select元素id不是這么簡單,這里是簡化了只是為了說明添加和刪除option。下面總結下常見的幾種iframe子頁面與子頁面以及子頁面與父頁面之間如何取值,希望可以幫助跟我之前一樣取不到值而困惑的朋友哈。這里假設有irame1和iframe2子頁面。

          1.父頁面獲取子頁面的值

          2.子頁面獲取父頁面的值,并賦值(子頁面操作父頁面)

          3.兩個子頁面相互操作(iframe1操作iframe2)

          以上都是js獲取的方法,還有jquery的方式,方法不一樣,基礎原理都是一樣的,父頁面可以拿到子頁面的值,子頁面之間不能之間取值,子頁面要先通過父頁面元素拿到其他子頁面iframe Id,再去訪問其他子頁面的元素。

          jquery不同ifame之間取值

          哪里寫的不妥的地方,歡迎大家在評論提出你的意見或建議哈。


          主站蜘蛛池模板: 精品性影院一区二区三区内射| 一区二区三区高清| 亚洲熟女乱综合一区二区| 久久国产免费一区二区三区| 老熟妇仑乱视频一区二区| 亚洲片国产一区一级在线观看| 亚洲国产老鸭窝一区二区三区| 韩国一区二区三区| 亚洲视频免费一区| 精品日产一区二区三区手机| 中文无码精品一区二区三区| av在线亚洲欧洲日产一区二区| 美女视频一区二区三区| 成人免费一区二区无码视频| 在线观看一区二区精品视频| 精品视频无码一区二区三区 | 在线观看国产区亚洲一区成人| 日韩精品一区二区三区毛片| 毛片无码一区二区三区a片视频 | 无码视频一区二区三区| 无码人妻一区二区三区免费| 亚洲第一区视频在线观看| 无码精品黑人一区二区三区| 亚洲综合无码AV一区二区| 一区二区乱子伦在线播放| 亚洲一区在线免费观看| 一区二区三区午夜视频| 国产精品区一区二区三在线播放 | 精品国产一区二区三区久久蜜臀 | 亚洲一区二区三区国产精华液| 亚洲va乱码一区二区三区| 中文字幕无线码一区二区| 中文字幕一区二区三区在线观看 | 玩弄放荡人妻一区二区三区| 毛片一区二区三区无码| 一区二区三区在线视频播放| 一区二区三区四区在线观看视频| 无码人妻精品一区二区三区99不卡| 一区二区三区视频免费观看 | 免费视频一区二区| 亚洲精品一区二区三区四区乱码|