将所有jQuery函数包装到一个类中

Wrap all jQuery functions into a class

本文关键字:一个 jQuery 函数 包装      更新时间:2023-09-26

我想为js类包装所有的jQuery's DOM函数,但这些函数只处理该类的单个属性。

class Foo {
  constructor() {
    this.$wrapper = $('<div>wrapper</div>')
  }
}
var f = new Foo();
// have to call this
f.$wrapper.appendTo($('body'));
// want to call this
f.appendTo($('body'));

我可以通过为每个jQuery方法创建同名方法并始终将其应用于this.$wrapper来手动完成此操作,这将花费大量时间。但我想知道是否有更简单的方法来做到这一点。

https://jsfiddle.net/gy9tLyk2/

是的,只需扩展jQuery.fn.init并使用super调用:

class Foo extends jQuery.fn.init {
  constructor() {
    super('<div>wrapper</div>');
  }
}
Foo.prototype.constructor = jQuery;
new Foo().appendTo('body');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

注意我替换Foo.prototype.constructor是因为jQuery将访问实例的constructor属性并调用它。但是像Foo这样的ES6类是不可调用的,jQuery也不应该调用Foo

不确定babel是否能够正确编译,以下是ES5代码:

function Foo() {
  this.init('<div>wrapper</div>');
}
Foo.prototype = Object.create(jQuery.fn);
new Foo().appendTo('body');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

一种选择是使用ES2015代理,即Proxy构造函数。

class Foo {
  constructor() {
    this.$wrapper = $('<div>wrapper</div>');
    return new Proxy(this, {
        get: function(target, prop, receiver) {
         if ( target.hasOwnProperty(prop) ) {
           return target[prop];
         }
         return function() {
           let ret = target.$wrapper[prop](...arguments);
           if ( ret !== target.$wrapper ) return ret;
           return receiver;
         }
      }
    });
  }
}
var f = new Foo();
var a = f.appendTo($('body')).text('changed').prop('tagName');

但不建议这样做,原因如下:

  1. 浏览器支持
  2. 代理慢
  3. jQuery有getter和setter,创建一个代理处理程序来处理所有的jQuery和类方法是很棘手的。