赞
踩
最近看相关报道,vue3.0 开发计划 传送门 https://juejin.im/post/5bb719b9f265da0ab915dbdd
其中,监测机制:
一句话介绍:更加全面、精准、高效;更具可调试性的响应跟踪;以及可用来创建响应式对象的 API。
3.0 将带来一个基于 Proxy 的 observer 实现,它可以提供覆盖语言 (JavaScript——译注) 全范围的响应式能力,消除了当前 Vue 2 系列中基于 Object.defineProperty
所存在的一些局限,如:
另外这个新的 observer 还有以下特性:
new Vue({data : {...}})
来创建这里所谓的 observable;另外,其实 vuex 内部也是用这种方式来实现的)Vue.set
强制添加一个新的属性,将导致所有依赖于这个对象的 watch 函数都会被执行一次;而在 3.x 中,只有依赖于这个具体属性的 watch 函数会被通知到。renderTracked
和 renderTriggered
钩子,我们可以精确地追踪到一个组件发生重渲染的触发时机和完成时机,及其原因那么 proxy 到底是什么 该怎么使用呢???
target是指代理的原对象,它是你需要拦截访问的原始对象,它总是作为Proxy构造器的第一个方法,也可以传递到每个trap中。
handler是一个包含你要进行拦截和处理的对象,也就是你拦截了原始对象以后想干什么?主要的代理内容在这里,是作为Proxy构造器的第二个方法参数传统,它是实现Proxy API。
trap用来规定对于指定什么方法进行拦截处理,如果你想拦截get方法的调用,那么你要定义一个get trap。
- let obj = { name:"bruce",age:"25"}
-
- let handler = {
- //get运算符有两个参数 - 对象本身和被访问的属性。
- get:function(target,prop){
- console.log('target:'+target+"prop:"+prop);
- },
- //set操作符有三个参数 - 对象本身,被访问的属性和为该属性设置的值。
- set:function(target,prop,value){
- if(typeof(value) == 'string'){ //用来作 类型检验
-
- }
- console.log('target:'+target+"prop:"+prop+"value:"+value);
- }
- }
-
- let proxy = new Proxy(obj,handler)
-
- proxy.name //打印 target:[object Object]prop:name
-
- proxy.name = 333 //打印 target:[object Object]prop:namevalue:333
proxy与设计模式
在面向对象的编程中,代理模式的合理使用能够很好的体现下面两条原则:
单一职责原则: 面向对象设计中鼓励将不同的职责分布到细粒度的对象中,Proxy 在原对象的基础上进行了功能的衍生而又不影响原对象,符合松耦合高内聚的设计理念。
Proxy
实现前端中3种代理模式的使用场景,分别是:缓存代理、验证代理、实现私有属性。
- //计算斐波那契数列 40以上很慢
- const getFib = (number) => {
- if (number <= 2) {
- return 1;
- } else {
- return getFib(number - 1) + getFib(number - 2);
- }
- }
-
- //创建缓存代理的工厂函数
-
- const getCacheProxy = (fn, cache = new Map()) => {
- return new Proxy(fn, {
- apply(target, context, args) {
- const argsString = args.join(' ');
- console.log(args)
- if (cache.has(argsString)) {
- console.log(argsString)
- // 如果有缓存,直接返回缓存数据
- console.log(`输出${args}的缓存结果: ${cache.get(argsString)}`);
- return cache.get(argsString);
- }
- const result = fn(...args);
- cache.set(argsString, result);
- return result;
- }
- })
- }
-
- //使用
- const getFibProxy = getCacheProxy(getFib)
- getFibProxy(40); // 102334155
- getFibProxy(40); // 输出40的缓存结果: 102334155
-
-
- // 表单对象
-
- const userForm = {
- account: '',
- password: '',
- }
-
- // 验证方法
- const validators = {
- account(value) {
- // account 只允许为中文
- const re = /^[\u4e00-\u9fa5]+$/;
-
- return {
- valid: re.test(value),
- error: '"account" is only allowed to be Chinese'
- }
- },
-
- password(value) {
- // password 的长度应该大于6个字符
- return {
- valid: value.length >= 6,
- error: '"password "should more than 6 character'
- }
- }
- }
-
-
- // 校验器
- const getValidateProxy = (target, validators) => {
-
- return new Proxy(target, {
-
- _validators: validators,
-
- set(target, prop, value) {
-
- if (value === '') {
-
- console.error(`"${prop}" is not allowed to be empty`);
-
- return target[prop] = false;
-
- }
-
- const validResult = this._validators[prop](value);
-
- if(validResult.valid) {
-
- return Reflect.set(target, prop, value);
-
- } else {
-
- console.error(`${validResult.error}`);
-
- return target[prop] = false;
-
- }
-
- }
-
- })
-
- }
- // 使用
- const userFormProxy = getValidateProxy(userForm, validators);
- userFormProxy.account = '123'; // "account" is only allowed to be Chinese
- userFormProxy.password = 'he'; // "password "should more than 6 character
- function getPrivateProps(obj, filterFunc) {
-
- return new Proxy(obj, {
- get(obj, prop) {
- if (!filterFunc(prop)) {
- let value = Reflect.get(obj, prop);
- // 如果是方法, 将this指向修改原对象
- if (typeof value === 'function') {
- value = value.bind(obj);
- }
- return value;
- }
- },
-
- set(obj, prop, value) {
-
- if (filterFunc(prop)) {
- throw new TypeError(`Can't set property "${prop}"`);
- }
- return Reflect.set(obj, prop, value);
- },
-
- has(obj, prop) {
- return filterFunc(prop) ? false : Reflect.has(obj, prop);
- },
-
- ownKeys(obj) {
- return Reflect.ownKeys(obj).filter(prop => !filterFunc(prop));
- },
-
- getOwnPropertyDescriptor(obj, prop) {
- return filterFunc(prop) ? undefined : Reflect.getOwnPropertyDescriptor(obj, prop);
- }
-
- });
-
- }
- //因为私有属性 一般以 _开头 这里就简单过滤
- function propFilter(prop) {
- return prop.indexOf('_') === 0;
- }
-
参考资料:https://www.imooc.com/article/47896
http://es6.ruanyifeng.com/#docs/proxy
https://www.cnblogs.com/diligenceday/p/5474126.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。