官方对tapable
的定义是钩子,业界很多写tapable
的觉得它是发布订阅模式,它确实很像发布订阅模式,但是不完全是,至于官方说的钩子,个人感觉在webpack
内部可以称作钩子,因为是官方定义的,所以肯定是按照设计的想法来使用的,如果是你自己使用,操作不当可能就不是钩子了,毕竟只是一个工具,你拿扳手当锤子也没人说你什么,以上是个人见解,下面附上一些验证的思路。
不喜欢论证,喜欢看使用的可以跳过这个小标题,到第二个标题
tapable使用详解
。
先来看看什么是发布订阅,发布订阅是需要分为两个部分,一个是发布,一个是订阅。
对应转化成代码应该是下面这样的:
/**
* 发布订阅模式
*/
// 掘金是调度中心
class Jujin {// 掘金的所有用户users = {};// 注册用户registerUser(userInfo) {const user = new User(userInfo);// 内部注册的用户才有权限订阅user.subscribe = (uuid, callback) => {user.subscribes[uuid] = callback;}// 内部注册的用户才有权限发布消息user.publish = (message) => {this.#publish(user.uuid, message);}this.users[user.uuid] = user;return user;}#publish(uuid, message) {const users = Object.values(this.users);for (let user of users) {const callback = user.subscribes[uuid];if (callback) {callback(message);}}}
}
class User {constructor(userInfo) {this.name = userInfo.name;this.age = userInfo.age;this.uuid = Math.random().toString(36).substr(2);// 订阅的用户this.subscribes = {};}
}
// 掘金上线啦
const jujin = new Jujin();
// 我在掘金上注册了一个账号
const 田八 = jujin.registerUser({name: '田八',age: 18
});
// 你在掘金上注册了一个账号
const 你 = jujin.registerUser({name: '你',age: 18
});
// 你关注了我
你.subscribe(田八.uuid, (message) => {console.log(message);
});
// 我发布了一篇文章
田八.publish('你好,我是田八!');
// 路人甲在掘金上注册了一个账号
const 路人甲 = jujin.registerUser({name: '路人甲',age: 18
});
// 路人甲发布了一篇文章
路人甲.publish('你好,我是路人甲!');
// 可惜路人甲没有人关注,所以没有人看到他的文章
执行结果
代码不是正儿八经的发布订阅模式写的,但是思想还是差不多的,主要是为了还原我自己画的图,正儿八经的发布订阅模式有三个模块,一个是发布者,一个是订阅者,一个调度中心,我这里发布者和订阅者合并到一起了,调度中心还分管着权限。
这里主要看使用方式,最典型的就是dom
的events
事件:
const btn = document.getElementById('button');
btn.addEventListener('click', () => {console.log('订阅点击事件')
});
// 发布点击事件
btn.click();
等会再来讨论这个代码,接下来看看钩子。
钩子函数听得比较多,主要来源是React
,还有Vue3
的composition api
,钩子函数是一种消息处理机制,本质是用来处理系统消息的,通过应用系统调用分配,将其挂入应用系统,看看百度百科的解释(不需要你看文档,稍微会点百度也可以知道):钩子。
来看上面写的其实就知道钩子是和应用程序挂钩的,是由应用程序提供的,简单的实现一下:
class HooksApp {hooks = {'onBeforeCreated': [],'onCreated': [],'onBeforeDestroyed': [],'onDestroyed': []};onHooks(hookName, callback) {if (this.hooks[hookName]) {this.hooks[hookName].push(callback);}}created() {this.hooks.onBeforeCreated.forEach((callback) => {callback();});// 创建需要一秒钟const now = new Date();while (new Date() - now < 1000) ;this.hooks.onCreated.forEach((callback) => {callback();});}update() {console.log('我有一个update,我不提供钩子!')}destroy() {this.hooks.onBefore