分类 JavaScript 下的文章

今天正好有个老朋友聊起来jquery源码,他对于源码不了解,我抱着学习交流的心态,给他讲解了核心实现。(好像自己也鸽了好长时间)

顺便在哪个cdn服务商找个jquery文件打开, 我这里用的1.2.3版本为例,最新版本也差不多,只有两三处变化https://cdnjs.cloudflare.com/ajax/libs/jquery/1.2.3/jquery.js

源码分析

17-20行传入选择器,返回自身new出来的init方法,估计你们也没用过$()的第二个参数,这里省略掉

var jQuery = window.jQuery = function(selector) {
    return new jQuery.prototype.init(selector);
}

26-27行这就是为什么总是用$开头的原因,挂载到window对象下,属于全局变量

// Map the jQuery namespace to the '$' one
window.$ = jQuery;

36-547行剔除我们不需要的保留核心,留下init方法,内部做了jquery实例与选择器的判断,这里我们忽略掉,简化

jQuery.fn = jQuery.prototype = {
    init: function(selector) {
        var nodes = document.querySelectorAll(selector);
        for (var i in nodes) {
            this[i] = nodes[i];
        }
        return this;
    }
    //此处省略十万字
}

549行来上一段这个,jquery原型链传递给jquery原型下init方法的原型,回头再看new时候的代码,很清楚明了

jQuery.prototype.init.prototype = jQuery.prototype;

完整实现

在jQuery的原型上继续增加功能就很接近初版jQuery了,这里我是简单实现了text()方法

    var jQuery= function (selector) {
        return new jQuery.fn.init(selector);
    }

    jQuery.fn = jQuery.prototype = {
        init: function (selector) {
            var nodes = document.querySelectorAll(selector);
            for (var i in nodes) {
                this[i] = nodes[i];
            }
            return this;
        },
        element: function (callback) {
            for (var i = 0; i < this.length; i++) {
                callback(this[i]);
            }
        },
        text: function (content) {
            if (content == '' || content) {
                this.element(function (node) {
                    node.innerHTML = content;
                })
                return content;
            } else {
                return this[0].innerHTML;
            }
        },
    }

    jQuery.prototype.init.prototype = jQuery.prototype;

    window.$ = jQuery;

结束

核心其实一点不复杂,插件的实现我倒是很喜欢,自身的功能我看来大部分全是用插件实现的,工具自身的巧妙设计加上便利性。

在传统页面制作上jquery一把梭用的很舒服,但MVVM的出现改变了大家的思考方式,只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,对于项目管理轻松不少。

如果有简单需求的单页上,jquery还是有用武之地的,上MVVM只能是徒增麻烦。

如果有新手学习 nodejs,获取 url post 传回的参数时,会发生和我一样的问题,今天就来解决这个小麻烦

node.js 不像 php 这种老牌后端语言有特定的获取外部参数的做法,毕竟是个新生力量,希望后来的版本能够更加便捷高效


//正常的获取值
app.get('/', (req, res) => {
  console.log(req.query);
  res.send('完成');
});
app.post('/', (req, res) => {
  console.log(req.body);
  res.send('完成');
});

正常输出的话,你的预想是这样的...

// GET请求
{
  name: '冯小贤',
  age: '18'
}
// 完成

// POST请求
{
  name: '冯小贤',
  age: '18'
}
// 完成

然而并不是!!!

// 两次的输出会是这样!!!
{ }
//undefined

这是因为我们这里缺少一个模块,express的中间件 body-parser

官方说明
Node.js body parsing middleware.
Parse incoming request bodies in a middleware before your handlers, available under the req.body property.

基本就是说,解析客户端请求的body中的内容,JSON编码处理和url编码处理


接下来我们就来安装 body-parser

// 安装 body-parser
npm install body-parser

// 导入 app.js
var bodyParser = require('body-parser');
app.use(bodyParser());

//这样就可以使用 req.body 来获取 post 传递来的值了
app.post('/', (req, res) => {
  console.log(req.body);
  res.send('完成');
});

// json就是用  app.use(bodyParser.json())

学习没有动力,那吃枣是?的,学习 nodejs 的过程中,我来给大家一点提神醒脑的?

这里我是用了 cnodejs社区 最简单的爬虫小教程做基础改鳝,完成的

//初始化项目
npm init
//启动 app.js
node app.js
//你就可以愉♂快的玩耍了(代码见文章末尾)
如不知道如何使用 nodejs
Linux玩家可以看 我的这篇文章;Windows玩家可以直接去官网下载 .msi ,下一步下一步安装 直达车

基本的爬取思路

  1. 页面的分页按钮,抓到在此页出现的所有小姐姐的页面链接,存储下来
  2. 使用 eventproxy 来并发访问每个小姐姐的页面
  3. 访问的过程中,使用 cheerio(类似jquery的模块) 来匹配我们需要的图片地址 ,记录找到的所有图片地址
  4. http 去请求每张图片地址,保存二进制数据流
  5. fs将二进制数据流,输出成图片文件,文件名从原始地址提取出来
  6. 保存至 文件夹
这里我怕由于请求过于庞大,使用 express 构建静态页面提供 查询下载,降低爬取的站点被爬死的可能性

下载地址:xjj.zip