2.动态参数
- • 在日常开发中,我们需要向后台接口发送请求来获取信息,例如传参如下。业务在后续时需要添加新参数,每个接口需要把 token 值也一并传过去, 普遍我们会去改封装的请求方法,把 token 参数添加进去。但我们直接修改封装好的请求方法不是好的行为,那我们可使用上面说过的 AOP 方式来改进。
{ name: 'xxxx', password: 'xxxx', }
- • 如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>AOP动态参数</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <script src="https://unpkg.com/vue@3.2.20/dist/vue.global.js"></script> </head> <body> <div id="app">{{message}}</div> </body> </html> <script type="text/javascript"> const { reactive, ref, createApp } = Vue; const app = createApp({ setup() { const message = ref("empty params"); Function.prototype.before = function (beforeFn) { var _self = this; return function () { beforeFn.apply(this, arguments); return _self.apply(this, arguments); }; }; Function.prototype.after = function (afterFn) { var _self = this; return function () { var ret = _self.apply(this, arguments); afterFn.apply(this, arguments); return ret; }; }; function ajax(type, url, params){ message.value = `${type} ----> ${url} -----> ${JSON.stringify(params)}`; } function getToken(){ // do something return 'token'; } ajax = ajax.before(function(type, url, params){ params.token = getToken(); }) ajax('get', 'https://www.baidu.com/userinfo', {name: 'se', password: 'xsdsd'}); return { message, }; }, }); app.mount("#app"); </script>
3.表单校验
- • 在日常开发中,我们经常要去做校验表单数据,通常的方式是在功能函数中进行判断处理或将判断逻辑提取为一个函数的方式。但这种方式其实是与功能性函数相混合,且校验逻辑与功能性函数有耦合关系。那我们可使用 AOP 方式来改进。
- • 如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>AOP表单验证</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <script src="https://unpkg.com/vue@3.2.20/dist/vue.global.js"></script> </head> <body> <div id="app"> <label> 姓名: <input type="text" v-model="data.name" placeholder="请输入姓名" /> </label> <label> 密码: <input type="text" v-model="data.pass" placeholder="请输入密码" /> </label> <p v-if="data.name || data.pass">{{data.name + '/' + data.pass}} ----after-----> {{data.message}}</p> <hr> <button @click="submitBtn">submit</button> </div> </body> </html> <script type="text/javascript"> const { reactive, ref, createApp, watchEffect } = Vue; const app = createApp({ setup() { const data = reactive({ name: "", pass: "", message: "", }); Function.prototype.before = function (beforeFn) { var _self = this; return function () { if (beforeFn.apply(this, arguments) === false) return; return _self.apply(this, arguments); }; }; function valid() { if (!data.name || !data.pass) { alert("用户名或密码不能为空"); return false; } } function formSubmit() { console.log("data ------>", data); data.message = `${data.name} ------- ${data.pass}`; } formSubmit = formSubmit.before(valid); function submitBtn() { formSubmit(); } return { data, submitBtn, }; }, }); app.mount("#app"); </script>
装饰器模式的优缺点
- • 优点:
- 1. 扩展性强:装饰器模式允许在不修改现有代码的情况下,动态地添加新功能或修改现有功能。通过使用装饰器,可以在运行时按需组合和堆叠装饰器对象,实现各种组合方式,从而实现更多的功能扩展。
- 2. 遵循开闭原则:装饰器模式通过添加装饰器类来扩展功能,而不是修改现有的代码。这样可以保持原有代码的稳定性,符合开闭原则,即对扩展开放,对修改关闭。
- 3. 分离关注点:装饰器模式将功能的扩展和核心功能分离开来,每个装饰器类只关注单一的额外功能。这样可以使代码更加清晰、可读性更高,并且容易维护和测试。
- • 缺点:
- 1. 增加复杂性:使用装饰器模式会增加额外的类和对象,引入了更多的复杂性和层次结构。这可能使代码变得更加复杂,理解和调试起来可能更加困难。
- 2. 潜在的性能影响:由于装饰器模式涉及多个对象的组合和堆叠,可能会引入额外的运行时开销,对性能产生一定的影响。尤其是当装饰器链较长时,可能会导致性能下降。
装饰器模式的适用场景
- 1. 动态地扩展对象功能:当需要在运行时动态地为对象添加额外的功能或责任时,装饰器模式是一个很好的选择
- 2. 遵循开闭原则:如果你希望在不修改现有代码的情况下扩展功能,而且要保持代码的稳定性,装饰器模式是一个合适的解决方案。
- 3. 分离关注点:当你希望将不同的功能分离开来,使每个功能都有自己独立的装饰器类时,装饰器模式是有用的。每个装饰器只关注单一的额外功能,这样可以使代码更加清晰、可读性更高,并且容易维护和测试。
- 4. 多层次的功能组合:如果你需要实现多个功能的组合,而且每个功能都可以灵活选择是否添加,装饰器模式可以很好地满足这个需求。通过堆叠多个装饰器对象,可以按照特定的顺序组合功能,实现各种组合方式。
- 5. 继承关系的替代方案:当你面临类似于创建大量子类的情况时,装饰器模式可以作为继承关系的替代方案。通过使用装饰器模式,可以避免创建过多的子类,而是通过组合不同的装饰器来实现不同的功能组合。
Tip: 文章部分内容参考于曾探
大佬的《JavaScript 设计模式与开发实践》。文章仅做个人学习总结和知识汇总
特殊字符描述
•问题标注 Q:(question)
•答案标注 R:(result)
•注意事项标准:A:(attention matters)
•详情描述标注:D:(detail info)
•总结标注:S:(summary)
•分析标注:Ana:(analysis)
•提示标注:T:(tips)