zoukankan      html  css  js  c++  java
  • ✅问题:Rails.ajax的data不支持{}hash格式。必须使用string。 dataType的格式。

    Rails.ajax({
      url: url,
      type: "PATCH",
      data: {"post":{"category_id":this.value}},
      dataType: "json"
    })

    不支持这个格式,不会传递参数。

    $.ajax仍然可以使用。并可以用data: {"post":{"category_id":this.value}}传递参数。


    解决记录:

    昨天晚上2小时

    成本:昨天一晚上2小时无解,参数就是不能上传,有点烦躁。

    收获:chrome-inpector使用熟练度上升。

    今天早上2小时

    非时间成本:无。

    收获:学习源码,理解Rail.ajax的过程。确认必须使用string格式上传data。

    偶然发现解决了问题

    使用$.ajax的传统写法data: {"post":{"category_id":this.value}}, 成功后,看了一眼header的最下面有一个Form Data(1)

    点击出现:

    Form Data 

    post[category_id]: 4 
    我猜测应该使用"post[category_id]: 4 " 作为data的值,测试后,成功!
     
    再回顾,发现了旁边还有一个view source , 和一个view url decode/encode。因为是string格式,所以编码解码都一样。而如果使用$.ajax的data: {"post":{"category_id":this.value}}, view source和view URL encode会进行编码:post%5Bcategory_id%5D=4
     
    反思:这次走弯路也比较多,主要是知识块的欠缺和缺少实际经验。
     
    最后:改成data: "post[category_id]="+ this.value

    摘录(点击查看Rails.ajax git)

    if xhr.readyState is XMLHttpRequest.OPENED
      xhr.send(options.data)

     options.data必须是string格式

    Rails.ajax部分是用xhttp语法写的。

    因为Ajax,就是异步javascript和XML的组合。

    两方面:

    1. 浏览器内建XMLHttpRequest object ,用来从server上请求data.

    2. Javascript 和 HTML DOM 显示这些数据。

    ⚠️:ajax是个误导的名字, 因为它常常使用plain text 或者JSON text来传输数据。


    分析rails-ujs/utils/ajax.coffee中得代码:

    AcceptHeaders是一个hash, 包括:text, html, xml, json, script等key/value对儿。

    Rails.ajax = (options) ->

    这是一个函数,options是参数,参数url, type, data, dataTpye等等。

    options = prepareOptions(options)

    调用prepareOptions()方法,返回得结果储存在变量options中。

    prepareOptions = (options) ->

      1.设置url,如果options参数中有url,直接用,否则使用当前网页窗口的URL

    options.url = options.url or location.href

    2. type是字符串,使用javascript中的 方法,变为大写字母。

    options.type = options.type.toUpperCase()
    # 如果type是"get" request,则把data参数附加到url后面
    if options.type is 'GET' and options.data

    # 如果不存在?则加上?然后附加data,否则加上&(目的是url中传参数)
      if options.url.indexOf('?') < 0  
        options.url += '?' + options.data
      else
        options.url += '&' + options.data
    # Use "*" as default dataType,如果有dataType参数,就使用它
    options.dataType = '*' unless AcceptHeaders[options.dataType]?
    options.accept = AcceptHeaders[options.dataType]
    options.accept += ', */*; q=0.01' if options.dataType isnt '*'
    options

    xhr = createXHR options, ->   #这是一个函数

    createXHR = (options, done) ->  #也是一个函数

    createXHR = (options, done) ->

    1. 新建请求。
    xhr = new XMLHttpRequest()
    # 打开并设置xhr, 类型,url,是否异步(是)
    xhr.open(options.type, options.url, true)

    #给请求头部增加一个label/value对儿,这是加一个代表header接受的数据格式。
    xhr.setRequestHeader('Accept', options.accept)
    # 当发送string时,设置 Content-Type 
    # Sending FormData will automatically set Content-Type to multipart/form-data
    if typeof options.data is 'string'
      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')

    如果不是options.crossDomain, 则设置。。。(安全原因,浏览器不支持crossDomain)
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest') unless options.crossDomain
    # Add X-CSRF-Token(安全的原因,防止跨站虚伪请求攻击,增加token)
    CSRFProtection(xhr)
    xhr.withCredentials = !!options.withCredentials

    # 当readyState变化则调用函数:根据XMLHttpRequest的状态, done是传入的参数

    xhr.onreadystatechange = ->
      done(xhr) if xhr.readyState is XMLHttpRequest.DONE
    xhr

    xhr = createXHR options, ->

    # 调用processResponse方法,用来处理收到的response数据。
    response = processResponse(xhr.response ? xhr.responseText, xhr.getResponseHeader('Content-Type'))

    # 如果status是200则成功,否则报错。
    if xhr.status // 100 == 2
      options.success?(response, xhr.statusText, xhr)
    else
      options.error?(response, xhr.statusText, xhr)
    options.complete?(xhr, xhr.statusText)

    processResponse = (response, type) ->

    # 如果反应的是string
    if typeof response is 'string' and typeof type is 'string'

    # 如果type字符串中有json, 则把response转化为普通格式。
    if type.match(/json/)
      try response = JSON.parse(response)

    # 如果是script格式的,则创建<script>并添加到head标签内。
    else if type.match(/(?:java|ecma)script/)
      script = document.createElement('script')
      script.setAttribute('nonce', cspNonce())
      script.text = response
      document.head.appendChild(script).parentNode.removeChild(script)

    # 如果是xml格式的,则对response转化为string.
    else if type.match(/xml/)
      parser = new DOMParser()
      type = type.replace(/;.+/, '') # remove something like ';charset=utf-8'
      try response = parser.parseFromString(response, type)

    response

    可以接受的dataType:

    AcceptHeaders =
    '*': '*/*'
    text: 'text/plain'
    html: 'text/html'
    xml: 'application/xml, text/xml'
    json: 'application/json, text/javascript'
    script: 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript'

  • 相关阅读:
    Android 开发 深入理解Handler、Looper、Messagequeue 转载
    Android 开发 Handler的基本使用
    Java 学习 注解
    Android 开发 AlarmManager 定时器
    Android 开发 框架系列 百度语音合成
    Android 开发 框架系列 Google的ORM框架 Room
    Android 开发 VectorDrawable 矢量图 (三)矢量图动画
    Android 开发 VectorDrawable 矢量图 (二)了解矢量图属性与绘制
    Android 开发 VectorDrawable 矢量图 (一)了解Android矢量图与获取矢量图
    Android 开发 知晓各种id信息 获取线程ID、activityID、内核ID
  • 原文地址:https://www.cnblogs.com/chentianwei/p/9388135.html
Copyright © 2011-2022 走看看