【前端设计模式】代理模式

109 阅读1分钟

代理模式的作用

被代理对象不能直接访问,需要通过代理

标准代理模式

未命名文件(11).png

class Singer {
  name: string
  constructor(name: string) {
    this.name = name
    this.prepareMusic()
  }
  singSong() {
    console.log('Singing...')
  }
  private prepareMusic() {
    console.log('Preparing...')
  }
}

class Agent {
  singer: Singer
  constructor(name: string) {
    this.singer = new Singer(name)
  }
  singSong(cnt: number) {
    while(cnt--) this.singer.singSong()
  }
}

const agent = new Agent('Jay')
agent.singSong(3)
// Preparing...
// Singing...
// Singing...
// Singing...

代理模式的应用

DOM事件代理

  • 将事件绑定到父容器上
  • 适合子元素数量不确定的场景(如图片瀑布流)

Proxy语法

跟踪属性(Vue3 数据响应式)

const city = {
  name: '西安'
}

const proxy = new Proxy(city, {
  get(target, key) {
    console.log('get...')
    return Reflect.get(target, key)
  },
  set(target, key, val) {
    console.log('set...', val)
    return Reflect.set(target, key, val)
  }
})

proxy.name = '上海'
console.log(proxy.name)

隐藏属性

const city = {
  name: '西安'
}

const hiddenProps = ['name']
const proxy = new Proxy(city, {
  get(target, key) {
    if(hiddenProps.includes(key as string)) return undefined
    return Reflect.get(target, key)
  },
  set(target, key, val) {
    if(hiddenProps.includes(key as string)) return false
    return Reflect.set(target, key, val)
  },
  has(target, key) {
    if(hiddenProps.includes(key as string)) return false
    return Reflect.has(target, key)
  }
})

记录实例

class City {
  name: string
  constructor(name: string) {
    this.name = name
  }
}

const cityList = new Set()

const proxy = new Proxy(City, {
  construct(...args) {
    const city = Reflect.construct(...args)
    cityList.add(city)
    return city
  }
})