• webpack4.X之tapable实例对象SyncHook源码


    模拟手写SyncHook源码

    const SyncHook=require('./SyncHook.js')
    
    let hook=new SyncHook(["name","age"])
    
    hook.tap('fn1',function(name,age){
        console.log('fn1--->',name,age)
    })
    
    hook.tap('fn2',function(name,age){
        console.log('fn2--->',name,age)
    })
    
    hook.call('lw',18)
    class Hook {
        constructor(args = []) {
          this.args = args
          this.taps = []  // 将来用于存放组装好的 {}
          this._x = undefined  // 将来在代码工厂函数中会给 _x = [f1, f2, f3....]
        }
      
        tap(options, fn) {
          if (typeof options === 'string') {
            options = { name: options }
          }
          options = Object.assign({ fn }, options)  // { fn:... name:fn1 }
      
          // 调用以下方法将组装好的 options 添加至 []
          this._insert(options)
        }
      
        _insert(options) {
          this.taps[this.taps.length] = options
        }
      
        call(...args) {
          // 01 创建将来要具体执行的函数代码结构
          let callFn = this._createCall()
          // 02 调用上述的函数(args传入进去)
          return callFn.apply(this, args)
        }
      
        _createCall() {
          return this.compile({
            taps: this.taps,
            args: this.args
          })
        }
      }
      
      module.exports = Hook
      
    let Hook = require('./Hook.js')
    
    class HookCodeFactory {
      args() {
        return this.options.args.join(',')  // ["name", "age"]===> name, age
      }
      head() {
        return `var _x = this._x;`
      }
      content() {
        let code = ``
        for (var i = 0; i < this.options.taps.length; i++) {
          code += `var _fn${i} = _x[${i}];_fn${i}(${this.args()});`
        }
        return code
      }
      setup(instance, options) {  // 先准备后续需要使用到的数据
        this.options = options  // 这里的操作在源码中是通过 init 方法实现,而我们当前是直接挂在了 this 身上
        instance._x = options.taps.map(o => o.fn)   // this._x = [f1, f2, ....]
      }
      create() { //核心就是创建一段可执行的代码体然后返回
        let fn
        // fn = new Function("name, age", "var _x = this._x, var _fn0 = _x[0]; _fn0(name, age);")
        fn = new Function(
          this.args(),
          this.head() + this.content()
        )
        return fn
      }
    }
    
    let factory = new HookCodeFactory()
    
    class SyncHook extends Hook {
      constructor(args) {
        super(args)
      }
    
      compile(options) {  // {taps: [{}, {}], args: [name, age]}
        factory.setup(this, options)
        return factory.create(options)
      }
    }
    
    module.exports = SyncHook
    ---感谢阅读,o(* ̄︶ ̄*)o开心每一天!
  • 相关阅读:
    SSL 1579——泽泽在巴西
    SSL 1644——取数字问题
    SSL 1589——火车票
    SSL 1506——打鼹鼠
    SSL 1212——大厅安排
    洛谷 1064——金明的预算方案(动态规划的背包问题)
    SSL 1463——公共子串
    SSL 1461——最大连续数列的和
    SSL 1643——最小乘车费用
    SSL 1460——最小代价问题
  • 原文地址:https://www.cnblogs.com/websiteblogs/p/14457510.html
Copyright © 2020-2023  润新知