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'

  • 相关阅读:
    团队博客18
    团队博客17
    团队博客16
    团队博客15
    团队博客14
    团队博客13
    团队博客12
    课堂作业08--MVC框架的具体应用
    课堂作业07--MVC框架
    课堂作业06--23中设计模式
  • 原文地址:https://www.cnblogs.com/chentianwei/p/9388135.html
Copyright © 2011-2022 走看看