为Bootstrap 4创建自定义组件


舆论已将Bootstrap转换为过去的传奇框架类别,但仍然值得一看。 Bootstrap 4是用于安全布局的出色导航器,最重要的是,用于创建Web应用程序的HTML over JS方法样本充分展示了HTML的现有功能,用于对用户界面进行声明式描述。


JavaScript框架代码的开发方式也很有用。 jQuery插件的体系结构仍在使用中,但是从版本4开始,它由Rollup包装在使用Babel6 转换的ES6类包中。 jQuery可能根本不会很快发布-稍后再介绍-但就目前而言,以创建自己的BsMultiSelect插件为例,与Boostrap 4在同一堆栈上,将揭示该框架的开发功能。


为什么“ 每个程序员都应该编写自己的...


改善商品只会变质 。” 了解新的Bootstrap的需要是将其组件转移到新堆栈中,以及现在创建高阶组件要容易得多。 一切似乎都很简单:结合.form-control.badge.dropdown-menu ,您可以轻松获得多选...



门口的建筑冲突


生成的BsMultiSelect插件直接使用JS bootstrap.js代码,而是使用其依赖项popper.js (香草弹出框架)。 这是因为bootstrap.js中dropdown组件需要在DOM初始化期间找到所谓的toggle元素(在特定情况下,这是一个打开菜单的按钮),如果找不到它,则会崩溃并报错(因为我是直接从js创建的,所以我有“ buttons”当然不是)。 结论:无法(或不利地)直接从JS创建在“ HTML over JS”下锐化的组件。 结论二:您需要对自定义组件进行编程,以便在“ HTML over JS”组件下始终总有一个较轻的“ pure JS”组件。 我已经将此MulitSelect.js不仅彻底清除了代码,还彻底清除了Bootstrap样式。 MulitSelect.js在BsMulitSelect.js中起着相同的作用,而dropper.js的popper.js也起着同样的作用。


关于popper.js的两个词


很棒的图书馆-一个功能。 DropDown.js重复执行,但提供了一个完全受限的接口(同样,因为在“ HTML over JS”中不需要整个API)。 波普尔有比我们想要的更开放的问题。 我对在IE11下发布与Chrome浏览器不同的事件感到失望


关于从IIFE过渡到课程


标准的jQuery插件样板是在IIFE中定义构造函数。 现在,这是IIFE中的一类。 开放性:做私有方法的旧功能方法与ES6 lambda冲突,因此它们在Bootstrap中被“放弃”。 所有方法都是公开的,而伪私有方法的前缀为_即。 秘密的。 我了解我错了,但是我遵循我的惯例-“带有大写字母的公共方法”。 在其他所有方面,BsMultiSelect都采用了“标准” DropDown.js的协议,即 我想将他代表为一种带有肉的样板。


但是,另一个区别是,由于存在汇总,因此我点击了文件..
 import $ from 'jquery' import AddToJQueryPrototype from './AddToJQueryPrototype' import MultiSelect from './MultiSelect' // ... ( (window, $) => { AddToJQueryPrototype('BsMultiSelect', (element, optionsObject, onDispose) => { // ... return new MultiSelect(element, optionsObject, onDispose, facade, window, $); }, $); } )(window, $) 

新协议:插件应发布构造函数 -以免丢失IIFE中的构造函数。 是的,应该保留一个IIFE-没有人删除以标准方式定义window,$和Popper依赖项(对于那些“无法进入模块”的人)的任务。


Eslint和Stylelint Linter配置


我没有义务遵循苛刻的Bootstrap代码样式规则。 当然,他们在可以帮助他们设置空间的环境中进行编写,并且源代码控制的严格性非常好,但是我很难每秒都听到VS Code中lint的痛苦。 在编写自己的插件时,规则可以而且应该大大放松。


Eslint,stylelint可能不会经常出现,但是没有希望研究新规则。 在所有方面,这项成就使我更加恼火。


组织代码和汇总


Bootstrap的ES6可再发行代码由汇总打包为两个版本:独立的bootstrap.js和捆绑包bootstrap.bundle.js-后者包括popper.js。


rollup.config.js的作者对我来说是本能。 所有这些通过push和pop进行的配置转换 ,取决于所需的独立版本或捆绑包版本,看起来都很复杂而令人生畏,幸运的是,编写插件时,您只需要一种类型的捆绑包“独立”,而不必证明我可以做得更好。


软件包的主字段中也指出了Bootstrap的独立版本,即 npm依赖项解析为用户通过<script>加载的文件。 这并不是一个明确的解决方案,但是我的BsMultiSelect插件遵循相同的路径。 在这种情况下,可以将babel帮助程序包含在插件中 ,尽管事实上它们也包含在bootsrap.js中。 复制某种程度上是不正确的...


有趣的是,Bootstrap在jspm下具有并行配置-本机浏览器ES模块加载器 ,其主字段已经是干净的远程代码,没有捆绑的12个组件,但是分别存储在js / dist目录中。 在这里,每个文件都包含babel帮助程序。 Jspm现在正处于十字路口,因此通过创建BsMultiselect忽略它。


但是,问问鉴赏家很有趣,jspm是否会将所有12次重复的助手助手提升到浏览器?

已发现汇总的一大优点-与webpack相比,它的包可读性强。


Bootsrap 4使用Babel 6和BsMultiSelect Babel 7插件


使用更新的rollup-babel-plugin(也在beta中), BsMultiSelect可以轻松迁移到Babel 7 beta。 由于新的@babel/preset-env (转译器的配置“将在其上运行代码的浏览器”), 现在值得移至Babel 7 。 仅使用Internet,就很难理解ES6预设的工作方式,它们经历了漫长的发展,并且积累了许多过时的配置。 最好立即下注Babel 7 + @babel/preset-env


尽管如此,babel的beta错误并不需要等待很长时间:[... nodeList]已在nodeList.concat()中被编译。 我很长一段时间都不了解,将代码转换成jquery调用(这仍然是必需的,但稍后会再介绍)解决了该问题。 问:“为什么不通天塔不与他打交道?”,答案:“进口和拉姆达”。


实践方面


Bootstrap 4及其插件(与所有js代码一样)有两个选项可加载到浏览器中: 通过脚本/样式 (创建“页面”),以及通过程序集节点/ webpack (创建“应用程序”),所以我将继续这两个原则上,情况非常不同,并表示:“页面”和“应用程序”)。
对于页面和应用程序,将使用相同的Bootstrap“分发文件”。 这不是一个显而易见的方法,也不是唯一的解决方案(例如,对于jspmmocha测试,使用了不同的代码),但是在创建自己的插件时,除了遵循该约定并希望达到最佳效果之外,别无他法。


在两个不同的下载选项(页面和应用程序)中使用相同的代码在满足两个需求之间找到平衡,这是插件开发人员面临的主要架构任务。


毕竟,也可以在您的应用程序中临时创建Bootstrap插件。 在这种情况下,您可以很高兴地编写插件代码:多义性和对方案的SASS变量的访问。 但是,当依赖重用时,有必要将插件转移到其自己的npm包中,上述乐趣归结为问题类别:您无法访问SASS变量,并且需要牢记通过脚本连接插件的“页面”的创建者(我的多文件在哪里?)。


访问SASS Bootstrap 4样式变量


我想写Bootstrap CSS类/选择器来编写插件。 在这种情况下,自定义Bootstrap主题时,您可以期望插件进行调整而无需付出额外的努力。


对于自发布的插件,无法访问SASS变量。


现有的CSS类/选择器-未涵盖BsMutliSelect的所有必需样式,例如,您需要ul.form-control min-height ,而在bootstrap.css中只有一个高度为input.form-control的css选择器-您无法应用它为ul 。 其他现有的类/选择器带来了许多多余的样式:例如,如果您想将.form-control中的颜色分配给元素而不分配类.form-control怎么办? 这将不起作用,因为不存在.input-color类的类,其中变量$ input-color将与所有内容“分开”发布。


此外,不可能遵循Bootstrap团队的决定:如果有需要,他们就不会遇到这样的问题-他们使用所需的变量创建CSS类/选择器并对其进行操作。 如果您想辩论,您将不得不与Mark Otto进行解释,如果请求属于“要约”类别,那么即使在CSS选择器中进行外观更改,BS团队中的决策水平也异常高。


我提出以下解决方案。


对于页面(通过script引发插件),您不得不忍受变量的不可访问性。 但是没有必要提供处理CSS的方法-可以通过js参数自定义无法访问的变量,因为它们不多(并且并非所有方案都更改了它们)。 对于BsMultiSelect,有问题的是:禁用颜色,输入颜色,聚焦控制阴影(例如仅10种样式,其中大多数很少更改方案)...


首先,这是该插件所依赖的所有样式的声明...
 $("select[multiple='multiple']").bsMultiSelect({ selectedPanelDefMinHeight: 'calc(2.25rem + 2px)', // default size selectedPanelLgMinHeight: 'calc(2.875rem + 2px)', // LG size selectedPanelSmMinHeight: 'calc(1.8125rem + 2px)', // SM size selectedPanelDisabledBackgroundColor: '#e9ecef', // disabled background selectedPanelFocusBorderColor: '#80bdff', // focus border selectedPanelFocusBoxShadow: '0 0 0 0.2rem rgba(0, 123, 255, 0.25)', // foxus shadow selectedPanelFocusValidBoxShadow: '0 0 0 0.2rem rgba(40, 167, 69, 0.25)', // valid foxus shadow selectedPanelFocusInvalidBoxShadow: '0 0 0 0.2rem rgba(220, 53, 69, 0.25)', // invalid foxus shadow inputColor: '#495057', // color of keyboard entered text selectedItemContentDisabledOpacity: '.65' // btn disabled opacity used }); 

但是对于使用SASS和收集器的应用程序,您可以提供将BsMultiSelect.scss复制到自己的位置,并在其中更正指向_variables.scss的路径。 因此,插件将“接收”变量变量。


全部通过CSS ...
  $("select[multiple='multiple']").bsMultiSelect({ useCss: true }); 

这两个方法是通过两个“适配器”在我的JS代码中明确编写的。 BsMultiSelect实际上是两个插件合而为一。 一个通过js变量使用样式, 另一个则委托此CSS工作。


同时,我必须直接说,即使使用了通过JS参数传递自定义样式,也可能需要使用CSS,这仅仅是因为这些方案的作者通常会非常粗略地完成他们的工作。 还是奇怪。 例如, 出于某种原因, Skethy方案决定菜单不需要悬停效果。 功能必须归档。


但是,通过一个粗略的示例,我希望您能看到该插件如何相对轻松地适应繁重的电路(有必要通过js参数重载这三种样式的值)。


通过js适应方案
 $("select[multiple='multiple']").bsMultiSelect({ selectedPanelFocusBoxShadow:"0px 0px 0px 0.2rem rgba(51,51,51,0.25)", selectedPanelFocusBorderColor:"#333", selectedPanelDisabledBackgroundColor: "#f7f7f9" }); 


这是使用“标准” CSS类.bage.form-control.close等可以实现的最大值。 几乎所有内容都适合该计划,但并非所有内容都适用。


遗憾的是,您当然无法摆脱这三个参数,并非所有架构样式变量都可以通过css选择器/类来访问(我在撒谎,如果您可以将BsMultiSelect.scss复制给自己并携带电路变量,则可以离开,但这并不能完全满足,就像所有以“复制自己”开头的决定一样)。


单击此处: https : //dashboardcode.imtqy.com/BsMultiSelect/indexsketchy.html


Polyfill的


在“我正在在应用程序内部编写一个临时插件”场景中,您将毫无问题地使用@babel/polyfill ,并修补polyfill.io DOM,因为它已经存在于应用程序内部。


将插件移至外部npm模块时,所有乐趣消失了,因为Bootstrap用户尚未决定取悦文档中所需的大量polyfills。


解决方案:所有通天塔都不会变位,而是留给多亲,阻止它这样做,磨牙,转换成jQuery调用(例如,$ .closest中的Node.closest)。 Bootstrap 4本身就采用了这种方法,显然,它是在对抗膨胀。 惊喜 jQuery是一个polyfill。


我同意与Babel一起关注CanIUse.com和MDN.com进行编程并不有趣。 而且代码(对于我来说)很尴尬。


在这里有必要再次从上方突出显示这种情况。 Bootstrap使用两个jQuery和popper.js库。 Popper.js是一个双重香草框架,它本身没有babel,jQuery或外部polyfills。 JQuery已经由使用babel的grunt打包,但是以某种方式神奇地没有了它的polyfills和helper。 第三方Bootstrap插件(如BsMultiSelct)使用Babel7。您的产品可能仍使用其他东西。 没有单一的polyphile平台,预计会有多个代码重复,有四个最接近的实现都加载到浏览器中。 但是对此无能为力。


如果在创建自己的插件时仍然使用了多文件,则需要记住,如果应用程序具有内联脚本(即<script>$( function() {/*..*/}) </script> ),您只需同步下载多文件(否则,内联代码可能比插件加载时更早开始执行)。 即 例如webpack-polyfill-injector (我所知道的最丰富的polyphil注入器),我需要对其进行控制,以便它不会决定异步加载polyphiles(默认行为)。


没有jQuery


jQuery感觉有些毒,它与Babel / ES6竞争并使其模糊不清,但这并不是永远的。 有一个分支v4-whithout-jquery ,它已经在池请求中,它计划发布bootstrap-nojquery c版本4.3 。 以前,事件的名称空间被称为拒绝jquery的最大问题,尽管很明显,没有它们也可以编写(BsMultiSelect却没有)。 显然决定了。


还宣布,从版本4.3开始,可以将原始组件分别加载到浏览器中(仅适用于“应用程序”方案)。 原始组件会变成 “像BsMultiSelect一样”吗? 不行 如果BS团队需要一些SASS变量,他们将为自己创建CSS类/选择器,并将通过JS(“功能CSS”)对其进行操作。 自定义功能创建者不可用。


第5版的 sass到post-css https://github.com/twbs/bootstrap/projects/11的可能过渡基本上不会改变任何内容。 或更改所有内容:“基于HTML的JS”。


Bootstrap 5将必须就如何集成到Babel多文件以及如何修补DOM方面建立建议。 这里的预测或多或少是明确的:完全不同的程序集将提供给页面创建者和应用程序创建者。


总结


当您使用临时方法在Babel上编写Bootstrap 4组件而没有考虑重用时,这意味着多义字符以及从何处获取样式变量,但您并不了解悲伤。


但是,如果您将插件制作为单独的npm软件包-并希望按照Bootstrap 4本身的精神做出决定,那么乐趣就会变得越来越少,您思考的频率就会越来越长。 您可能必须立即决定谁是您的用户并提供不同的版本,一个用于将捆绑包构建应用程序的用户,另一个用于编写页面,即 加载插件脚本。

Source: https://habr.com/ru/post/zh-CN416235/


All Articles