- 底层模块的变更,必然有高层模块的耦合,开闭原则就是减少变更的扩展性
通俗的意思就是说,在开发过程中,在前期设计就必须做好相对应的扩展
- 在修改代码时必须要尽量少动原有的代码,最好不要修改老的代码,这就是对修改关闭
- 那么如何处理新的需求呢?这里就涉及到代码的前期涉及了,尽量做到的是新增函数,只对新需求做扩展
这里举一个栗子:
这里有个表单:
<div id="loginForm">
<input type="text" class="username" id="username" placeholder="username"><br>
<input type="text" class="pwd" id="pwd" placeholder="pwd"><br>
<button onclick="checkLogin()">提交</button>
</div>
复制代码
一般做前端校验的方法可能就会是这个样子:
- 写一个公共的校验方法来对表单中的每个输入项进行校验
- 取出 input 表单中的每个值,依次根据指定的校验规则,来校验前端输入的内容
- 如果出现错误的话,就会对这个输入错误的数据进行提醒
比如下面这样的方式:
function checkLogin() {
let username = document.querySelector("#username").value;
if (!username) {
alert("username must not be null");
}
let pwd = document.querySelector("#pwd").value;
if (!pwd) {
alert("pwd must not be null");
}
}
复制代码
这样就会面临下面的问题:
- 如果校验规则有变动的话,就需要对原来的代码进行修改
- 如果需求有变动,比如在原来的表单中新增了一个 input 输入框的话,就还需要修改原来的这个校验的代码
- 一般来说,修改代码都有可能对原来的代码造成一定的问题,修改就有可能出错
对修改关闭
这是一个非常重要的原则,对原来已有的代码最好不做修改
那么我们在这里该这么做呢?看这样的修改:
- 在 html 中添加一个 input 输入框自身的自定义属性 data-validate 用来标识这个 input 输入框对应的校验函数名
<div id="loginForm">
<input type="text" class="username" data-validate="checkUsername" id="username" placeholder="username"><br>
<input type="text" class="pwd" data-validate="checkPwd" id="pwd" placeholder="pwd"><br>
<button onclick="checkLoginForm()">提交</button>
</div>
复制代码
- 写通用函数,专门负责这个表单的校验,获取所有的 input 输入框,拿到对应的校验函数,并调用对应的挂载在 window 上的校验函数
function checkLoginForm() {
// 表单
let form = document.querySelector("#loginForm");
// 表单中input
let ipts = form.querySelectorAll("input");
// 获取input中的校验函数名,并调用对应的函数
for (let i = 0; i < ipts.length; i++) {
let input = ipts[i];
let validate = input.dataset.validate;
let validateFn = window[validate];
if (validateFn) {
let rst = !validateFn(input.value);
if (rst) {
return false;
}
} else {
alert(`当前没有这个${validate}校验函数`);
}
}
}
复制代码
- 这样以后的扩展就可以单独写对应的校验函数就ok,无需再去修改原来的 checkLoginForm 函数,同时校验函数还可以复用。
function checkUsername(username) {
if (!username) {
alert("username must not be null");
}
}
复制代码
- data-validate="checkUsername" 属性值对应的就是通用的校验函数名称,减少对原有代码的修改和侵入。