为vanilla javascript插件制作默认设置

时间:2017-03-06 13:44:15

标签: javascript object plugins

试图在普通的javascript中构建一个简单的工具提示插件。

在我的代码中,我尝试将bcolor设置为我的代码中的默认设置,我认为当我们想要设置多个默认设置时,这不是一个好方法。

那么,如何在我的vanilla javascript插件中进行默认设置?

JSFIDDLE

var Tooltip = function(selector, bcolor) {
  this.targetElement = document.querySelectorAll(selector);
  this.bcolor = bcolor;
  if (this.bcolor == null || typeof this.bcolor !== "string") {
    this.bcolor = "#333";
  }

  if (this.targetElement == null) {
    console.log("Ooops, error!")
  }

  return this;
}

Tooltip.prototype.tooltip = function() {
  for (var i = 0; i < this.targetElement.length; i++) {

    var text = this.targetElement[i].getAttribute("data-tooltip");

    this.targetElement[i].style.position = "relative";

    var span = document.createElement("span");
    this.targetElement[i].appendChild(span);
    span.style.position = "absolute";
    span.style.top = "-25px";
    span.style.left = "-20px";
    span.style.padding = "4px"
    span.style.borderRadius = "5px";
    span.style.backgroundColor = this.bcolor;
    span.style.color = "#fff";
    span.innerHTML = text;
  }
}

var box = new Tooltip(".box", "red");
box.tooltip();

1 个答案:

答案 0 :(得分:13)

首先,让我们看看如何轻松支持多个选项。对此的一个常见解决方案是让构造函数接受“配置”对象而不是简单的字符串或数字参数。请考虑使用此表单:

var Tooltip = function(selector, options) {
    this.targetElement = document.querySelectorAll(selector);
    this.options = options;
    ...
};

var box = new Tooltip(".box", { color: "red" });

请注意,我们不是传递单个值,而是传入包含该单个值的对象。但是该对象可能包含许多配置选项 - 而不仅仅是一个!例如,您可以传入:

var box = new Tooltip(".box", {
    backgroundColor: "red",
    textColor: "white",
    fontSize: 12,
    animated: true,
    animationSpeed: 1000
});

当您需要访问任何这些选项时,您的代码只需使用对options对象的引用:例如,您可以使用this.bcolor而不是this.options.backgroundColor。这是上面的代码,扩展了一些选项:

Tooltip.prototype.tooltip = function() {
   for (var i = 0; i < this.targetElement.length; i++) {
       ...
       span.style.backgroundColor = this.options.backgroundColor;
       span.style.color = this.options.textColor;
       span.style.fontSize = this.options.fontSize + "px";
       ...
   }
}

这就是你如何处理多种选择;但每个默认值呢?为此,您需要首先在某处定义默认值:

Tooltip.prototype.defaultOptions = {
    backgroundColor: "#FF9",
    textColor: "black",
    fontSize: 12,
    animated: false,
    animationSpeed: 1000
};

然后你的构造函数可以旋转defaultOptions,使用它的值来填充提供的options对象中缺少的“漏洞”:

var Tooltip = function(selector, options) {
    this.targetElement = document.querySelectorAll(selector);
    this.options = options;

    for (var optionName in this.defaultOptions) {
        if (typeof this.options[optionName] === 'undefined')
            this.options[optionName] = this.defaultOptions[optionName];
    }
    ...
};

typeofundefined的值的测试仅在值不存在时才为真,因此for循环将任何值从defaultOptions复制到{{1只要options中不存在它们。它很好且可扩展:只要向options添加新值,循环就会将其复制到defaultOptions,无论调用者之前传递的是什么。

而且,更重要的是,options循环实际上就是for正在做的所有事情:将值从一个对象复制到另一个对象。 (jQuery解决方案更优雅一点,但我在这里简化了一些事情,以便更明显地发生了什么。)

但是,如果您想在某些地方使用默认行为,该怎么办?例如,如果您没有定义特定的字体大小,可能只是希望它从父元素或文档继承而不是从jQuery.extend分配给它。

如果你想要那种“不分配 - 除非提供”的行为,上面相同的基本模式可以工作,但是你需要稍微调整一下默认选项,然后在你添加一个条件时'正在应用该选项。考虑这个例子与我上面显示的不同之处:

defaultOptions

这对你来说应该足够了。

此处的变体( // Notice that we specifically leave out fontSize here in the defaults. Tooltip.prototype.defaultOptions = { backgroundColor: "#FF9", textColor: "black", animated: false, animationSpeed: 1000 }; Tooltip.prototype.tooltip = function() { for (var i = 0; i < this.targetElement.length; i++) { ... span.style.backgroundColor = this.options.backgroundColor; span.style.color = this.options.textColor; // Now, we only assign the fontSize if it was provided by the user. if (typeof this.options.fontSize !== 'undefined') span.style.fontSize = this.options.fontSize + "px"; ... } } 模式针对Object.extend 的测试)在JavaScript中被广泛使用,并且被大量使用通过jQuery和许多其他库。如果你遵循他们所做的相同的基本设计,你将会处于非常好的公司。