HTML中a标签如何实现post请求的

今天查看rails是如何为link_to中post请求加上authenticity_token才发现a链接不是天然就支持post请求的, 是需要经过代码处理才可以。下面列出2种实现方式,rails使用的是创建表单的方式。

创建表单方式

<a href="javascript:doPost("addStudent.action", {"name":"张三"})">提交</a>
function doPost(action, params) {
  const postForm = document.createElement("form")
  postForm.method = "post"
  postForm.action = action
  // set params
  for (var i in params) {
    var input = document.createElement("input")
    input.setAttribute("name", i)
    input.setAttribute("value", params[i])
    postForm.appendChild(input)
  }
  // create real form and submit
  document.body.appendChild(postForm)
  postForm.submit()
  // remove post form
  document.body.removeChild(postForm)
}

使用ajax的方式(比较常用)

<a href="addStudent.action" class="a_post">提交</a>
$(".a_post").on("click",function(event){
  event.preventDefault()
  const a = $(event.currentTarget)
  $.ajax({
      type: "POST",
      url: a.attr("href")
      data: JSON.stringify({param1:value1, param2:value2}),
      dataType:"json",
      success: function(result){},
      error: function(result){}
  })
})

Rails 是如何实现的

link_to "This is post link", post_url, method: :post
# <a href="/post" data-method="post" rel="nofollow"><This is post link</a>
Rails.handleMethod = (e) ->
  link = this
  method = this.getAttribute("data-method")
  return unless method

  href = Rails.herf(link)
  csrfToken = Rails.csrfToken()
  csrfParam = Rails.csrfParam()
  form = document.createElement("form")
  formContent = "<input name='_method' value=#{method} type='hidden' />"

  if csrfParam? and csrfToken? and not Rails.isCrossDomain(href)
    formConent += "<input name='#{csrfParam}' value='#{csrfToken}' type='hidden' />

  formContent += "<input type='submit' />"

  form.method = 'post'
  form.action = href
  form.target = link.target
  form.innerHTML = formContent
  form.style.display = 'none'

  document.body.appendChild(form)
  form.querySelector('[type="submit"]').click()

rails为请求加入了_method参数,是用来内部实现RESTful设计的。

参考