写这篇文章的目的,一方面是介绍一下自己编写的模块化 DOM 库 domq.js,另一方面是希望大家对 jQuery 有一个正确的认识,即使 jQuery 已经逐渐退出历史舞台,但是它的 API 将会以另外一种形式存在下去。

GitHub:https://github.com/nzbin/domq

文档:https://nzbin.gitbooks.io/domq-api/usage.html

jQuery 不会死去

从 GitHub 放弃 jQuery,再到 Bootstrap 5 宣布移除 jQuery,看来一个时代终究要落下帷幕。

为什么我们会放弃 jQuery 呢?原因无非这样几个:不需要再进行浏览器的兼容,原生 DOM 查找已经很方便,AJAX 请求有更好的替代方式等等。

在我看来 jQuery 最大的弊端是无法分模块引入,直接引入整个库实在有些不妥,毕竟太多功能已经没有用武之地。但是 jQuery 的 DOM 操作依然很有必要。很多人对我的这个观点有些疑问。其实在使用 MVVM 框架的时候,DOM 操作确实已经很少。但是我们也不可能总是做一些 CRUD 的功能。对于复杂的业务需求仍然需要一些 DOM 操作。

假如 jQuery 可以把 DOM 操作相关的功能模块分离出来,或许还有很大的使用空间。

原生当道

在平时的项目中,越来越多的人选择用原生 JS 去操作对象,比如获取元素属性,宽高,定位等等。

早在几年前,github 上就有很多文章介绍如何用原生 JS 代替 jQuery,比如 YouDontNeedJQueryYouMightNotNeedjQuery等。就我个人而言,纯 JS 操作确实很简单,但是并不是很优雅,复杂一点的操作还要经常翻 MDN。

// jQuery
$('.my #awesome selector'); // JS
document.querySelectorAll('.my #awesome selector');
// jQuery
$(el).hide(); // JS
el.style.display = 'none';
// jQuery
$(el).after(htmlString); // JS
el.insertAdjacentHTML('afterend', htmlString);

以上是 jQuery 和原生 JS 对比的一个缩影,结果显而易见,jQuery 的 API 更加简洁。除此之外,jQuery API 的使用形式也非常统一。相反,原生 JS 的 API 使用方式就比较多样了,既有赋值,又有传参等。另外原生 JS 的 API 名称冗长,不方便记忆。这也是很多 JS 库诞生的意义。

很多插件一般都会有一个 utils 的文件,基本会对原生方法做一个简单封装并提供一些工具方法。

Zepto 的优势与弱势

Zepto 是一个思想超前的库,为什么我会有这样的结论?Zepto 对原生方法做了进一步的抽象,使用更简单。正如我在上文说过的,既然 jQuery 的 API 简洁易用,而且我们也更加熟悉,那我们为什么不将 jQuery 和原生 JS 结合起来呢?令人惊讶的是,早在 2010 年,Zepto 的作者就已经这样去做了。用原生 JS 实现了 jQuery 的大部分 API,可替代率接近九成吧,至少在我编写的插件中,几乎可以替换掉所有的 jQuery API。而且 Zepto 也不是一味的使用 document.querySelector 方法,而是根据性能优劣,有选择的使用 document.getElementById 以及 document.querySelector 等。

但是 Zepto 也有一些显而易见的缺陷,毕竟还是上个时代的产物,首先就是无法按需加载,现在我们在写项目的时候更愿意根据自己的需要引入某些方法,而不是将整个库全部引入,虽然 Zepto 的体积不大,但是作为强迫症还是有一些厌恶。另外就是 Zepto 本身也有一些 bug,比如 scrollTopscrollLeft 方法。其它不同参见源码。

// Zepto
scrollTop: function(value) {
if (!this.length) return
var hasScrollTop = 'scrollTop' in this[0]
if (value === undefined) return hasScrollTop ? this[0].scrollTop : this[0].pageYOffset
return this.each(hasScrollTop ?
function() { this.scrollTop = value } :
function() { this.scrollTo(this.scrollX, value) })
}

document 元素无法获得正确的值,我对这个问题提过 pr 但是没有回应,Zepto 目前基本已经停止维护。正确的方法如下:

// Domq
function scrollTop(value) {
if (!this.length) return
var hasScrollTop = 'scrollTop' in this[0]
if (value === undefined) return hasScrollTop
? this[0].scrollTop
: isWindow(this[0])
? this[0].pageYOffset
: this[0].defaultView.pageYOffset;
return this.each(hasScrollTop ?
function () { this.scrollTop = value } :
function () { this.scrollTo(this.scrollX, value) })
}

Domq 的使命

形如 jQuery 的 DOM 操作库有很多,比如 bonzo$dom,但是在我重构 jQuery 插件时,我发现没有办法用这些库直接替换 jQuery,只有 Zepto 相对完美,但是我又不希望引入额外的无用的方法。

最后我决定改造 Zepto,使之更符合现在的使用习惯。多说一点,个人觉得 Zepto 的核心函数稍显凌乱,命名空间既有 zepto、又有 $Z,感觉非常混乱,而 domq 的核心函数只有 D 这一个命名空间,形态及功能和 jQuery 的核心函数几乎一样,可以认为是一个 mini 版的 jQuery。

// Zepto 核心方法
var Zepto = (function() {
var zepto = {};
...
zepto.Z = function(dom, selector) {
return new Z(dom, selector)
}
...
$ = function(selector, context) {
return zepto.init(selector, context)
}
...
})()
// Domq 核心方法
var D = function (selector, context) {
return new D.fn.init(selector, context);
} D.fn = D.prototype = {
...
init: function(){
...
}
...
}

当然, Domq 最关键的还是按需加载,根据需要挂载方法,尽量减少不必要的代码。使用方式很简单,但是你需要创建一个独立文件,重新挂载需要的方法到 D 命名空间上,这在编写插件时非常有用。

import {
D,
isArray,
addClass
} from 'domq.js/src/domq.modular'; // 静态方法
const methods = {
isArray
} // 原型方法
const fnMethods = {
addClass
} D.extend(methods);
D.fn.extend(fnMethods);

另外,在做项目时经常会用到一些工具方法,这时候用一个工具库暴露这些方法或许是最好的方式。Domq 也有一些常用的工具方法,不过还需要再迭代一下。

D.type()
D.contains()
D.camelCase()
D.isFunction()
D.isWindow()
D.isEmptyObject()
D.isPlainObject()
D.isNumeric()
D.isArray()
D.inArray()
...

Domq 没有太多新的东西,所以也没有太多可以介绍的,它已经在插件 PhotoViewer 以及实际项目中得以运用,欢迎大家下载使用。

总结

这是一个好的时代,也是一个坏的时代,jQuery 的落幕确实让人感叹,但是我们完全没必要因为 jQuery 的落幕而放弃 jQuery 的使用方式。正如前文所说,jQuery 的 DOM 操作在我看来依然是最好用的,所以,你不需要 jQuery,但你需要一个 DOM 库。

GitHub:https://github.com/nzbin/domq

你不需要 jQuery,但你需要一个 DOM 库的更多相关文章

  1. jQuery对象与JS原生dom对象之间的转换

    jQuery就是JS的一个扩展库,工具库,提供很多方便快捷的方法,所以将JS对象转换为jQuery对象后,能更方便地操作这个对象.但是jQuery对象也不是万能的,有一些JS对象有的能,jQuery对 ...

  2. 基于JQuery.timer插件实现一个计时器

    基于JQuery.timer插件实现一个计时器,需要的朋友可以参考下.   先去官网下载jQuery Timers插件 ,然后引用到html中.这里是1.2 version 复制代码代码如下: < ...

  3. 【jQuery插件】用jQuery Masonry快速构建一个pinterest网站布局(转)

    [jQuery插件]用jQuery Masonry快速构建一个pinterest网站布局 时间:2011年03月21日作者:愚人码头查看次数:29,744 views评论次数:25条评论 前段时间领导 ...

  4. jquery用div模拟一个下拉列表框

    原文 jquery用div模拟一个下拉列表框 今天分享一个用我自己用jquery写的,用div模拟下拉列表select,这个效果网上有很多,但是写一个有自己思路的代码效果,更有成就感,先看截图: 自我 ...

  5. jQuery为啥要提供一个load()方法?

    上午的时候,找个闲暇事件整理之前整理的一些关于jQuery的东西,看到了一个之前做的jQuery的$(document).ready()与window.onload()方法的比較. 上面两个方法最重要 ...

  6. vue setTimeout用法 jquery滚动到某一个div的底部

    //vue 中setTimeOut用法 var $this = this; setTimeout(function(){ $this.goEnd() }, 10); goEnd:function(){ ...

  7. jQuery源码的一个坑

    纯吐槽 大半夜也真是够了,想学着jQ造个小轮子巩固下js,结果一开始就卡住了. 虽然之前也看过源码,但是主要是研究方法实现什么的,对于框架主函数和入口结构不怎么熟悉,于是想着一步一步调试看看. $(' ...

  8. 使用jQuery和CSS3实现一个数字时钟

    点击进入更详细教程及源码下载     在线演示 我们经常会在网站中看见一个时钟的效果.今天向大家分享一个使用jQuery和CSS3实现一个数字时钟教程. http://www.html5cn.org/ ...

  9. jQuery 是javascript的一个库(常用插件、处理器)

    jQuery校验官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation jQuery就是javascript的一个库,把我 ...

随机推荐

  1. 解决@ResponseBody注解返回的json中文乱码问题

    1. 简介 主要解决@ResponseBody注解返回的json中文乱码问题. 2.解决方案 2.1mvc加上注解(推荐此方法) 在mvc配置文件中假如下面配置(写在 <mvc:annotati ...

  2. 知识科普:IM聊天应用是如何将消息发送给对方的?(非技术篇)

    1.引言 沟通是人类的最基本需求,复杂多变的沟通内容.沟通方式,正是人类文明之所以如此璀璨的关键所在.   在自然界中,要完成一件事情的沟通,我们可以直接通过声音传递给对方,这是再平常不过的事了(靠“ ...

  3. 在macos上基于python2.7安装PyQt5

    在python3上面安装PyQt5是十分简单的,可是,在python2.7上安装这个东西,着实让人折腾了一把.要总结一下,年纪大了,记性不好. 首先要安装最新版的Qt和python2,命令如下: br ...

  4. AI - TensorFlow - 可视化工具TensorBoard

    TensorBoard TensorFlow自带的可视化工具,能够以直观的流程图的方式,清楚展示出整个神经网络的结构和框架,便于理解模型和发现问题. 可视化学习:https://www.tensorf ...

  5. 从壹开始前后端分离[.netCore 不定期 ] 36 ║解决JWT自定义中间件授权过期问题

    缘起 哈喽,老张的不定期更新的日常又开始了,在咱们的前后端分离的.net core 框架中,虽然已经实现了权限验证<框架之五 || Swagger的使用 3.3 JWT权限验证[修改]>, ...

  6. c#进阶一:使用ILDASM来查看c#中间语言

    平时工作的时候总是使用ctrl c+ctrl v去快速开发实现业务功能,但是在工作之余,我们也应该要注意静下心来去学习和提高自己.进阶的文章随性来写,不定时更新.希望可以和大家共同学习,共同进步.今天 ...

  7. Java运行时环境---ClassLoader类加载机制

    背景:听说ClassLoader类加载机制是进入BAT的必经之路. ClassLoader总述: 普通的Java开发其实用到ClassLoader的地方并不多,但是理解透彻ClassLoader类的加 ...

  8. dedecms织梦上下页标签和CSS

    模板中的分页部分源码: <div class="pagination-wrapper" style= "font-size:20pt;color:red;text- ...

  9. 获取url特定参数

    获取通过url拼接的特定参数值: // 获取url指定参数 function getUrlParams(name) { var reg = new RegExp("(^|&)&quo ...

  10. 渐进式Web应用程序的深入概述

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://www.grapecity.com.cn/blogs/wijmo-depth-ove ...