Skip to content

介绍

  • 使用者无权访问目标对象
  • 中间加代理,通过代理做授权和控制

示例

  • 科学上网,访问 GitHub.com
  • 明星经纪人

常见使用场景

  • 网页事件代理
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="div1">
      <a href="#">a1</a>
      <a href="#">a2</a>
      <a href="#">a3</a>
      <a href="#">a4</a>
      <a href="#">a5</a>
      <a href="#">a6</a>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script>
      let div1 = document.getElementById('div1')
      //监听a标签上的点击事件,不可能对a一个一个的去绑定
      div1.addEventListener('click', function (e) {
        let target = e.target
        if (target.nodeName === 'A') {
          console.log(target.innerHTML)
        }
      })
    </script>
  </body>
</html>
  • jQuery的$.proxy
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="div1">
      <a href="#">a1</a>
      <a href="#">a2</a>
      <a href="#">a3</a>
      <a href="#">a4</a>
      <a href="#">a5</a>
      <a href="#">a6</a>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script>
      // $("#div1").click(function () {
      // 	$(this).addClass("red");
      // });
      // $("#div1").click(function () {
      // 	setTimeout(function () {
      //     // this 不符合期望
      // 		$(this).addClass("red");
      // 	}, 1000);
      // });

      // $("#div1").click(function () {
      //   var _this = this;
      // 	setTimeout(function () {
      //     // _this 符合期望
      // 		$(_this).addClass("red");
      // 	}, 1000);
      // });

      // $("#div1").click(() => {
      // 	setTimeout(() => {
      // 		$(this).addClass("red");
      // 	}, 1000);
      // });

      $('#div1').click(function () {
        setTimeout(
          $.proxy(function () {
            $(this).addClass('red')
          }, this),
          1000
        )
      })
    </script>
  </body>
</html>
  • es 6的proxy
javascript
//明星
let star = {
  name: 'dd',
  age: 25,
  phone: '明星电话:189****05**',
}

//经纪人
let agent = new Proxy(star, {
  //target是要代理的对象,key是要获取的属性值
  get: function (target, key) {
    if (key === 'phone') {
      //返回经纪人的电话,不会把明星的电话直接给你
      return '经纪人电话:189******3*'
    }
    if (key === 'price') {
      //明星不报价,经纪人谈价格
      return '12K'
    }
    return target[key]
  },
  set: function (target, key, value) {
    if (key === 'customPrice') {
      if (value < 100000) {
        //最低10万
        throw new Error('价格太低')
      } else {
        target[key] = value
        return true
      }
    }
  },
})

console.log(agent.name)
console.log(agent.phone)
console.log(agent.price)

agent.customPrice = 150000
console.log('agent.customPrice:' + agent.customPrice)

代理模式代码示例

javascript
class ReadImg {
  constructor(fileName) {
    this.fileName = fileName
    this.loadFromDisk()
  }
  dispaly() {
    console.log('display... ' + this.fileName)
  }
  loadFromDisk() {
    console.log('loading... ' + this.fileName)
  }
}

class ProxyImg {
  constructor(fileName) {
    this.realImg = new ReadImg(fileName)
  }
  dispaly() {
    this.realImg.dispaly()
  }
}

// test
let proxyImg = new ProxyImg('pic.png')
proxyImg.dispaly()

设计原理验证

  • 代理类和目标类分离,隔离开目标类和使用者
  • 符合开放封闭原则

区分

代理模式 VS 适配器模式

  • 适配器模式:提供一个不同的接口(如不同版本的插头)
  • 代理模式:提供一模一样的接口

代理模式 VS 装饰器模式

  • 装饰器模式:扩展功能,原有功能不变且可直接使用
  • 代理模式: 显示原有功能,但是经过限制或者阉割之后的

Layout Switch

Adjust the layout style of VitePress to adapt to different reading needs and screens.

Expand all
The sidebar and content area occupy the entire width of the screen.
Expand sidebar with adjustable values
Expand sidebar width and add a new slider for user to choose and customize their desired width of the maximum width of sidebar can go, but the content area width will remain the same.
Expand all with adjustable values
Expand sidebar width and add a new slider for user to choose and customize their desired width of the maximum width of sidebar can go, but the content area width will remain the same.
Original width
The original layout width of VitePress

Page Layout Max Width

Adjust the exact value of the page width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the page layout
A ranged slider for user to choose and customize their desired width of the maximum width of the page layout can go.

Content Layout Max Width

Adjust the exact value of the document content width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the content layout
A ranged slider for user to choose and customize their desired width of the maximum width of the content layout can go.

Spotlight

Highlight the line where the mouse is currently hovering in the content to optimize for users who may have reading and focusing difficulties.

ONOn
Turn on Spotlight.
OFFOff
Turn off Spotlight.