当前位置:   article > 正文

vue3.0后的学习proxy笔记(觉得和reflect一起对比学习效果更佳)_return new proxy{fn,{apply(target,context,args){}}

return new proxy{fn,{apply(target,context,args){}}}

      最近看相关报道,vue3.0 开发计划 传送门 https://juejin.im/post/5bb719b9f265da0ab915dbdd

其中,监测机制:

一句话介绍:更加全面、精准、高效;更具可调试性的响应跟踪;以及可用来创建响应式对象的 API。

3.0 将带来一个基于 Proxy 的 observer 实现,它可以提供覆盖语言 (JavaScript——译注) 全范围的响应式能力,消除了当前 Vue 2 系列中基于 Object.defineProperty 所存在的一些局限,如:

  • 对属性的添加、删除动作的监测
  • 对数组基于下标的修改、对于 .length 修改的监测
  • 对 Map、Set、WeakMap 和 WeakSet 的支持

另外这个新的 observer 还有以下特性:

  • 公开的用于创建 observable (即响应式对象——译注) 的 API。这为小型到中型的应用提供了一种轻量级的、极其简单的跨组件状态管理解决方案。(译注:在这之前我们可以通过另外 new Vue({data : {...}}) 来创建这里所谓的 observable;另外,其实 vuex 内部也是用这种方式来实现的)
  • 默认为惰性监测(Lazy Observation)。在 2.x 版本中,任何响应式数据,不管它的大小如何,都会在启动的时候被监测。如果你的数据量很大的话,在应用启动的时候,这就可能造成可观的性能消耗。而在 3.x 版本中,只有应用的初始可见部分所用到的数据会被监测,更不用说这种监测方案本身其实也是更加快的。
  • 更精准的变动通知。举个例子:在 2.x 系列中,通过 Vue.set 强制添加一个新的属性,将导致所有依赖于这个对象的 watch 函数都会被执行一次;而在 3.x 中,只有依赖于这个具体属性的 watch 函数会被通知到。
  • 不可变监测对象(Immutable observable):我们可以创建一个对象的“不可变”版本,以此来阻止对他的修改——包括他的嵌套属性,除非系统内部临时解除了这个限制。这种机制可以用来冻结传递到组件属性上的对象和处在 mutation 范围外的 Vuex 状态树。
  • 更良好的可调试能力:通过使用新增的 renderTrackedrenderTriggered 钩子,我们可以精确地追踪到一个组件发生重渲染的触发时机和完成时机,及其原因

那么 proxy 到底是什么 该怎么使用呢???

target是指代理的原对象,它是你需要拦截访问的原始对象,它总是作为Proxy构造器的第一个方法,也可以传递到每个trap中。

handler是一个包含你要进行拦截和处理的对象,也就是你拦截了原始对象以后想干什么?主要的代理内容在这里,是作为Proxy构造器的第二个方法参数传统,它是实现Proxy API。

trap用来规定对于指定什么方法进行拦截处理,如果你想拦截get方法的调用,那么你要定义一个get trap。

  1. let obj = { name:"bruce",age:"25"}
  2. let handler = {
  3. //get运算符有两个参数 - 对象本身和被访问的属性。
  4. get:function(target,prop){
  5. console.log('target:'+target+"prop:"+prop);
  6. },
  7. //set操作符有三个参数 - 对象本身,被访问的属性和为该属性设置的值。
  8. set:function(target,prop,value){
  9. if(typeof(value) == 'string'){ //用来作 类型检验
  10. }
  11. console.log('target:'+target+"prop:"+prop+"value:"+value);
  12. }
  13. }
  14. let proxy = new Proxy(obj,handler)
  15. proxy.name //打印 target:[object Object]prop:name
  16. proxy.name = 333 //打印 target:[object Object]prop:namevalue:333

    proxy与设计模式

     在面向对象的编程中,代理模式的合理使用能够很好的体现下面两条原则:

  • 单一职责原则: 面向对象设计中鼓励将不同的职责分布到细粒度的对象中,Proxy 在原对象的基础上进行了功能的衍生而又不影响原对象,符合松耦合高内聚的设计理念。

  • 开放-封闭原则:代理可以随时从程序中去掉,而不用对其他部分的代码进行修改,在实际场景中,随着版本的迭代可能会有多种原因不再需要代理,那么就可以容易的将代理对象换成原对象的调用

    Proxy实现前端中3种代理模式的使用场景,分别是:缓存代理验证代理实现私有属性

1.0.0 缓存代理

  1. //计算斐波那契数列 40以上很慢
  2. const getFib = (number) => {
  3. if (number <= 2) {
  4. return 1;
  5. } else {
  6. return getFib(number - 1) + getFib(number - 2);
  7. }
  8. }
  9. //创建缓存代理的工厂函数
  10. const getCacheProxy = (fn, cache = new Map()) => {
  11. return new Proxy(fn, {
  12. apply(target, context, args) {
  13. const argsString = args.join(' ');
  14. console.log(args)
  15. if (cache.has(argsString)) {
  16. console.log(argsString)
  17. // 如果有缓存,直接返回缓存数据
  18. console.log(`输出${args}的缓存结果: ${cache.get(argsString)}`);
  19. return cache.get(argsString);
  20. }
  21. const result = fn(...args);
  22. cache.set(argsString, result);
  23. return result;
  24. }
  25. })
  26. }
  27. //使用
  28. const getFibProxy = getCacheProxy(getFib)
  29. getFibProxy(40); // 102334155
  30. getFibProxy(40); // 输出40的缓存结果: 102334155

 

1.0.1 验证代理

  1. // 表单对象
  2. const userForm = {
  3. account: '',
  4. password: '',
  5. }
  6. // 验证方法
  7. const validators = {
  8. account(value) {
  9. // account 只允许为中文
  10. const re = /^[\u4e00-\u9fa5]+$/;
  11. return {
  12. valid: re.test(value),
  13. error: '"account" is only allowed to be Chinese'
  14. }
  15. },
  16. password(value) {
  17. // password 的长度应该大于6个字符
  18. return {
  19. valid: value.length >= 6,
  20. error: '"password "should more than 6 character'
  21. }
  22. }
  23. }
  24. // 校验器
  25. const getValidateProxy = (target, validators) => {
  26. return new Proxy(target, {
  27. _validators: validators,
  28. set(target, prop, value) {
  29. if (value === '') {
  30. console.error(`"${prop}" is not allowed to be empty`);
  31. return target[prop] = false;
  32. }
  33. const validResult = this._validators[prop](value);
  34. if(validResult.valid) {
  35. return Reflect.set(target, prop, value);
  36. } else {
  37. console.error(`${validResult.error}`);
  38. return target[prop] = false;
  39. }
  40. }
  41. })
  42. }
  43. // 使用
  44. const userFormProxy = getValidateProxy(userForm, validators);
  45. userFormProxy.account = '123'; // "account" is only allowed to be Chinese
  46. userFormProxy.password = 'he'; // "password "should more than 6 character

 

1.0.2 实现私有属性 (设置访问限制)

 

  1. function getPrivateProps(obj, filterFunc) {
  2. return new Proxy(obj, {
  3. get(obj, prop) {
  4. if (!filterFunc(prop)) {
  5. let value = Reflect.get(obj, prop);
  6. // 如果是方法, 将this指向修改原对象
  7. if (typeof value === 'function') {
  8. value = value.bind(obj);
  9. }
  10. return value;
  11. }
  12. },
  13. set(obj, prop, value) {
  14. if (filterFunc(prop)) {
  15. throw new TypeError(`Can't set property "${prop}"`);
  16. }
  17. return Reflect.set(obj, prop, value);
  18. },
  19. has(obj, prop) {
  20. return filterFunc(prop) ? false : Reflect.has(obj, prop);
  21. },
  22. ownKeys(obj) {
  23. return Reflect.ownKeys(obj).filter(prop => !filterFunc(prop));
  24. },
  25. getOwnPropertyDescriptor(obj, prop) {
  26. return filterFunc(prop) ? undefined : Reflect.getOwnPropertyDescriptor(obj, prop);
  27. }
  28. });
  29. }
  30. //因为私有属性 一般以 _开头 这里就简单过滤
  31. function propFilter(prop) {
  32. return prop.indexOf('_') === 0;
  33. }

 

 

参考资料:https://www.imooc.com/article/47896

http://es6.ruanyifeng.com/#docs/proxy 

https://www.cnblogs.com/diligenceday/p/5474126.html      

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/140070
推荐阅读
相关标签
  

闽ICP备14008679号