如何使用方法创建 javascript 插件?
How to create a javascript plugin with methods?
来自How to create a jQuery plugin with methods?
如何在 javascript 没有 JQuery
的情况下做同样的事情
JQuery
(function ( $ ) {
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
};
}( jQuery ));
Js
?
如果您的意思是“如何将我自己的方法添加到 DOM 元素”,我的建议是:不要,因为您的方法可能会与后来添加到标准中的方法发生冲突。 (并且 绝对 不在库中,只在特定页面或应用程序的代码中这样做——如果你这样做的话。)相反,做 jQuery 所做的并且在元素周围放置包装器。
但是如果您无论如何都想这样做,您需要将函数添加到您希望它们出现的元素的原型中。基本 HTML 元素是 HTMLElement
,因此要向所有 HTML 元素添加一个方法,您需要将其添加到那里。
// Ensure that your method isn't enumerable by using `Object.defineProperty`
Object.defineProperty(HTMLElement.prototype, "greenify", {
configurable: true,
writable: true,
value() {
this.style.color = "green";
}
});
示例:
// Ensure that your method isn't enumerable by using `Object.defineProperty`
Object.defineProperty(HTMLElement.prototype, "greenify", {
configurable: true,
writable: true,
value() {
this.style.color = "green";
}
});
// Use it
document.getElementById("a").greenify();
document.getElementById("b").greenify();
// Since it's on the prototype, it applies regardless of
// whether the element already existed:
const c = document.createElement("div");
c.greenify();
c.textContent = `This is "c"`;
document.body.appendChild(c);
<div id="a">This is "a"</div>
<div id="b">This is "b"</div>
目前,元素集合是 NodeList
个实例(querySelectorAll
和其他较新的集合)或 HTMLCollection
个实例(getElementsByXYZ
),尽管这可能会进一步发展.因此,如果您希望能够在集合上调用 addClass
,您可以将其添加到其中一个或两个原型中。让我们从 greenify
转到一个更有用的示例:将 class 添加到集合中的所有元素:
// Ensure that your method isn't enumerable by using `Object.defineProperty`
function addClass(...classes) {
for (let n = 0; n < this.length; ++n) {
this[n].classList.add(...classes);
}
}
Object.defineProperty(NodeList.prototype, "addClass", {
configurable: true,
writable: true,
value: addClass
});
Object.defineProperty(HTMLCollection.prototype, "addClass", {
configurable: true,
writable: true,
value: addClass
});
// Use it
document.querySelectorAll("div").addClass("accent");
document.getElementsByClassName("x").addClass("emphasize");
.accent {
color: green;
}
.emphasize {
font-weight: bold;
}
<div class="x">This is "a"</div>
<div class="x">This is "b"</div>
普通旧函数
jQuery 只不过是 JavaScript 本身。您可以轻松地将 greenify
和 boldify
编写为普通函数。这是一个很好的方法,因为每个简单的函数都易于编写、测试和在需要此特定行为的程序的任何部分中重用 -
function greenify (elem) {
elem.style.color = "green"
}
function boldify (elem) {
elem.style.fontWeight = "bold"
}
greenify(document.querySelector("#foo"))
boldify(document.querySelector("#bar"))
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
html render: example 1
class注意事项和注意事项
jQuery 使用面向对象的风格,允许“链接”方法。这个接口是可取的,因为它使我们能够将程序编写为长链表达式,就像我们可以写句子一样。大多数人会使用 class
来完成此操作,它是定义函数并将“方法”添加到函数的 prototype -
的语法糖
class MyTools {
constructor (elem) {
this.elem = elem
}
greenify() {
this.elem.style.color = "green"
return this
}
boldify() {
this.elem.style.fontWeight = "bold"
return this
}
}
function mytools (elem) {
return new MyTools(elem)
}
mytools(document.querySelector("#foo")).greenify()
mytools(document.querySelector("#bar")).boldify()
mytools(document.querySelector("#qux")).boldify().greenify()
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
html render: example 2
但是如果我们的 mytools
class 中有很多像 greenify
和 boldify
这样的方法呢?您可以看到 class 如何变得相当大,并且为每个方法重复 return this
有点负担。如果将来有人只想使用您工具库的 部分 怎么办?使用单体 class 使得无法使用 dead code elimination,这意味着即使需要 one 功能也必须包含整个模块。
高阶函数
我们能否构建一个没有这些缺点的直观界面?解决这些问题的一种方法是使用 higher-order functions。这样的函数可以将一个函数作为输入 and/or return 一个新函数作为输出。您可能使用过内置的高阶函数,例如 Array.prototype.map
、Array.prototype.filter
、Array.prototype.reduce
或其他函数,但我们也可以轻松创建自己的 -
const effect = f =>
x => { f(x); return x }
function identity (value) {
return { value, map: f => identity(f(value)) }
}
const boldify =
effect(elem => elem.style.fontWeight = "bold")
const greenify =
effect(elem => elem.style.color = "green")
// prefix style; ordinary function calls
greenify(boldify(document.querySelector("#foo")))
// "chaining" style; by use of identity
identity(document.querySelector("#qux"))
.map(boldify)
.map(greenify)
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
html render: example 3
模块
即使是 jQuery 3.6.0 的“精简版”也超过了 72 KB,并且无法只导入其中的一部分。这是 jQuery 选择通过单个面向对象的接口实现所有内容的结果,jQuery
函数,别名为 $
。然而,JavaScript 的未来在于其为 modules 设计。它们可重复使用、灵活并且可以即时加载,从而生成高度优化和简化的脚本,可以立即响应用户。
上面我们写了几个函数。让我们看看我们如何开始为我们自己的程序组织模块 -
// func.js
function identity (value) {
return { value, map: f => identity(f(value)) }
}
const effect = f =>
x => { f(x); return x }
export { effect, identity }
// css.js
import { effect } from "./func.js"
const boldify =
effect(elem => elem.style.fontWeight = "bold")
const greenify =
effect(elem => elem.style.color = "green")
export { boldify, greenify }
当我们使用模块时,我们 import
只使用我们需要的部分。这使编译器(转译器、“打包器”、“捆绑器”等)有机会删除死代码并显着减少已完成的生产就绪程序的大小 -
// main
import { greenify } from "./css.js"
greenify(document.querySelector("#some-elem"))
甚至 *
导入也可以优化,因为依赖项解析器可以确定仅使用来自 css
命名导入的特定函数 -
import { identity } from "./func.js"
import * as css from "./css.js"
identity(document.querySelector("#some-elem"))
.map(css.boldify)
.map(css.greenify)
增加你的模块
所以您想扩展您的模块以支持其他一些颜色,例如 bluify
、purplify
等。你可以试试这样的 -
// css.js
// DON'T DO THIS!
const bluify =
effect(elem => elem.style.color = "green")
const greenify =
effect(elem => elem.style.color = "green")
const purplify =
effect(elem => elem.style.color = "purplify")
// ...
export { bluify, greenify, purplify, ... }
相反,请注意每个函数中只有 elem.style.color = ...
的 ...
部分发生了变化。为了避免一遍又一遍地重复自己,我们创建函数 -
// css.js
import { effect } from "./func.js"
// any color, not just green!
const color = value =>
effect(elem => elem.style.color = value)
// any font-weight, not just bold!
const fontWeight = value =>
effect(elem => elem.style.fontWeight = value)
// other CSS properties...
const fontSize = value =>
effect(elem => elem.style.fontSize = value)
// ...
export { color, fontWeight, fontSize, ... }
请注意 color
、fontWeight
和 fontSize
各有一个 value
参数。我们减少了代码重复并使我们的功能更有用 -
// main.js
import { identity } from "./func.js"
import * as css from "./css.js"
identity(document.querySelector("#bar"))
.map(css.color("limegreen"))
.map(css.fontSize("24pt"))
identity(document.querySelector("#qux"))
.map(css.color("dodgerblue"))
.map(css.fontWeight("900"))
html render: example 4
展开下面的代码段 4 以在您自己的浏览器中验证此结果 -
// func.js
const effect = f =>
x => { f(x); return x }
function identity (value) {
return { value, map: f => identity(f(value)) }
}
// css.js
const fontWeight = value =>
effect(elem => elem.style.fontWeight = value)
const fontSize = value =>
effect(elem => elem.style.fontSize = value)
const color = value =>
effect(elem => elem.style.color = value)
// main.js
identity(document.querySelector("#bar"))
.map(color("limegreen"))
.map(fontSize("24pt"))
identity(document.querySelector("#qux"))
.map(color("dodgerblue"))
.map(fontWeight("900"))
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
jQuery精简版
也许您喜欢 jQuery,因为它接受 CSS 选择器并且不需要您使用 identity
或 document.querySelector
。 jQuery 做出了选择,你也可以。这是你的程序,你可以自由地发明你想要的任何便利 -
// myquery.js
import { identity } from "./func.js"
function $(selector) {
const loop = t => plugin => loop(t.map(plugin))
return loop(identity(document.querySelector(selector)))
}
export { $ }
我们可以开始看到我们自己的 $
不断发展! -
// main.js
import { $ } from "./myquery.js"
import { color, fontSize, fontWeight } from "./css.js"
// example expressions
$("#bar")(color("gold"))(fontSize("8pt"))
$("#qux")(fontSize("14pt"))(color("hotpink"))(fontWeight(900))
html render: example 5
展开下面的代码段 5 以在您的浏览器中验证结果 -
// func.js
const effect = f =>
x => { f(x); return x }
function identity (value) {
return { value, map: f => identity(f(value)) }
}
// css.js
const fontWeight = value =>
effect(elem => elem.style.fontWeight = value)
const fontSize = value =>
effect(elem => elem.style.fontSize = value)
const color = value =>
effect(elem => elem.style.color = value)
// myquery.js
function $(selector) {
const loop = t => plugin => loop(t.map(plugin))
return loop(identity(document.querySelector(selector)))
}
// main.js
$("#bar")(color("gold"))(fontSize("8pt"))
$("#qux")(fontSize("14pt"))(color("hotpink"))(fontWeight(900))
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
也许您想对多个元素进行操作,类似于jQuery?我们可以通过使用 querySelectorAll
并使用 Array.from
将 plugin
应用于可迭代对象中的所有元素来做到这一点。请注意,我们也可以绕过 identity
的需要,因为 loop
已经 closes over 其 context
-
// myquery.js (updated)
function $(selector) {
const loop = context => plugin => loop(Array.from(context, plugin))
return loop(document.querySelectorAll(selector))
}
// main.js
// target all <p> elements
$("p")(color("orchid"))
// target #foo element
$("#foo")(fontSize("18pt"))(fontWeight("bold"))
// target #bar and #qux elements
$("#bar,#qux")(fontSize("12pt"))
html render: example 6
展开下面的代码段 6 以在浏览器中验证结果 -
// func.js
const effect = f =>
x => { f(x); return x }
function identity (value) {
return { value, map: f => identity(f(value)) }
}
// css.js
const fontWeight = value =>
effect(elem => elem.style.fontWeight = value)
const fontSize = value =>
effect(elem => elem.style.fontSize = value)
const color = value =>
effect(elem => elem.style.color = value)
// myquery.js
function $(selector) {
const loop = t => plugin => loop(t.map(v => Array.from(v, plugin)))
return loop(identity(document.querySelectorAll(selector)))
}
// main.js
$("p")(color("orchid"))
$("#foo")(fontSize("18pt"))(fontWeight("bold"))
$("#bar,#qux")(fontSize("12pt"))
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
鹰眼
您是否注意到 color
、fontWeight
和 fontSize
看起来几乎一模一样?我们可以继续使用抽象来去除额外的重复。通过捕获行为的最小可识别本质,我们获得了最大的灵活性,使我们能够轻松地从简单的行为构建复杂的行为 -
// css.js
import { effect } from "./func.js"
const style = property => value =>
effect(elem => elem.style[property] = value)
const color = style("color")
const fontWeight = style("fontWeight")
const fontSize = style("fontSize")
// ...
export { color, fontWeight, fontSize, style, ... }
来自How to create a jQuery plugin with methods?
如何在 javascript 没有 JQuery
的情况下做同样的事情JQuery
(function ( $ ) {
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
};
}( jQuery ));
Js
?
如果您的意思是“如何将我自己的方法添加到 DOM 元素”,我的建议是:不要,因为您的方法可能会与后来添加到标准中的方法发生冲突。 (并且 绝对 不在库中,只在特定页面或应用程序的代码中这样做——如果你这样做的话。)相反,做 jQuery 所做的并且在元素周围放置包装器。
但是如果您无论如何都想这样做,您需要将函数添加到您希望它们出现的元素的原型中。基本 HTML 元素是 HTMLElement
,因此要向所有 HTML 元素添加一个方法,您需要将其添加到那里。
// Ensure that your method isn't enumerable by using `Object.defineProperty`
Object.defineProperty(HTMLElement.prototype, "greenify", {
configurable: true,
writable: true,
value() {
this.style.color = "green";
}
});
示例:
// Ensure that your method isn't enumerable by using `Object.defineProperty`
Object.defineProperty(HTMLElement.prototype, "greenify", {
configurable: true,
writable: true,
value() {
this.style.color = "green";
}
});
// Use it
document.getElementById("a").greenify();
document.getElementById("b").greenify();
// Since it's on the prototype, it applies regardless of
// whether the element already existed:
const c = document.createElement("div");
c.greenify();
c.textContent = `This is "c"`;
document.body.appendChild(c);
<div id="a">This is "a"</div>
<div id="b">This is "b"</div>
目前,元素集合是 NodeList
个实例(querySelectorAll
和其他较新的集合)或 HTMLCollection
个实例(getElementsByXYZ
),尽管这可能会进一步发展.因此,如果您希望能够在集合上调用 addClass
,您可以将其添加到其中一个或两个原型中。让我们从 greenify
转到一个更有用的示例:将 class 添加到集合中的所有元素:
// Ensure that your method isn't enumerable by using `Object.defineProperty`
function addClass(...classes) {
for (let n = 0; n < this.length; ++n) {
this[n].classList.add(...classes);
}
}
Object.defineProperty(NodeList.prototype, "addClass", {
configurable: true,
writable: true,
value: addClass
});
Object.defineProperty(HTMLCollection.prototype, "addClass", {
configurable: true,
writable: true,
value: addClass
});
// Use it
document.querySelectorAll("div").addClass("accent");
document.getElementsByClassName("x").addClass("emphasize");
.accent {
color: green;
}
.emphasize {
font-weight: bold;
}
<div class="x">This is "a"</div>
<div class="x">This is "b"</div>
普通旧函数
jQuery 只不过是 JavaScript 本身。您可以轻松地将 greenify
和 boldify
编写为普通函数。这是一个很好的方法,因为每个简单的函数都易于编写、测试和在需要此特定行为的程序的任何部分中重用 -
function greenify (elem) {
elem.style.color = "green"
}
function boldify (elem) {
elem.style.fontWeight = "bold"
}
greenify(document.querySelector("#foo"))
boldify(document.querySelector("#bar"))
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
html render: example 1 |
---|
class注意事项和注意事项
jQuery 使用面向对象的风格,允许“链接”方法。这个接口是可取的,因为它使我们能够将程序编写为长链表达式,就像我们可以写句子一样。大多数人会使用 class
来完成此操作,它是定义函数并将“方法”添加到函数的 prototype -
class MyTools {
constructor (elem) {
this.elem = elem
}
greenify() {
this.elem.style.color = "green"
return this
}
boldify() {
this.elem.style.fontWeight = "bold"
return this
}
}
function mytools (elem) {
return new MyTools(elem)
}
mytools(document.querySelector("#foo")).greenify()
mytools(document.querySelector("#bar")).boldify()
mytools(document.querySelector("#qux")).boldify().greenify()
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
html render: example 2 |
---|
但是如果我们的 mytools
class 中有很多像 greenify
和 boldify
这样的方法呢?您可以看到 class 如何变得相当大,并且为每个方法重复 return this
有点负担。如果将来有人只想使用您工具库的 部分 怎么办?使用单体 class 使得无法使用 dead code elimination,这意味着即使需要 one 功能也必须包含整个模块。
高阶函数
我们能否构建一个没有这些缺点的直观界面?解决这些问题的一种方法是使用 higher-order functions。这样的函数可以将一个函数作为输入 and/or return 一个新函数作为输出。您可能使用过内置的高阶函数,例如 Array.prototype.map
、Array.prototype.filter
、Array.prototype.reduce
或其他函数,但我们也可以轻松创建自己的 -
const effect = f =>
x => { f(x); return x }
function identity (value) {
return { value, map: f => identity(f(value)) }
}
const boldify =
effect(elem => elem.style.fontWeight = "bold")
const greenify =
effect(elem => elem.style.color = "green")
// prefix style; ordinary function calls
greenify(boldify(document.querySelector("#foo")))
// "chaining" style; by use of identity
identity(document.querySelector("#qux"))
.map(boldify)
.map(greenify)
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
html render: example 3 |
---|
模块
即使是 jQuery 3.6.0 的“精简版”也超过了 72 KB,并且无法只导入其中的一部分。这是 jQuery 选择通过单个面向对象的接口实现所有内容的结果,jQuery
函数,别名为 $
。然而,JavaScript 的未来在于其为 modules 设计。它们可重复使用、灵活并且可以即时加载,从而生成高度优化和简化的脚本,可以立即响应用户。
上面我们写了几个函数。让我们看看我们如何开始为我们自己的程序组织模块 -
// func.js
function identity (value) {
return { value, map: f => identity(f(value)) }
}
const effect = f =>
x => { f(x); return x }
export { effect, identity }
// css.js
import { effect } from "./func.js"
const boldify =
effect(elem => elem.style.fontWeight = "bold")
const greenify =
effect(elem => elem.style.color = "green")
export { boldify, greenify }
当我们使用模块时,我们 import
只使用我们需要的部分。这使编译器(转译器、“打包器”、“捆绑器”等)有机会删除死代码并显着减少已完成的生产就绪程序的大小 -
// main
import { greenify } from "./css.js"
greenify(document.querySelector("#some-elem"))
甚至 *
导入也可以优化,因为依赖项解析器可以确定仅使用来自 css
命名导入的特定函数 -
import { identity } from "./func.js"
import * as css from "./css.js"
identity(document.querySelector("#some-elem"))
.map(css.boldify)
.map(css.greenify)
增加你的模块
所以您想扩展您的模块以支持其他一些颜色,例如 bluify
、purplify
等。你可以试试这样的 -
// css.js
// DON'T DO THIS!
const bluify =
effect(elem => elem.style.color = "green")
const greenify =
effect(elem => elem.style.color = "green")
const purplify =
effect(elem => elem.style.color = "purplify")
// ...
export { bluify, greenify, purplify, ... }
相反,请注意每个函数中只有 elem.style.color = ...
的 ...
部分发生了变化。为了避免一遍又一遍地重复自己,我们创建函数 -
// css.js
import { effect } from "./func.js"
// any color, not just green!
const color = value =>
effect(elem => elem.style.color = value)
// any font-weight, not just bold!
const fontWeight = value =>
effect(elem => elem.style.fontWeight = value)
// other CSS properties...
const fontSize = value =>
effect(elem => elem.style.fontSize = value)
// ...
export { color, fontWeight, fontSize, ... }
请注意 color
、fontWeight
和 fontSize
各有一个 value
参数。我们减少了代码重复并使我们的功能更有用 -
// main.js
import { identity } from "./func.js"
import * as css from "./css.js"
identity(document.querySelector("#bar"))
.map(css.color("limegreen"))
.map(css.fontSize("24pt"))
identity(document.querySelector("#qux"))
.map(css.color("dodgerblue"))
.map(css.fontWeight("900"))
html render: example 4 |
---|
展开下面的代码段 4 以在您自己的浏览器中验证此结果 -
// func.js
const effect = f =>
x => { f(x); return x }
function identity (value) {
return { value, map: f => identity(f(value)) }
}
// css.js
const fontWeight = value =>
effect(elem => elem.style.fontWeight = value)
const fontSize = value =>
effect(elem => elem.style.fontSize = value)
const color = value =>
effect(elem => elem.style.color = value)
// main.js
identity(document.querySelector("#bar"))
.map(color("limegreen"))
.map(fontSize("24pt"))
identity(document.querySelector("#qux"))
.map(color("dodgerblue"))
.map(fontWeight("900"))
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
jQuery精简版
也许您喜欢 jQuery,因为它接受 CSS 选择器并且不需要您使用 identity
或 document.querySelector
。 jQuery 做出了选择,你也可以。这是你的程序,你可以自由地发明你想要的任何便利 -
// myquery.js
import { identity } from "./func.js"
function $(selector) {
const loop = t => plugin => loop(t.map(plugin))
return loop(identity(document.querySelector(selector)))
}
export { $ }
我们可以开始看到我们自己的 $
不断发展! -
// main.js
import { $ } from "./myquery.js"
import { color, fontSize, fontWeight } from "./css.js"
// example expressions
$("#bar")(color("gold"))(fontSize("8pt"))
$("#qux")(fontSize("14pt"))(color("hotpink"))(fontWeight(900))
html render: example 5 |
---|
展开下面的代码段 5 以在您的浏览器中验证结果 -
// func.js
const effect = f =>
x => { f(x); return x }
function identity (value) {
return { value, map: f => identity(f(value)) }
}
// css.js
const fontWeight = value =>
effect(elem => elem.style.fontWeight = value)
const fontSize = value =>
effect(elem => elem.style.fontSize = value)
const color = value =>
effect(elem => elem.style.color = value)
// myquery.js
function $(selector) {
const loop = t => plugin => loop(t.map(plugin))
return loop(identity(document.querySelector(selector)))
}
// main.js
$("#bar")(color("gold"))(fontSize("8pt"))
$("#qux")(fontSize("14pt"))(color("hotpink"))(fontWeight(900))
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
也许您想对多个元素进行操作,类似于jQuery?我们可以通过使用 querySelectorAll
并使用 Array.from
将 plugin
应用于可迭代对象中的所有元素来做到这一点。请注意,我们也可以绕过 identity
的需要,因为 loop
已经 closes over 其 context
-
// myquery.js (updated)
function $(selector) {
const loop = context => plugin => loop(Array.from(context, plugin))
return loop(document.querySelectorAll(selector))
}
// main.js
// target all <p> elements
$("p")(color("orchid"))
// target #foo element
$("#foo")(fontSize("18pt"))(fontWeight("bold"))
// target #bar and #qux elements
$("#bar,#qux")(fontSize("12pt"))
html render: example 6 |
---|
展开下面的代码段 6 以在浏览器中验证结果 -
// func.js
const effect = f =>
x => { f(x); return x }
function identity (value) {
return { value, map: f => identity(f(value)) }
}
// css.js
const fontWeight = value =>
effect(elem => elem.style.fontWeight = value)
const fontSize = value =>
effect(elem => elem.style.fontSize = value)
const color = value =>
effect(elem => elem.style.color = value)
// myquery.js
function $(selector) {
const loop = t => plugin => loop(t.map(v => Array.from(v, plugin)))
return loop(identity(document.querySelectorAll(selector)))
}
// main.js
$("p")(color("orchid"))
$("#foo")(fontSize("18pt"))(fontWeight("bold"))
$("#bar,#qux")(fontSize("12pt"))
<p id="foo">hello world</p>
<p id="bar">hello world</p>
<p id="qux">hello world</p>
鹰眼
您是否注意到 color
、fontWeight
和 fontSize
看起来几乎一模一样?我们可以继续使用抽象来去除额外的重复。通过捕获行为的最小可识别本质,我们获得了最大的灵活性,使我们能够轻松地从简单的行为构建复杂的行为 -
// css.js
import { effect } from "./func.js"
const style = property => value =>
effect(elem => elem.style[property] = value)
const color = style("color")
const fontWeight = style("fontWeight")
const fontSize = style("fontSize")
// ...
export { color, fontWeight, fontSize, style, ... }