转载

如何在没有 jQuery 的情况下使用 Bootstrap 组件

你使用 Bootstrap 的 JavaScript 组件 吗? 你喜欢 Vanilla JavaScript 吗? 如果答案是肯定的,那么你应该会对 Native JavaScript for Bootstrap 项目感兴趣,这个项目的目标是消除组件对 jQuery 的依赖,改用原生 JavaScript。

为什么?

最大的动力关乎性能。

benchmarks 的很多报告显示,原生 JavaScript 的执行速度优于 jQuery,这会带来潜在的性能提升。

另一个性能优势在于降低了页面的大小。现在来做个快速的对比。下面所有数字都是通过 gzip 压缩过后的文件大小,单位为 KB。bootstrap.js 指原来的 Bootstrap 脚本,bsn.js 则代表 Bootstrap Native 脚本,jq 表示 jQuery。这里我们看到所有需要的组件组成的文件包,但需要指出的是,这两个库都是模块化结构,可以只加载需要的组件及其依赖的组件。

Bootstrap.js:

  • jq 3.1.0 + bootstrap.js = 34.5 + 11.2 = 45.7

  • jq 3.1.0 slim + bootstrap.js = 27.2 + 11.2 = 38.4

  • jq 2.2.4 + bootstrap.js = 34.3 + 11.2 = 45.5

  • jq 1.12.4 + bootstrap.js = 38.8 + 11.2 = 50.0

Native JavaScript for Bootstrap:

  • minifill + bsn.js = 2.4 + 7.8 = 10.2

  • polyfill.io(on chrome 54) + bsn.js = 1.1 + 7.8 = 8.9

  • polyfill.io(on IE 8) + bsn.js = 12.1 + 7.8 = 19.9

( IE8 下 polyfill.io 的大小来源于 这里 。这些 polyfill 会在下一节讨论 )

如何在没有 jQuery 的情况下使用 Bootstrap 组件

所以使用 Bootstrap 组件时,大小范围在 [38.4, 50.0] KB,而使用 Bootstrap Native,这个范围缩小到 [8.9, 19.9] KB.

浏览器支持

关于浏览器支持,是与 原来 Bootstrap 基于 jQuery 的脚本 进行比较,它支持 最新的主要的移动浏览器和桌面浏览器的最新版本及 IE8+ 。这由两个 polyfill 策略实现。

第一个解决方案是使用 Polyfill.io 服务。你唯一需要做的事情就是在页面内插入 script 标签来引入适合每个浏览器的 polyfill。

<script src="https://cdn.polyfill.io/v2/polyfill.js"></script>

这个服务可以根据网站上实际使用的功能进行配置,以定制其响应。详情参阅 Pollyfill.io 的文档 。

除此之外,还可以使用 minifill ,一个由项目作者提供支持的轻量自定义的 polyfill。

用法

用法与原来的 Bootstrap 脚本类似,只是不再使用 jQuery,而用由这个项目支持的 Bootstrap 脚本。另外,如果需要的话,还要加入 polyfill。

现在在 </body> 标签之前引入所需要的脚本文件:

<script src="https://cdn.jsdelivr.net/bootstrap.native/1.0.4/bootstrap-native.js"></script>

文档页面 上还列举了一些其它的 CDN URL。也可以将文件下载到本地,在本地使用。

如果需要用到 polyfill,它们需要在 <head> 标签中引入:

<script src="https://cdn.jsdelivr.net/minifill/0.0.3/minifill.min.js"> </script>
<!--[if IE]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<![endif]-->

这段代码采用 minifill polyfill。

参阅 项目文档页面 查看更多操作指南。

确切的说,它并没有一一对应地移植原有脚本所支持的特性。作者故意选择留下了一些小功能,特别是不常使用的那些。主要是为了性能方面的原因,也是为了简化开发。

让我们来看看这些情况。

自定义事件

许多 Bootstrap 组件都会在生命周期中触发事件。例如,Modal 会触发两个事件,分别是在它打印后和关闭后(实际上每个动作都对应两个事件,一个在动作前发生('show'),一个在动作后发生('shown'))。

Tab 组件在切换标签的时候也有类似的事件通知其观察者:为当前标签发送一个隐藏事件,同时为将要显示的标签发送一个显示事件。

Bootstrap Native 则不同,它只为 Carousel 和 Button 提供了这些事件。最初的 Carousel 会在两张幻灯片之间切换的时候触发一对事件。一个是 'slide',在切换发生前发生,另一个是 'slid',在切换结束后发生。传递给事件处理函数的事件对象有两个属性与切换有关,direction 和 relatedTarget。

下面的 jQuery 代码进行了展示:

$carousel  .on('slide.bs.carousel', function(e) {
    var caption = $(e.relatedTarget).find('.carousel-caption').text();
    console.log('About to slide to the ' + e.direction + ' to slide ' +  caption);
  })
  .on('slid.bs.carousel', function(e) {
    var caption = $(e.relatedTarget).find('.carousel-caption').text();
    console.log('Slid to the ' + e.direction + ' to slide ' + caption);
  });

Bootstrap Native 也支持这两个事件,但事件对象不包含 diretion 和 relatedTarget 这两个属性。我们这可以这样用原生 JavaScript 重写上面的代码:

carousel.addEventListener('slide.bs.carousel', function(e) {
  console.log('About to slide');
});

carousel.addEventListener('slid.bs.carousel', function(e) {
  console.log('Slid');
});

如果其它组件需要自定义事件怎么办?实现起来并不难。我们可以参考 Bootstrap Native 的 Carousel 组件的代码,使用 CustomEvent API 。

首先创建事件对象:

if (('CustomEvent' in window) && window.dispatchEvent) {
  slid =  new CustomEvent("slid.bs.carousel");
  slide = new CustomEvent("slide.bs.carousel");
}

当切换开始时,触发 ‘slide’ 事件:

if (slide) {
  this.carousel.dispatchEvent(slide);
}

最后在切换结果时触发 ‘slid’ 事件:

if (slid) {
  self.carousel.dispatchEvent(slid);
}

基于这个模式,也很容易给其它组件添加类似的代码。

CustomEvent API 不太容易在每个浏览器都实现 ,不过上面的 plyfill 会有所帮助。

编程 API

Bootstrap 组件的 API 允许使用 JavaScript 来进行初始化和控制。例如,Modal 组件有 3 个方法用于控制其可见性::

$('#mymodal').modal('show')
$('#mymodal').modal('hide')
$('#mymodal').modal('toggle')

Bootstrap Native 一般不提供这些编程控制。上述方法已不再存在于 Modal,以及 Dropdonw,Tab,Alert 和 Carousel。

其它不同点

如果我们对组件进行并行比较,很明显 Bootstrap Native 不是一个文本端口,在某些情况下它删除功能,而在其他情况下它添加一些新的东西。

比如,我们在 Tooltip 中必须显式初始化 Bootstrap,因为性能原因, data-api 将选择性加入 。在 Bootstrap Native 中,只要 DATA API 属性被正确设置,初始化工作会自动执行。另外,Native 版本可以自动放置于标题栏,不需要额外选择。但是它不覆盖像 Bootstrap 那样的模板系统。

下拉菜单提供另一个关于 刻意 实现的选择 的例子,它相对于 Bootstrap 组件略有差异。jQuery 下拉菜单会在点击菜单 item 后关闭,而 Native 菜单会保持打开状态。

键盘输入处理也是不完整的。标签导航有用,但是其他操作是 部分实现 的 。

在 Modal 中,没有用于指定加载组件内容的来源的 remote 选项 ,但是有一个可以动态生成内容的模板系统。

对于 Carousel 来说,jQuery 组件默认会响应键盘输入,而在原生 JavaScript 的版本中,需要通过 data-keyboard 属性来启用这个功能:

<div id="carousel" class="carousel slide" ... data-keyboard="true">

对于这个组件的另一个不同之处在于如何定义持续时间的选项。这个选项的值决定了从当前幻灯片切换到下一个幻灯片的过渡效果持续的时间。两个库定义的默认时间都是 600 毫秒,对于大多数情况来说这都是一个合理的时间。

如果我们想改变这个时间,因为在两个库中的动画都是通过 CSS 实现的,所以我们首先要添加一些 CSS 规则来覆盖默认的持续时间。

Bootstrap 中需要使用一些 jQuery 代码来修改这个时间,这通过 JavaScript 的硬代码实现:

$carousel.data()['bs.carousel'].constructor.TRANSITION_DURATION = 2000;

另一方面,Bootstrap Native 允许通过组件根元素上的 data-duration 属性来设置,处理起来更容易:

<div id="carousel" class="carousel slide" data-ride="carousel" data-interval="false" data-duration="2000">

其它组件(比如 Modal 和 Tooltip)也可以使用相同的选项来改变过渡动画的时间。

对于其它问题和解释,请参阅 文档页 和项目的  issue tracker 。

我觉得这个项目非常有意思,但我不会很快摒弃原来的 jQuery 版本。实际上,在其它‘jQuery 对战 Vanilla JS’的比较中,哪一个胜出取决于具体的使用情况。

上一节研究的问题不应该是主要阻碍,所以如果你不是在寻找一个完美的逐字逐句转换 Bootstrap JavaScript 组件的工具,并且已经准备好应付一些细节上的差异,这可能是正确的解决方案。

另外,值得一提的是,该项目正积极发展,可以在 GitHub tracker 上快速返馈问题。

原文  https://www.oschina.net/translate/use-bootstrap-components-without-jquery
正文到此结束
Loading...