jjzjj

javascript - 为 vanilla javascript 插件进行默认设置

coder 2024-07-28 原文

尝试用纯 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();

最佳答案

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

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
});

当您需要访问任何这些选项时,您的代码可以简单地使用对选项对象的引用:例如,您可以使用 this.options 而不是 this.bcolor .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 循环从 复制任何值defaultOptionsoptions,只要它们不存在于 options 中。它很好而且可扩展:只要您向 defaultOptions 添加新值,循环就会将其复制到 options 中,无论调用者之前传递了什么。

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


但是如果您希望在某些地方使用默认行为怎么办?例如,如果您没有定义特定的字体大小,您可能只是希望它从父元素或文档继承,而不是将其分配给 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 模式针对 undefined 的测试)在整个位于 JavaScript 中,并被 jQuery 和许多其他库大量使用。如果您遵循与他们相同的基本设计,那么您将成为很好的伙伴。

关于javascript - 为 vanilla javascript 插件进行默认设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42627218/

有关javascript - 为 vanilla javascript 插件进行默认设置的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  3. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  4. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  5. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  6. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  7. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  8. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  9. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  10. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

随机推荐