tapable

lazysunday發表於2018-06-27

Tapable 所提供的 plugin 方法類似於 addEventListen 監聽事件,apply 方法類似於事件觸發函式 trigger

plugin

Tapable.prototype.plugin = function plugin(name, fn) {
    // 將函式注入多個事件流中
    if (Array.isArray(name)) {
        name.forEach(function(name) {
            this.plugin(name, fn);
        }, this);
        return;
    }
    // 如果不存在該事件流 新建並將函式插入
    if (!this._plugins[name]) this._plugins[name] = [fn];
    // 存在就新增執行函式
    else this._plugins[name].push(fn);
};複製程式碼

hasPlugins

Tapable.prototype.hasPlugins = function hasPlugins(name) {
    // 嘗試獲取對應事件流
    var plugins = this._plugins[name];
    // 存在事件流且有可執行函式
    return plugins && plugins.length > 0;
};複製程式碼

apply

Tapable.prototype.apply = function apply(...fns) {
    // 遍歷所有引數並執行
    for (var i = 0; i < fns.length; i++) {
        fns[i].apply(this);
    }
};複製程式碼

  該函式並不直接關聯於_plugins物件,而是按照引數傳入順序依次執行。

applyPlugins

  依次遍歷指定name的事件流,不同名字的函式可接受引數數量不一樣。

// 不接受傳參
Tapable.prototype.applyPlugins0 = function applyPlugins0(name) {
    var plugins = this._plugins[name];
    if (!plugins) return;
    for (var i = 0; i < plugins.length; i++)
        plugins[i].call(this);
};
// 接受一個引數
Tapable.prototype.applyPlugins1 = function applyPlugins1(name, param) {
    var plugins = this._plugins[name];
    if (!plugins) return;
    for (var i = 0; i < plugins.length; i++)
        plugins[i].call(this, param);
};
...
// 接受五個引數
Tapable.prototype.applyPlugins5 = function applyPlugins5(name, param1, param2) {
    var plugins = this._plugins[name];
    if (!plugins) return;
    for (var i = 0; i < plugins.length; i++)
        plugins[i].call(this, param1, param2, param3, param4, param5);
};
// 接受任意數量引數
Tapable.prototype.applyPlugins = function applyPlugins(name) {
    var args = Array.prototype.slice.call(arguments, 1);    if (!this._plugins[name]) return;
    // var args = Array.prototype.slice.call(arguments, 1);
    var plugins = this._plugins[name];
    for (var i = 0; i < plugins.length; i++)
        plugins[i].apply(this, args);
};複製程式碼

applyPluginsWaterfall

  事件流執行過程中,每一次執行的返回值會作為下一次的引數(僅限於第一個引數)。

Tapable.prototype.applyPluginsWaterfall0 = function applyPluginsWaterfall0(name, init) {
    var plugins = this._plugins[name];
    if (!plugins) return init;
    var current = init;
    for (var i = 0; i < plugins.length; i++)
        current = plugins[i].call(this, current);
    return current;
};
// ...1
// ...
// ...5
Tapable.prototype.applyPluginsWaterfall = function applyPluginsWaterfall(name, init) {    if(!this._plugins[name]) return init;    var args = Array.prototype.slice.call(arguments, 1);    var plugins = this._plugins[name];    var current = init;    for(var i = 0; i < plugins.length; i++) {        args[0] = current;        current = plugins[i].apply(this, args);    }    return current;};複製程式碼

applyPluginsBailResult

  事件流執行過程中,返回第一個不是undefined的值,後續函式不執行。

Tapable.prototype.applyPluginsBailResult = function applyPluginsBailResult(name, ...args) {
    if (!this._plugins[name]) return;
    // var args = Array.prototype.slice.call(arguments, 1);
    var plugins = this._plugins[name];
    for (var i = 0; i < plugins.length; i++) {
        var result = plugins[i].apply(this, args);
        if (typeof result !== "undefined") {
            return result;
        }
    }
};

// 1,2,3,4,5複製程式碼

applyPluginsAsync

Tapable.prototype.applyPluginsAsync = function applyPluginsAsyncSeries(name) {    var args = Array.prototype.slice.call(arguments, 1);    var callback = args.pop();    var plugins = this._plugins[name];    if(!plugins || plugins.length === 0) return callback();    var i = 0;    var _this = this;    args.push(copyProperties(callback, function next(err) {        if(err) return callback(err);        i++;        if(i >= plugins.length) {            return callback();        }        plugins[i].apply(_this, args);    }));    plugins[0].apply(this, args);};複製程式碼