技术总结:#
一 事件委托
事件委托利用冒泡的原理,把事件加到父级身上,触发执行效果,其好处:a 提高性能,新添加的元素,还有之前的事件
实现功能:动态添加input,每个input标签
html代码
<!--自定义的商品-->
<div class="flexWrap">
<!--标题-->
<nav class="nav2_1">
<ul>
<li class="hmain textleft" style="padding: 0;"><a href="javascript:;">自定义的商品</a></li>
<li class="hmain textright" style="padding: 0;"><a href="javascript:;" class="color_35B1F7" id="addInput">添加商品 <span
class="icon-ic_add"></span></a></li>
</ul>
</nav>
<div class="flexWrap" id="definedWrap">
<!--数据导入-->
<div class="flexContainer">
<div class="width8">已添加事项</div>
<div class="flex-item textCenter">数量</div>
<div class="flex-item textCenter">预算(元)</div>
<div class="width3_5">操作</div>
</div>
<!--包含的事项,数据导入-->
<div class="flexContainer">
<div class="width8">
<input type="text" id="shop1" name="budgetName" value="" class="inputBoxM" placeholder="请输入事项" />
</div>
<div class="flex-item textCenter">
<input type="number" id="price1" name="budget" value="" class="inputBoxM" data-price="1" />
</div>
<div class="flex-item textCenter">
<input type="number" id="qty1" name="budgetQuantity" value="" class="inputBoxM" data-qty="1" />
</div>
<div class="width3_5">
<input type="button" id="delete" value="删除" />
</div>
</div>
</div>
</div>
js代码
<script>
window.onload = function() {
//获取元素
document.body.style.height = view().h + "px";
document.body.style.width = view().w + "px";
//获得页面宽高
function view() {
return {
w: document.documentElement.clientWidth,
h: document.documentElement.clientHeight
};
};
//动态添加自定义标签
//获得父级元素
var aWrap = $("#definedWrap");
//获得点击事件按钮
var oInputAdd = $("#addInput");
//设置初始Index
var FieldCount = 1; //to keep track of text box added
//event 对象,事件源,不管在哪个事件中,只要你操作的那个元素就是事件源
//IE: window.event.srcElement
//标准下:event.target
//鼠标移入时获取事件源
//当输入域失去焦点 (blur) ,触发函数
aWrap.change(function(ev) {
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if (target.nodeName.toLocaleLowerCase() == 'input') {
if ($("input:not('#alltotal')")) {
//获取到计算长度
var $total = $('input[data-price]');
var all = 0;
//遍历
for (var i = 0, n = $total.length; i < n; i++) {
var price = parseInt($('[data-price]:eq(' + i + ')').val());
var qty = parseInt($('[data-qty]:eq(' + i + ')').val());
all += price * qty;
// $total.eq(i).val( price * qty );
}
$('#alltotal').val(all);
$('#allval').val(all);
}
}
});
//点击删除,删除整行
aWrap.click(function() {
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if (target.id.toLocaleLowerCase() == 'delete') {
// alert($(target).parent());
//change the background color to red before removing
$(target).parent().parent().css("background-color", "#35b1f7");
$(target).parent().parent().fadeOut(400, function() {
$(this).remove();
alert($(this.find('input')[1]));
});
}
});
//触发点击事件,点击添加
$(oInputAdd).click(function(e) {
FieldCount++; //text box added increment
//add input box
$(aWrap).append('<div class="flexContainer"><div class="width8"><input type="text" id="shop' + FieldCount + '" value="" class="inputBoxM"/></div><div class="flex-item textCenter"><input type="number" id="price' + FieldCount + '" value="" class="inputBoxM" data-price="1" /></div><div class="flex-item textCenter"><input type="number" id="qty' + FieldCount + '" value="" class="inputBoxM" data-qty="1" /></div><div class="width3_5"><input type="button" id="delete" value="删除" /></div></div>');
});
};
</script>
拓展 ↓↓↓
1 事件:在浏览器客户端应用平台,基本都是以事件驱动的,即某个事件发生,然后做出相应的动作。浏览器的事件表示的某些事情发生的信号,下面是比较常用的事件:


2冒泡原理:
想象一下,气泡从水底开始往上升,由深到浅,升到最上面。在上升的过程中,气泡会经过不同深度层次的水。这个气泡就相当于事件,而水则相当于我们的整个DOM树;事件从DOM树的底层层往上传递,直到传递到DOM的根节点


我们现在想实现这样的功能,在div1点击的时候,弹出“我是最外层div”,点击span时,弹出“我是span”——》终止事件冒泡
方法一:在相应的处理函数内,加入event.stopPropagation(),终止事件的广播分发,这样事件停留在本节点,不会再往外传播
<script>
window.onload=function(){
document.getElementById("div1").addEventListener("click",function(event){
alert("我是最外层div");
event.stopPropagation();
});
document.getElementById("div2").addEventListener("click",function(event){
alert("我是第二层div");
event.stopPropagation();
});
document.getElementById("span").addEventListener("click",function(event){
alert("我是span");
event.stopPropagation();
});
}
//缺点:为了实现点击特定的元素显示对应的信息,要求每个元素的子元素也必须终止事件的冒泡传递,即跟别的元素功能上强关联,这样的方法会很脆弱。比如,如果span 元素的处理函数没有执行冒泡终止,则事件会传到div2 上,这样会造成div2 的提示信息
</script>
方法二:元素收到事件后,判断是否符合要求,然后做相应的处理,然后事件继续冒泡往上传递,进一步的,我们把本来每个元素都要有的处理函数,都交给了其祖父节点body 元素来完成了,也就是说,span,div2,div1 将自己的响应逻辑委托给body,让它来完成相应逻辑,自己不实现相应逻辑,这个模式,就是所谓的事件委托。
<script>
window.onload=function(){
document.getElementById("body").addEventListener("click",eventPerformed);
}
funtion eventPerformed(event){
var target=event.taget;
switch(target.id){
case"span":
alert("我是span");
break;
case"div1":
alert("我是div1");
break;
case"div2":
alert("我是div2");
break;
}
}
</script>

二 信息验证,普通验证和异步请求验证。模仿插件自己写的插件,目前测试没有问题,注释很明确且详细,贴上代码
插件
var ex = {
/*
{
form : document.getElementById(""), // 表单DOM
submit : document.getElementById(""), // 提交按钮,可选(若有项目验证失败,则禁用按钮阻止提交)
rules : {
email : funtion(val, result){
if(xxx)
return result(false); // 验证失败
else
return result(true); // 验证成功
},
ajaxUser: function (val, result){ // result 为结果回调函数,需将验证结果传入 true/false
ex.ajax({
url : "http://temp.com/", // ajax请求地址
success : function(data){ // ajax 请求成功的回调函数
return result(data.status == 200);
},
error : function(e){ // ajax 请求失败的回调函数
console.log(e.message)
},
data : "user=jill", // 发送的数据
type : "get", // 请求方式:get/post
dataType : "json" // 服务端返回数据类型
});
}
},
msg : { // 错误提示信息
user : { // 绑定控件 使用 data-warn 属性
email : "无效用户名", // 对应验证规则
noempty : "用户名不能为空"
}
},
able : function (result){ // 根据整体验证结果执行, 可选(用于做DOM操作阻止提交表单)
},
failed : function (back){ // 验证控件failed执行方式
back.val ;
back.msg ;
back.ele ;
},
final : function (){ // 提交表单动作
ex.ajax({
url : "http://120.25.66.55/ivan/checkParams.php", // ajax请求地址
data : "user=jill&passwd=123456", // 发送的数据
type : "get", // 请求方式:get/post
dataType : "json", // 服务端返回数据类型
success : function(data){ // ajax 请求成功的回调函数
switch (data.statusCode) {
case 200:
alert("登录成功");
location = "somewhere";
break;
case 201:
alert("密码或用户名错误");
default:
break;
}
},
error : function(e){ // ajax 请求失败的回调函数
console.log(e.message);
}
});
}
}
*/
verify: function (obj) {
if (undefined == obj.form) obj.form = document.forms[0];
if (undefined == obj.submit) obj.form = document.forms[0];
if (undefined == obj.rule) obj.rule = {};
if (undefined == obj.msgs) obj.msgs = {};
// 全局规则
var g_rule = {
v_noempty: function (val, fn) {
return fn(val != "");
},
v_number: function (val) {
return fn(!isNaN(val));
}
}
var stopEvent = function (ev) {
ev.preventDefault && ev.preventDefault();
ev.stopPropagation && ev.stopPropagation();
ev.cancelBubble = true;
return false;
};
var failed = function (ele, rule) {
var msg = "";
if (undefined != ele.dataset.warn) msg = obj.msgs[ele.dataset.warn][rule];
if (undefined != obj.failed) obj.failed({
"val": ele.value,
"msg": msg,
"ele": ele
});
};
var main = function (ev, ele, fn) {
var className = ele.className;
for (key in obj.rules) {
g_rule[key] = obj.rules[key];
}
for (key in g_rule) {
if (!ex.classop.find(className, key)) continue;
if (!g_rule[key](ele.value, function (result) {
if (undefined == obj.able) obj.able(result);
if (result) {
for (var i = 0; i < verifyList.length; i++) {
if (verifyList[i]) continue;
if (undefined != obj.submit) document.getElementById(obj.submit).disabled = true;
return false;
}
if (undefined != obj.submit) document.getElementById(obj.submit).disabled = false;
return true;
} else {
failed(ele, key);
if (undefined == ele.exid) ele.exid = verifyList.length;
verifyList[ele.exid] = false;
if (undefined != obj.submit) document.getElementById(obj.submit).disabled = false;
return false;
}
})) return false;
}
if (undefined == obj.rules) return true;
return true;
};
var vForm = function (form) {
for (key in obj.rules) {
g_rule[key] = obj.rules[key];
}
for (key in g_rule) {
var eles = document.getElementsByClassName(key);
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
if (!g_rule[key](eles[i].value, function (result) {
if (undefined == obj.able) obj.able(result);
if (result) {
for (var i = 0; i < verifyList.length; i++) {
if (verifyList[i]) continue;
if (undefined != obj.submit) document.getElementById(obj.submit).disabled = true;
return false;
}
if (undefined != obj.submit) document.getElementById(obj.submit).disabled = false;
return true;
} else {
failed(ele, key);
if (undefined == ele.exid) ele.exid = verifyList.length;
verifyList[ele.exid] = false;
if (undefined != obj.submit) document.getElementById(obj.submit).disabled = false;
return false;
}
})) return false;
}
}
return true;
}
var verifyList = {};
document.addEventListener('DOMContentLoaded', function () {
document.removeEventListener('DOMContentLoaded', arguments.callee, false);
var changeListen = function (ev) {
ev = ev || window.event;
var target = ev.target || ev.srcElement;
main(ev, target);
};
document.getElementById(obj.form).addEventListener('change', changeListen, false);
//document.getElementById(obj.form).addEventListener('click', changeListen, false);
document.getElementById(obj.form).addEventListener('input', changeListen, false);
document.getElementById(obj.form).addEventListener('propertychange', changeListen, false);
document.getElementById(obj.form).addEventListener('submit', function (ev) {
ev = ev || window.event;
var target = ev.target || ev.srcElement;
var result = vForm(document.getElementById(obj.form));
if (!result || (undefined != obj.final && !obj.final(ev, target)))
return stopEvent(ev);
}, false);
}, false);
},
/*
ajax({
url : "http://~", // ajax请求地址
success : function(data){ // ajax 请求成功的回调函数
// do something
},
error : function(e){ // ajax 请求失败的回调函数
},
data : "id=3", // 发送的数据
type : "get" // 请求方式:get/post
dataType : "json" // 服务端返回数据类型
})
*/
ajax: function (obj) {
if (undefined == obj.url) throw ("ajax url was undefined.");
if (undefined == obj.success) obj.success = function (d) {
};
if (undefined == obj.error) obj.error = function (d) {
};
if (undefined == obj.data) obj.data = "";
if (undefined == obj.type) obj.type = "get";
if (undefined == obj.dataType) obj.dataType = "text";
try {
var oReq = new XMLHttpRequest();
oReq.onload = function (e) {
obj.success(e.target.response);
};
var url = obj.url +
obj.url.indexOf("?") < 0 ? "?" : "&" + "___rand=" + Math.random();
if ("get" == obj.type.toLowerCase()) url = url + "&" + obj.data;
oReq.open(obj.type, obj.url, true);
//判断请求方式是get/post,若是get请求方式,直接发送,若是post请求,则添加xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
oReq.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
oReq.send(obj.data);
oReq.responseType = obj.dataType;
if ("get" == obj.type.toLowerCase()) oReq.send();
else oReq.send(obj.data);
} catch (e) {
obj.error(e);
}
},
classop: {
// 移除class
remove: function (className, removeName) {
className = className.Trim().replace(removeName, "");
className = className.replace(" ", "").Trim();
return className;
},
// 添加class
add: function (className, addName) {
className = className.Trim() + " " + addName.Trim();
className = className.replace(" ", " ").Trim();
return className;
},
// 查找class
find: function (className, findName) {
if (!className || "" == className) return false;
var classList = className.Trim().split(" ");
for (var i = 0; i < classList.length; i++) {
if (classList[i] == findName.Trim()) {
return true;
}
}
return false;
}
}
}
/* ---------------------------------------------------------------
* 重載JS中String.prototype函數功能
* 功能:去掉字符串(左|右)指定字符,若不传参,则去掉空白符
* 示例:var str = " 123 ";
* str = str.Trim(); // "123"
* -------------------------------------------------------------- */
String.prototype.Trim = function (str) {
return this.replace((new RegExp("(^(" + (str || "\\s") + ")*)|((" + (str || "\\s") + ")*$)", "g")), '');
}
String.prototype.LTrim = function (str) {
return this.replace((new RegExp("(^(" + (str || "\\s") + ")*)", "g")), '');
}
String.prototype.RTrim = function (str) {
return this.replace((new RegExp("((" + (str || "\\s") + ")*$)", "g")), '');
}
引入此插件,下面分别贴上关键代码 普通验证和异步验证
HTML里几个参数要对应噢
1 form表单的id
2 input 标签 需加入,a绑定控件 使用 data-warn
属性;
b绑定错误信息 ,使用class
属性
其中,id
,name
不做要求,留给后台
拿下面异步请求的html代码作为例子:
<form action="Main_main.html" method="post" enctype="application/x-www-form-urlencoded" id="login_form">
<fieldset>
<div class="inputBox line">
<input type="text" name="user" id="user" value="" placeholder="用户名/邮箱" data-warn="user" class="required v_noempty name " /><span class="icon-ic_user"></span>
</div>
<div class="inputBox">
<input type="password" name="password" id="password" value="" placeholder="密码" data-warn="pwd" class="required v_noempty pwd" /><span class="icon-ic_password"></span>
<a href="Reg_findPassword.html" class="TofindPwd">忘记密码?</a>
</div>
</fieldset>
<div class="inputBox">
<input type="submit" value=">" id="submit_btn" />
</div>
</form>
普通验证
<script src="../js/dk_verify.js" type="text/javascript"></script>
<script>
ex.verify({
form: "Reg_findPwd_form", // 表单DOM
submit: "PopUpBtn", // 提交按钮,可选(若有项目验证失败,则禁用按钮阻止提交)
rules: {
//验证用户名(长度 大于一 小于十)
name: function(val, result) {
if (val.length < 1 || val.length > 10) {
return result(false); // 验证失败
} else {
var tick_box = document.getElementById('tick_box');
tick_box.innerHTML = "";
return result(true); // 验证成功
}
},
//验证email格式(普通email验证正则表达)
email: function(val, result) {
var regular = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
var r=val.match(regular);
if (r ==null) {
return result(false); // 验证失败
} else {
var tick_box = document.getElementById('tick_box');
tick_box.innerHTML = "";
return result(true); // 验证成功
}
},
},
msgs: { // 错误提示信息
user: { // 绑定控件 使用 data-warn 属性
name: "用户名长度不超过20个字节", // 对应验证规则
v_noempty: "用户名不能为空"
},
email: {
email: "请输入有效邮箱", // 对应验证规则
v_noempty: "邮箱不能为空"
}
},
able: function(result) { // 根据整体验证结果执行, 可选(用于做DOM操作阻止提交表单)
},
failed: function(back) { // 验证控件failed执行方式
back.val;
back.msg;
back.ele;
var tick_box = document.getElementById('tick_box');
tick_box.innerHTML = back.msg;
},
final: function(ev, ele) { // 提交表单动作
//若验证成功,则会跑此函数,验证后需要干什么,在这里写下逻辑即可,比如,需要定时跳转
//获取元素
var pop_up = document.getElementById('pop_up');
var pop_wrap = document.getElementById('pop_wrap');
var PopUpBtn = document.getElementById('PopUpBtn');
document.body.style.height = view().h + "px";
//点击完成按钮,弹出弹窗
PopUpBtn.onclick = function() {
pop_up.style.height = view().h + "px";
pop_up.style.display = 'block';
pop_wrap.style.display = 'block';
delayURL();
return true;
};
//定时3秒跳转页面
function delayURL() {
var delay = document.getElementById("time").innerHTML;
//delayURL如果加引号,就相当于eval("delayURL()"),这样的话delayURL只会在全局里面找,但是不加引号,就会直接传递现在定义的delayURL
var t = setTimeout(delayURL, 1000);
if (parseInt(delay) > 0) {
delay--;
document.getElementById("time").innerHTML = delay;
} else {
clearTimeout(t);
//手动获取表单
document.getElementById("Reg_findPwd_form").submit();
//页面跳转页面URL
window.location.href = "https://www.baidu.com/";
}
};
}
});
</script>
异步验证
//引入插件
<script src="../js/dk_verify.js" type="text/javascript"></script>
<script>
ex.verify({
form: "login_form", // 表单DOM
submit: "submit_btn", // 提交按钮,可选(若有项目验证失败,则禁用按钮阻止提交)
rules: {
//验证用户名(长度 大于一 小于十)
name: function(val, result) {
if (val.length < 1 || val.length > 10){
return result(false); // 验证失败
}
else{
var tick_box = document.getElementById('tick_box');
tick_box.innerHTML = "";
return result(true); // 验证成功
}
},
//验证email格式(普通email验证正则表达)
email: function(val, result) {
var regular = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
var r=val.match(regular);
if (r ==null) {
return result(false); // 验证失败
}
else{
var tick_box = document.getElementById('tick_box');
tick_box.innerHTML = "";
return result(true); // 验证成功
}
},
//验证password格式(长度 大于四 小于十)
pwd: function(val, result) {
if (val.length < 4 || val.length > 10){
return result(false); // 验证失败
}
else{
var tick_box = document.getElementById('tick_box');
tick_box.innerHTML = "";
return result(true); // 验证成功
}
},
//异步请求验证
ajaxUser: function(val, result) { // result 为结果回调函数,需将验证结果传入 true/false
var user=document.getElementById('user');
ex.ajax({
url: "http://192.168.199.233:8080/loginForjs", // ajax请求地址
success: function(data) { // ajax 请求成功的回调函数
switch (data.statusCode) {
case 200:
return result(200);
break;
case 201:
return result(201);
default:
break;
}
},
error: function(e) { // ajax 请求失败的回调函数
console.log(e.message)
},
data: 'userName='+user.value, // 发送的数据
type: "post", // 请求方式:get/post
dataType: "json" // 服务端返回数据类型
});
}
},
msgs: { // 错误提示信息
user: { // 绑定控件 使用 data-warn 属性
name:"用户名长度不超过10个字节",
email: "无效用户名", // 对应验证规则
v_noempty: "用户名不能为空"
},
pwd:{
pwd:"请输入{4-10}个字符长的值",
v_noempty: "密码不能为空"
}
},
able: function(result) { // 根据整体验证结果执行, 可选(用于做DOM操作阻止提交表单)
},
failed: function(back) { // 验证控件failed执行方式
back.val;
back.msg;
back.ele;
var tick_box = document.getElementById('tick_box');
tick_box.innerHTML = back.msg;
},
final: function(ev, ele) { // 提交表单动作
var user=document.getElementById('user');
var pwd=document.getElementById('password');
ex.ajax({
url: "http://192.168.199.233:8080/loginForjs", // ajax请求地址
data: 'userName='+user.value+'&password='+pwd.value, // 发送的数据
type: "post", // 请求方式:get/post
dataType: "json", // 服务端返回数据类型
success: function(data) { // ajax 请求成功的回调函数
var redirectUrl=data.redirectUrl;
switch (data.statusCode) {
case 200:
alert("登录成功");
location = redirectUrl;
break;
case 201:
alert("密码或用户名错误");
default:
break;
}
},
error: function(e) { // ajax 请求失败的回调函数
console.log(e.message);
}
});
return false;
}
});
</script>
网友评论