Rails Guide--Working with JavaScript in Rails; 如何把jquery转化为原生js


1 An Introduction to Ajax

打开网页的的过程也叫:request response cycel。

JavaScript也可以request然后parse the response,还可以更新网页上的信息。

因此JS可以部分更新网页。这个技术称为Ajax.

Rails默认使用CoffeeScript。包括应用JS.例子:

$.ajax(url: "/test").done (html) ->

  $("#results").append html

这段代表从url上取数据,然后附加到一个id为results的div后面。

Rails 提供了内建支持来使用这个技术开发网页。无需你自己写这样的代码。有helper方法。

基本原理就是这样。

 

2 Unobtrusive JavaScript  不冒失的JS

Rails使用这个技术来把JS附加到DOM上去。unobtrusive意味着不把JS代表混入到HTML。

而是用data-*属性来传递参数给behavior。

 

3 Built-in Helpers

3.1 Remote elements

Rails提供了一组视图帮助方法,是用Ruby写的,用于帮你生成HTML元素。有时,你要增加Ajax到那些元素中。

因为Unobtrusive JS, the Rails "Ajax helper"其实一半是Ruby一半是JS。

rails-ujs提供了JS的部分,Ruby view helper增加适当的tags到你的DOM。

 

3.1.1 form_with

form_with默认生成data-remote= "true",可以绑定事件:

$(document).ready ->
 $("#new_article").on("ajax:success", (event) ->
  [data, status, xhr] = event.detail
  $("#new_article").append xhr.responseText
 ).on "ajax:error", (event) ->
  $("#new_article").append "<p>ERROR</p>"

解释:如果成功了则。。。,如果失败了则附加一个<p>

 

 

 

link_to 添加remote: true,后生成data-remote= "true",我们可以绑定Ajax events.如:

$ ->
   $("a[data-remote]").on "ajax:success", (event) ->
  alert "The article was deleted."

另外button_to 实际生成一个<form><input>...表格。

 

3.2 Customize remote elements

使用data-remote 属性无需再写一行jS代码,就能客制化元素的行为。你可以指定额外的 data-attributes来完成它。

3.2.1 data-method

就是RESTful风格,可以用HTTP的4个事件来激活link。

 

3.2.2 data-url and data-params

某个元素不涉及任何URL, 但你想要它们trigger Ajax calls。需要一起使用data-url和data-remote,另外还可以用data-params增加额外的参数。

如选项框:checkbox

<input type="checkbox" data-remote="true"
      data-url="/update" data-params="id=10" data-method="put">

3.2.3 data-type

data-type attribute.

3.3 其他:

data-confirm属性:

link_to "Dangerous zone", *_path, data: { confirm: "Are you sure?"} 生成类似:

<a href="..." data-confirm="Are you sure?">Dangerous zone</a>

data-disable-with attribute:

<%= form_with(model: @article.new) do |f| %>
   <%= f.submit data: { "disable-with": "Saving..." } %>
<%= end %>

生成:<input data-disable-with="Saving..." type="submit">

 

3.5 Rails-ujs event handlers(点击见,变化的event表格)

Rails5.1介绍rails-ujs,并且无需依赖jQuery。新版所有custom events只返回一个参数event.

增加了一个event.detail属性,它会返回一个array,这个array包括了其他的参数xhr, options, response, status。

Event nameExtra parameters (event.detail)Fired
ajax:success    [response, status, xhr] 在完成后,如果response是success,则激活event

例子:

document.body.addEventListener('ajax:success', function(event) {
    var detail = event.detail;
  var data = detail[0], status = detail[1], xhr = detail[2];
})

补充EventTarget.addEventListener()方法:

将指定的监听器注册到EventTarget上,当该对象出发指定的事件时,指定的回调函数就会被执行。target.addEventListener(type, listener, options)

在上面的例子'ajax:success'就是一个事件,后面的function是监听器。一旦事件触发,就会执行函数。结果返回给body.

 

4 Server-Side Concerns

Ajax除了客户端需要设置,服务器端也需要设置来支持它。通常,开发者想要Ajax request 返回JSON而不是HTML。看看怎么做:

4.1 案例http://guides.rubyonrails.org/working_with_javascript_in_rails.html#a-simple-example

或者参考:

file:///Users/chentianwei/离线保存的全栈文件/学习中心%20新生大学全栈营/Content/954.html

 重点:

在create方法内加 format.js, 添加create.js.erb文件。

然后使用escape_javascript(javascript)方法,也可以使用别名  j(),它的作用是转化为可以识别的javsscript代码。

下面2句code作用相同:

$("#post-list").prepend("<%=j render :partial => "post", :locals => { :post => @post } %>");

$("<%= escape_javascript(render :partial => "post", :locals => { :post => @post }) %>").prependTo("#post-list");

  


 

常用的vanilla javascript方法 替代jquery

 

其实是一个joke的叫法,准确的说是plain, regular javascript.

valla是一种俚语,意思是太常见以至于被认为是unexciting/normal/boring. 所以Vanllia JS实际上的意思是Normal Javascript。就像一个普通的vanilla icecream without topping。

(视频), 比jquery快100倍。

 

  • How to do queries for elements on the page.
  • How to add events.
  • How to hide/show just like you do with jQuery.
  • and so on...

在chrome的inspect-console可以输入JS查询,得到对应的web element. 

document.querySelector("#notifications")
<div id=​"notifications">​…​</div>​


document.getElementById("notifications")
<div id=​"notifications">​…​</div>​


document.getElementsByTagName("a")
HTMLCollection(8) [a, a, a, a, a, a, a, a]


document.querySelectorAll("#notifications p")

返回匹配元素的NodeList,这是一个array,可以使用array的方法, 如果是空的,则没有找到匹配。
NodeList(4) [p#notification_1, p#notification_2, p#notification_3, p#notification_4]

 

jquery和使用vanilla javascript的区别:

$("a").on("click", function(){  })  #无论你在function中运行什么都行,比如循环

而原生js必须明确指定循环操作:

VM16935:2 Uncaught TypeError: Failed to execute 'addEventListener' on 'EventTarget': 2 arguments required, but only 1 present.
document.querySelectorAll("p").forEach(function(anchor) {

   anchor.addEventListener("click", function(event) {

  event.preventDefault();

  console.log("clicked");

   })

})

> undefined  #如果点击网页上的任意p元素,则出现:

> clicked

⚠️ Array.prototype.forEach()方法执行一个提供的函数对每一个array element。

 

jquery的show, hide

$("#notifications").show/hide等同于:

document.querySelector("#notifications").style.display = 'none'
>"none"
document.querySelector("#notifications").style.display = 'block'
>"block"

 

document.querySelector("p").style

>CSSStyleDeclaration {alignContent: "", alignItems: "", alignSelf: "", alignmentBaseline: "", all: "", …}

点击css,会弹出所有可以使用的style后的css。是使用驼峰写法的,根原生css有区别:

css:   body {background-color: red; }

JS:  backgroundColor: "red";

 

jquery的append

$("#notifications").append("<p>Test</p>") ,等同于:

node = document.createRange().createContextualFragment("<p>test</p>")

#document-fragment<p>​test​</p>​

document.querySelector("#notifications").appendChild(node)

⚠️:有几个知识点:

 

抓取attributes和Data

<a rel="nofollow" data-method="delete" href="/users/sign_out">登出</a>

$("a").data("method")
> "delete"

$("a").attr("href")
>"/users/sign_out"

使用原生的:

 

document.querySelector("a").dataset
> DOMStringMap {method: "delete"}

document.querySelector("a").dataset.method = "post"   #可以改变
> "post"                        

另外一种原生写法:

document.querySelector("a").attributes,    #attributes获得所有属性。
>NamedNodeMap {0: rel, 1: data-method, 2: href, rel: rel, data-method: data-method, href: href, length: 3}

document.querySelector("a").getAttribute("data-method")

> "delete"

 

Ajax requests

用jquery version这么写: $.ajax({ })

Rails.5.1 这么写:(Javascript version with Rails UJS)

这会自动包括你的CSRF token for non-GET requests as well。❓啥意思

csrf token是一个校验随机数,用于防止cross-site request forgery跨站请求伪装攻击。

Rails.ajax({

  url: "/notificaitons.json",

  type: "GET",

  success: function(data) {

    console.log(data)

  }

})

⚠️ 视频:Rails5.1 new UJS library的使用

 

使用turbolinks,目的:放置到页面上面,等待HTML加载完成后,再加载

$(document).on("turbolinks:load", function() { ... }), 可以改成javascritp version:

document.addEventListener("turbolinks:load", function() { ... })

 


 

 

原生javascript 转化为coffeescript  (点击,进入自动转化网站)

document.addEventListener("turbolinks:load", function() {
 document.getElementById("new_message").addEventListener("keypress", function(e){
  console.log(e.key)
 })
})

转化为:

document.addEventListener 'turbolinks:load', ->
 document.getElementById('new_message').addEventListener 'keypress', (e) ->
  console.log e.key
  return
 return

 


jquery和原生js的相同功能代码( slim结构 ):

功能:删除一个贴文:

$(document).on("turbolinks:load", function(){
 $(".delete-post").click(function(evt){
  // 只能终止刷新index后的行为。
  evt.preventDefault();
  var url = $(this).attr("href");
  $.ajax({
    url: url,
    method: 'DELETE',
    dataType: 'json',
    success: function(data){
     $("#post-" + data["id"]).remove();
    }
  })
  // 也有preventDefault()的作用
  // return false
   })
})


document.addEventListener("turbolinks:load", function() {
  document.querySelectorAll(".delete-post").forEach(function(anchor) {
  anchor.addEventListener("click", function(event) {
    event.preventDefault();
    var url = this.getAttribute("href");
    Rails.ajax({
        url: url,
    type: "DELETE",
    dataType: 'json',
    success: function(data) {
     document.getElementById("post-" + data["id"]).style.display = 'none'
    }
  })
 })
  })
})

 

解释:

蓝色:放置在页面顶部 放置到页面上面,等待HTML加载完成后,再加载

绿色:主要区别。

黄色:写法的完全区别。

 

错误❌:新增的贴文,页面必须从新加载一次,否则点击删除按钮,会自动跳转到show页面

 

 


 

Turbolinks(6600🌟)

https://github.com/turbolinks/turbolinks

 

使用Ajax加速网页渲染。

RubyonRails

1.add gem 'turbolinks', '~> 5.1.0', 然后bundle install

2.add //= require turbolinks到application.js文件中。

如何使用:Page change Events

$(document).on "trubolinks:load", -> alert "page has loaded!"

更多使用方法见git

 

posted @ 2018-07-10 12:13  Mr-chen  阅读(464)  评论(0编辑  收藏  举报