使用 rails/jquery-ujs 来编写非侵入式的服务端模板代码

栏目: Ruby on Rails · 发布时间: 6年前

内容简介:项目地址演示 jquery-ujs原理解析:代理表单提交

项目地址 https://github.com/rails/jquery-ujs

在线 demo

演示 jquery-ujs https://mengkang.net/demo/rails/

原理解析:代理表单提交 https://mengkang.net/demo/rails/2.html

原理解析:实现 ajax 提交 https://mengkang.net/demo/rails/3.html

项目中经常看到类似于下面这样的 a 链接的请求,而点击的时候,实际发送的是 ajax 请求,而没有发生跳转。

<a href="/comments/destroy/908/" class="js-comment-destroy"
data-remote="true" 
data-method="post" 
data-confirm="确定要删除吗?">删除</a>

演示 https://mengkang.net/demo/rails/

原理分析

A 链接实现表单的提交

虽然点击还是跳转,但是通过控制台可以看到,该请求是 post 的方式,我们自定义的 rails 插件给代理了 click 为一个 form 的 post 请求。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://static.mengkang.net/view/js/jquery-1.11.3.min.js"></script>
    <script>
        (function ($) {
            'use strict';
            var rails;
            $.rails = rails = {
                linkClickSelector: 'a[data-remote]',
                href: function (element) {
                    return element[0].href;
                },
                handleMethod: function (link) {
                    var href = rails.href(link),
                        method = link.data('method'),
                        target = link.attr('target'),
                        form = $('<form method="post" action="' + href + '"></form>'),
                        metadataInput = '<input name="_method" value="' + method + '" type="hidden" />';

                    if (target) {
                        form.attr('target', target);
                    }

                    form.hide().append(metadataInput).appendTo('body');
                    form.submit();
                },
            };

            $(document).on('click.rails', rails.linkClickSelector, function (e) {
                var link = $(this);
                rails.handleMethod(link);
                return false;
            });
        })(jQuery);
    </script>
</head>
<body>
    <a href="/comments/destroy/908/" data-remote="false" data-method="post">删除</a>
</body>
</html>

代码演示 https://mengkang.net/demo/rails/2.html

例子中

$(document).on('click.rails', 'a[data-remote]', function (e) {
  //...
});

click.railsrails 是命名空间。方便解除该事件。

http://api.jquery.com/on/

One or more space-separated event types and optional namespaces, such as "click" or "keydown.myPlugin".

Any event names can be used for the events argument. jQuery will pass through the browser's standard JavaScript event types, calling the handler function when the browser generates events due to user actions such as click. In addition, the .trigger() method can trigger both standard browser event names and custom event names to call attached handlers. Event names should only contain alphanumerics, underscore, and colon characters.

An event name can be qualified by event namespaces that simplify removing or triggering the event. For example, click.myPlugin.simple defines both the myPlugin and simple namespaces for this particular click event. A click event handler attached via that string could be removed with .off("click.myPlugin") or .off("click.simple") without disturbing other click handlers attached to the elements. Namespaces are similar to CSS classes in that they are not hierarchical; only one name needs to match. Namespaces beginning with an underscore are reserved for jQuery's use.

实现 A 链接的 ajax 请求

在上面代码的基础上我们把 data-remote 参数利用上,如果 data-remote 设置为 true 则表示使用 ajax 请求。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://static.mengkang.net/view/js/jquery-1.11.3.min.js"></script>
    <script>
        (function ($) {
            'use strict';
            var rails;
            $.rails = rails = {
                linkClickSelector: ' a[data-remote]',
                href: function (element) {
                    return element[0].href;
                },
                isRemote: function(element) {
                    return element.data('remote') !== undefined && element.data('remote') !== false;
                },
                handleMethod: function (link) {
                    var href = rails.href(link),
                        method = link.data('method'),
                        target = link.attr('target'),
                        form = $('<form method="post" action="' + href + '"></form>'),
                        metadataInput = '<input name="_method" value="' + method + '" type="hidden" />';

                    if (target) {
                        form.attr('target', target);
                    }

                    form.hide().append(metadataInput).appendTo('body');
                    form.submit();
                },
                handleRemote: function(element) {
                    var options = {};

                    options.url = rails.href(element);
                    options.method = element.data('method');
                    options.data = element.data('params') || null;

                    return $.ajax(options);
                }
            };

            $(document).on('click.rails', rails.linkClickSelector, function (e) {
                var link = $(this);

                if (rails.isRemote(link)) {
                    rails.handleRemote(link);
                }else{
                    rails.handleMethod(link);
                }
                return false;
            });
        })(jQuery);
    </script>
</head>
<body>
  <a href="/comments/destroy/908/" data-remote="true" data-method="post">删除</a>
</body>
</html>

代码演示 https://mengkang.net/demo/rails/3.html

绑定到 ajax:success 做回调

$document.on('ajax:success', '.js-comment-destroy', function() {
    return $(this).closest('.media').remove();
});

这个事件是如何触发的呢?实际是在发送 ajax 里面使用 trigger 来触发。

options = {
    success: function(data, status, xhr) {
        element.trigger('ajax:success', [data, status, xhr]);
    },
    complete: function(xhr, status) {
        element.trigger('ajax:complete', [xhr, status]);
    },
    error: function(xhr, status, error) {
        element.trigger('ajax:error', [xhr, status, error]);
    }
}

options.url = rails.href(element);
options.method = element.data('method');
options.data = element.data('params') || null;

$ajax.(options);

扩展开发 data-done

为了完全非侵入式的 JavaScript 服务端开发,才有了这个需求(反正作为一个服务端渲染的模板,不想又去专门弄前端项目,更愿意直接在模板里修改)

<a href="/comments/destroy/908/" 
data-remote="true" 
data-method="post"
data-done="$(this).closest('.media').remove()"
>删除</a>
$(document).on('ajax:success', '[data-done]', function(evt, res) {
  var $res, $self, self;
  self = this;
  $self = $(this);
  $res = $(res);
  if (done) {
    (new Function('res', 'r', '$r', done)).call(self, res, res, $res);
  }
});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

人工智能

人工智能

腾讯研究院、中国信通院互联网法律研究中心、腾讯AI Lab、腾讯开放平台 / 中国人民大学出版社 / 2017-10-25 / 68.00元

面对科技的迅猛发展,中国政府制定了《新一代人工智能发展规划》,将人工智能上升到国家战略层面,并提出:不仅人工智能产业要成为新的经济增长点,而且要在2030年达到世界领先水平,让中国成为世界主要人工智能创新中心,为跻身创新型国家前列和经济强国奠定基础。 《人工智能》一书由腾讯一流团队与工信部高端智库倾力创作。本书从人工智能这一颠覆性技术的前世今生说起,对人工智能产业全貌、最新进展、发展趋势进行......一起来看看 《人工智能》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

MD5 加密
MD5 加密

MD5 加密工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具