JavaScript页面交互表单验证和密码强度验证

将来我需要做的事情是
随着用户的输入检测输入的内容是不是符合规则
如果符合规则, 那么 input 取消掉 active 类名, 并且 p.error 也取消掉 active
如果不符合规则, 那么 input 要加上 active 类名, 并且 p.error 也要加上 active
问题:
input 和 p 标签本身都有个自的类名
添加类名的时候好做 直接 += ’ 要添加的类名’
删除类名的时候不好做, 我们要获取到字符串, 把里面的某些内容干掉, 再从新赋值
解决:
把他们两个的内容提出来, 放在一个公共的父级上做特殊类名标注
现在开始:
如果正则检测出现问题, 我只要给 label 标签添加 active 类名
就可以操作 label 里面的 p 标签和 input 标签了
–>

表单验证 - 随着输入, 随时告诉你对还是不对 思路: 1. 获取元素, 获取的是两个 input 框 2. 随着用户的输入, 要随时验证用户输入的内容 => 每一个 input 框都要有一个事件 => 事件可以随着用户的输入去触发 => keydown 可以 input 可以 keyup 可以 3. 在事件里面, 验证用户输入的内容 => 如果验证对了, 那么就给 label 标签取消掉 active 类名 => 如果验证不对, 那么就给 label 标签添加 active 类名 单独书写第 3 步的思路 分析异同 不一样的地方 不同的文本框使用不同的正则来验证 => 用户名和密码不能用同一个正则来验证 一样的地方 一样的事件 一样的正确错误操作 => 正确的时候, 给自己的父元素(label)取消 active 类名 => 错误的时候, 给自己的父元素(lebel)添加 active 类名 代码思路: 3-1. 判断是哪个元素触发的事件 => 判断是用户名文本框还是密码文本框或者还是一些其他的 => 通过什么来判断 ? 可以通过元素的 id 来判断 也可以通过元素的 类名 来判断 如果有别的也可以用, 只要找到一个所有 input 上都有的, 并且都不一样的 => 怎么判断 ? 一两个的时候, 可以通过 if 条件判断就行 多了的时候, 可以通过 switch 来判断 3-2. 开始判断, 准备不同的正则, 来判断不同的内容 => 用户名正则 [^_].{5,11} => 密码正则 \w{6,12} => 在事件里面, 提前准备一个变量, 表示错误或者正确 默认是 错误的 随着书写, 只要对了, 就把这个变量变成 正确 随着书写, 只要错了, 就把这个变量变成 错误 3-3. 操作 label 的类名 => 如果当前的元素判断是 false, 那么给 this 元素的父元素添加 active 类名 => 如果当前的元素判断是 true, 那么给 this 元素的父元素取消 active 类名 => 不管对错, 我都是给 this.parentElement 在操作类名 => 可以把他单独提取出来, 只是根据对错来赋值类名 // 1. 获取元素 var inps = document.querySelectorAll('form input') // 3-2. 准备正则 var usernameReg = /^[^_].{5,11}$/ var passwordReg = /^\w{6,12}$/ var phoneReg = /^\d{11}$/ var idcardReg = /^\d{18}$/ // 2. 给每一个 input 框绑定一个 input 事件 for (var i = 0; i < inps.length; i++) { inps[i].addEventListener('input', function (e) { // 3-1. 判断是哪一个元素触发的事件 var eleId = this.id // 3-2. 提前准备一个变量, 用来表示错误或者正确 var flag = false // 开始判断 switch (eleId) { case 'username': flag = usernameReg.test(this.value) break case 'password': flag = passwordReg.test(this.value) break case 'phone': flag = phoneReg.test(this.value) break case 'idcard': flag = idcardReg.test(this.value) } // 3-2. 当判断结束的时候 this.parentElement.className = flag ? '' : 'active' }) } // // 1. 获取元素 // // 获取到 两个 文本框 // var inps = document.querySelectorAll('form input') // // 3-2. 准备正则 // // 因为不需要每次触发事件都准备一次正则 // // 正则始终就用这个一个就可以了, 所以直接书写在全局 // var usernameReg = /^[^_].{5,11}$/ // var passwordReg = /^\w{6,12}$/ // // 2. 给每一个 input 框绑定一个 input 事件 // for (var i = 0; i < inps.length; i++) { // inps[i].addEventListener('input', function (e) { // // 3-1. 判断是哪一个元素触发的事件 // // this 表示触发事件的那个元素 // var eleId = this.id // // 3-2. 提前准备一个变量, 用来表示错误或者正确 // var flag = false // // 开始判断 // switch (eleId) { // case 'username': // console.log('用户名文本框, 使用用户名正则') // // 使用用户名的正则去验证当前这个文本框用户输入的内容 // flag = usernameReg.test(this.value) // break // case 'password': // console.log('密码文本框, 使用密码正则') // flag = passwordReg.test(this.value) // break // } // // 3-2. 当判断结束的时候 // // 你就直到你当前输入的这个是错的还是对的 // // console.log(eleId + ' 输入内容是 : ', flag) // // 3-3. 给 label 元素添加或者取消 active 类名 // // if (flag === true) { // // this.parentElement.className = '' // // } else { // // this.parentElement.className = 'active' // // } // // 改写 // // this.parentElement.className = (flag === true ? '' : 'active') // // 继续简写 // this.parentElement.className = flag ? '' : 'active' // }) // } form>
  密码强度验证
  代码思路:
    1. 获取元素
      => 密码文本框, 因为要添加事件, 获取输入的内容, 正则验证
      => 三个 span 元素, 因为要操作 类名 来表示强度内容
    2. 给 密码文本框 设置一个 input 事件
      => 随着输入随时切换密码强度
    3. 在 密码文本框 的事件里面, 去操作强度类别
      => 要根据验证的强度, 来给不同的 span 标签添加类名
      3-1. 准备正则
        -> 一个是数字的验证
        -> 一个是字母的验证
        -> 一个是特殊符号的验证
      3-2. 开始进行验证
        -> 初始准备一个变量, 赋值为 0, 表示一个正则都没有满足
        -> 挨个的正则去进行判断, 满足一个, 变量++
        -> 最后, 我变量的数字就是满足了几个正则
      3-3. 根据级别去设置 span 的类名
        -> 级别是 0, 那么设置 0 个 span 有类名
        -> 级别是 1, 那么设置索引为 [0] 的有类名, 1 个
        -> 级别是 2, 那么设置索引为 [0] 和 [1] 的有类名, 2 个
        -> 级别是 3, 那么设置索引为 [0] 和 [1] 和 [2] 的有类名, 3 个
      3-4. 解决一个能上不能下的问题
        -> 因为一直在加类名, 没有清除过, 所以加上去就回不来了
        -> 当你需要给 span 添加类名的时候, 那么先给 span 还原到最初是的样子
// 1. 获取元素
// 密码文本框
var pwdInp = document.querySelector('#password')
var spans = document.querySelectorAll('p span')
// 3-1. 准备正则  => 加号(+) 表示 1 ~ 多次
var numReg = /\d+/
var zimuReg = /[a-zA-Z]+/
var fuhaoReg = /[@#$%^&]+/
// 2. 给 密码文本框 绑定一个输入事件
pwdInp.addEventListener('input', function () {
  // 3-2. 开始判断
  var level = 0 // 默认是 0 级, 一个正则都没有满足
  // 挨个正则去判断 - 确定级别
  if (numReg.test(this.value)) level++
  if (zimuReg.test(this.value)) level++
  if (fuhaoReg.test(this.value)) level++
  // 3-4. 在加类名之前, 给所有 span 的类名还原到最初是的状态
  spans[0].className = 'low'
  spans[1].className = 'center'
  spans[2].className = 'strong'
  // 3-3. 根据级别来给 span 设置类名
  for (var i = 0; i < level; i++) {
    spans[i].className += ' active'
  }
})
// // 1. 获取元素
// // 密码文本框
// var pwdInp = document.querySelector('#password')
// // console.log(pwdInp)
// // 三个 span 标签
// var spans = document.querySelectorAll('p span')
// // console.log(spans)
// // 3-1. 准备正则  => 加号(+) 表示 1 ~ 多次
// // 没写开头或者结尾, 表示只要字符串里面有数字就好使
// var numReg = /\d+/
// // 没写开头或者结尾, 表示只要字符串里面有字母就好使
// var zimuReg = /[a-zA-Z]+/
// // 没写开头或者结尾, 表示只要字符串里面有符号就好使
// var fuhaoReg = /[@#$%^&]+/
// // 2. 给 密码文本框 绑定一个输入事件
// pwdInp.addEventListener('input', function () {
//   // console.log('用户在输入密码')
//   // 3-2. 开始判断
//   var level = 0 // 默认是 0 级, 一个正则都没有满足
//   // 挨个正则去判断
//   if (numReg.test(this.value)) level++
//   if (zimuReg.test(this.value)) level++
//   if (fuhaoReg.test(this.value)) level++
//   // 3-4. 在加类名之前, 给所有 span 的类名还原到最初是的状态
//   spans[0].className = 'low'
//   spans[1].className = 'center'
//   spans[2].className = 'strong'
//   // 3-3. 根据级别来给 span 设置类名
//   for (var i = 0; i < level; i++) {
//     // 当 level === 0 的时候, i 一次都不执行
//     // 当 level === 1 的时候, i === 0
//     // 当 level === 2 的时候, i === 0 1
//     // 当 level === 3 的时候, i === 0 1 2
//     spans[i].className += ' active'
//   }
// })
  单独解释 level
  1. 定义变量是在事件里面进行定义的
    => 就是每次触发事件的时候, 都会定义一次 level 为 0
    => 每输入一个内容就会触发一个事件
    => 每次输入内容的时候, 都会定义 level 为 0
  2. 正则判断
    => 假如你输入 1
      -> level === 0
      -> 判断满足了一个正则, 执行一次 level++
      -> level 变成 1
    => 继续输入内容 11
      -> level = 0
      -> 判断满足了一个正则, 执行一次 level++
      -> level 变成 1

回顾作用域
1. 什么是作用域
=> 一个变量可以使用的范围
2. 作用域分类
=> 全局作用域
-> 一个 html 页面就是一个全局作用域
=> 局部作用域(私有作用域)
-> 只有函数生成私有作用域
3. 作用域的上下级关系
=> 写在哪个作用域里面的私有作用域
=> 就是哪个作用域的子级作用域
this 指向 *** 重要!!!重要!!!重要!!!
1. 定义: this 是一个使用在作用域里面的关键字
=> 作用域里面: 要么写在全局, 要么写在函数里面
=> 是个关键字: 定义变量的时候, 不能 var this
不需要定义, 我们直接使用就可以了
2. this 代表什么意思(this 指向)
=> 当你在全局作用域使用 this 的时候, this === window
-> 表示全局的意思
-> 一般很少在全局直接使用
=> 当你在函数里面使用的时候, 也就是在私有作用域里面使用的时候
-> 在 JS 里面, 很多的函数都会用到 this, 相当常用的一个关键字
-> 面试的时候, 好多的坑都是会问你 this 指向是谁而出现的
3. 函数内部的 this 指向(熟读并背诵全文)
=> 不管函数怎么定义, 不管函数在哪定义
=> 一个函数的 this 指向只和函数的调用方式有关系(箭头函数除外)
-> 函数直接调用(全局函数调用)
函数名() this -> window
-> 对象调用方式
对象名.函数名() this -> 点前面是谁就是谁
对象名’函数名’ this -> 中括号前面是谁就是谁
-> 事件处理函数
xxx.on事件类型 = function () {} this -> 事件源(绑定在谁身上的事件)
xxx.addEventListener(‘事件类型’, function () {}) this -> 事件源(绑定在谁身上的事件)
-> 定时器处理函数
setTimeout(function () {}, 时间) this -> window
setInterval(function () {}, 时间) this -> window
-> 还有一些没有学过的函数调用方式
未完待续
// 小案例
// var obj = {
// name: ‘我是 obj 对象’,
// fn: function () { console.log(this) }
// }
// var div = document.querySelector(‘div’)
// // a 这个函数才是 div 的事件处理函数
// // 是在 div 的事件处理函数里面, 以对象调用的方式在调用 obj.fn 这个函数
// div.onclick = function a() {
// // 这个位置的 this -> div 的
// // 函数是怎么调用的, 调用方式决定了函数内部的 this 指向
// // 标准的对象调用方式, 函数内部的 this 指向 点前面是谁就是谁
// obj.fn() // this -> obj
// }
// // 这么写是在把 obj.fn 这个函数当作事件处理函数使用
// div.onclick = obj.fn
// 小案例2
// var div = document.querySelector(‘div’)
// // a 这个函数才是 div 的事件处理函数
// div.onclick = function a() {
// var obj = {
// name: ‘我是 obj 对象’,
// fn: function () { console.log(this) }
// }
// // 不管函数定义在哪, 不管函数怎么定义
// // 只看函数的调用方式
// // 依旧是 对象调用 的方式, this 就是点前面是谁就是谁
// obj.fn() // this -> obj
// // 把 obj.fn 当作一个定时器处理函数去执行了
// // 定时器处理函数, this -> window
// // setTimeout(obj.fn, 1000) // this -> window
// // b 函数才是定时器处理函数
// // 只是在定时器处理函数里面使用对象调用的方式调用了 obj.fn 函数
// setTimeout(function b() {
// obj.fn() // this -> obj
// }, 1000)
// }
// 2. 对象调用方式
// var obj = {
// name: ‘张三’,
// fn: function () { console.log(this) }
// }
// 复杂数据类型的赋值
// 把 obj 里面存储的那个函数的地址, 赋值给了全局变量 f
// 从此以后, 全局变量 f 和 obj.fn 操作的是一个函数地址了
// var f = obj.fn

// // 我写 obj.fn() 和 f() 调用的是一个函数
// obj.fn() // this -> obj
// f() // this -> window
// var div = document.querySelector('div')
// // 当你点击 div 的时候, 执行 obj.fn 这个函数
// div.onclick = obj.fn // this -> div
// // 1000ms 以后, 执行 obj.fn 这个函数
// // 把 obj.fn 当作定时器处理函数在使用
// setTimeout(obj.fn, 1000) // this -> window
// 1. 普通函数调用(全局函数调用)
// function fn() {
//   console.log(this) // window
//   function fun() {
//     console.log(this)
//   }
//   fun() // 本次调用的时候, 函数内部的 this 指向谁 ?
// }
// // fn() 的调用方式, 是一个标准的普通函数调用
// // 这个函数里面的 this 指向 window
// fn()
// setTimeout(function () {
//   function fn() {
//     console.log(this)
//   }
//   fn() // 本次调用的时候, 函数内部的 this ?
// }, 1000)
// var div = document.querySelector('div')
// div.onclick = function () {
//   console.log(this) // this -> div
//   function fn() {
//     console.log(this) //window
//   }
//   // fn() 标准的普通函数调用, 全局函数调用
//   fn() // 本次函数调用的时候, this 指向谁 ?
// }

强行改变 this 指向
因为每一种函数调用方式都有自己的 this 指向
强行改变: 不管你本身指向哪里, 我让你指向哪, 你就得指向哪
我们有三个方法改变 this 指向
1. call()
使用方式: 直接跟在函数名后面使用就可以了
调用方式 强行改变 this 指向的调用方式
fn() -> fn.call()
obj.fn() -> obj.fn.call()
参数:
call(你要改变的 this 指向, 给函数传递参数, 给函数传递参数, …)
第一个参数: 你要改变的 this 指向, 不传递或者写一个 null 都是表示 window 的意思
第二个参数开始: 依次给函数传递参数
作用:
就是改变函数内部的 this 指向
特点: 直接调用函数, 写完以后, 函数就直接执行了
2. apply()
使用方式: 直接跟在函数名后面使用就可以了
调用方式 强行改变 this 指向的调用方式
fn() -> fn.apply()
obj.fn() -> obj.fn.apply()
参数:
apply(你要改变的 this 指向, [给函数传递参数1, 给函数传递参数2, …])
第一个参数: 你要改变的 this 指向, 不传递或者写一个 null 都是表示 window 的意思
第二个参数: 是一个数组或者伪数组都可以, 里面的每一项依次是给函数传递参数
作用:
改变 this 指向
改变给函数传递参数的方式
特点: 直接调用函数, 写完以后, 函数就直接执行了
3. bind()
使用方式: 直接跟在函数名后面使用就可以了
调用方式 强行改变 this 指向的调用方式
fn() -> fn.bind()
obj.fn() -> obj.fn.bind()
参数:
bind(你要改变的 this 指向, 给函数传递的参数1, 给函数传递的参数2, …)
第一个参数: 你要改变的 this 指向, 不传递或者写一个 null 都是表示 window 的意思
第二个参数开始: 依次是给函数传递参数
作用:
改变 this 指向
改变一个不需要立即执行的函数的 this 指向的时候
特点:
不会直接调用函数, 写完以后函数没有执行
而是返回一个新的函数, 一个改变好了 this 指向的函数
一个已经被改变一次 this 指向的新函数不能被再次改变了
栗子: 事件
div.onclick = fn // fn 内部的 this 指向 div
我想修改以下, 触发点击行为的时候, 我不想函数里面的 this 指向 div
如果写成 div.onclick = fn.call(window), 点击的时候就没有函数执行了
你绑定事件的时候就把函数执行了, 而不是点击的时候再执行
// bind 小案例2
// 我想把 fn 函数当作事件处理函数来使用
// 并且 fn 函数内部的 this 改变成 obj
// function fn() {
// console.log(this)
// }
// var obj = { name: ‘我是 obj 对象’ }
// var div = document.querySelector(‘div’)
// 直接把 fn 当作事件处理函数来使用
// 但是 this 指向没有改变, 依旧会在执行的时候指向 div
// div.onclick = fn
// 如果使用 call 方法改变 this 指向
// 确实是改变了 this 指向
// 书写 fn.call() 的时候, 就已经把函数调用了, 你点击的时候, 就没有函数执行了
// div.onclick = fn.call(obj)
// 如果使用 apply 方法改变 this 指向
// 确实是改变了 this 指向
// 书写 fn.apply() 的时候, 就已经把函数调用了, 你点击的时候, 就没有函数执行了
// div.onclick = fn.apply(obj)
// 如果使用 bind 方法改变 this 指向
// 相当于把 fn 函数复制了一份, 并且改变其中的 this 指向为 obj
// 并且把返回值这个新函数给了 div.onclick
// 当你点击的时候, 执行的是 fn.bind 的返回值(那个改变好 this 指向的新函数)
// div.onclick = fn.bind(obj)
// 改变过 this 不能再次被改变
// // res 是 JS 给你制作的一个函数
// var res = fn.bind(obj)
// // res2 是把一个 JS 给你制作的函数再次改变 this 指向
// var res2 = fn.bind(100)
// console.log(res2)
// res2()
// bind 小案例
// 想把这个函数当作一个定时器处理函数来使用
// 同时又想让这个函数内部的 this 指向 obj 对象
// function fn() {
// console.log(this)
// }
// var obj = { name: ‘我是 obj 对象’ }
// 基本版本
// 把 fn 当作定时器处理函数了, 但是没有改变 this 指向, 依旧指向 window
// setTimeout(fn, 100)
// 如果使用 call 来改变 this 指向
// 把 fn 的 this 指向改变了, 但是再书写 call 的时候, 就已经把函数调用了
// 1000ms 以后就没有函数能被调用
// setTimeout(fn.call(obj), 1000)
// 如果使用 apply 来改变 this 指向
// 把 fn 的 this 指向改变了, 但是再书写 apply 的时候, 就已经把函数调用了
// 1000ms 以后就没有函数能被调用
// setTimeout(fn.apply(obj), 1000)
// 如果使用 bind 来改变 this 指向
// 把 fn 的复制了一份, 并且 this 指向改变成了 obj, 会返回一个新的函数
// 1000ms 以后, fn.bind 的返回值(也就是改变好 this 的新函数)会被调用
// 把 fn 函数同时当作了定时器处理函数, 并且也改变了 this 指向
// setTimeout(fn.bind(obj), 1000)
// 3. bind()
// function fn(a, b) {
// console.log('this: ', this)
// console.log('第一个参数: ', a)
// console.log(‘第二个参数: ‘, b)
// console.log(’’)
// }
// // 准备几个数据用于改变 this 指向的时候使用
// var obj = { name: ‘我是 obj 对象’ }
// var arr = [10, 20, 30, 40, 50]
// var reg = /^abcd / / / v a r t i m e = n e w D a t e ( ) / / / / 直 接 调 用 / / f n ( 10 , 20 ) / / 函 数 调 用 了 / / / / 使 用 b i n d 改 变 一 下 t h i s 指 向 / / / / 本 次 b i n d 会 把 f n 函 数 复 制 一 份 , 把 里 面 的 t h i s 改 变 成 o b j / / / / 100 是 给 f n 函 数 传 递 的 第 一 个 参 数 / / / / 200 是 给 f n 函 数 传 递 的 第 二 个 参 数 / / / / 注 意 : 此 时 不 会 直 接 调 用 函 数 , 而 是 会 有 一 个 返 回 值 出 现 / / / /

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值