源生JS怎样实现todolist功能
这次给大家带来源生JS怎样实现todolist功能,源生JS实现todolist功能的注意事项有哪些,下面就是实战案例,一起来看一下。
该项目主要可以练习js操控dom,事件,事件触发之间的逻辑关系,以及如何写入缓存,获取缓存。
主要功能:
将用户输入添加至待办项
可以对todolist进行分类,用户勾选即将待办项分入已完成组
todolist的每一项可删除和编辑
将用户输入数据写入localStorage本地缓存,实现对输入数据的保存
可以清楚域名下本地缓存,并清空所有todolist项
具体功能的实现
HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>todolist-prime</title>
<link rel="stylesheet" href="yuanshengcss" rel="external nofollow" >
</head>
<body>
<header>
<section>
<label for="add_list">My todolist</label>
<input type="text" id="add_list" name="add_list" placeholder="type here" required>
</section>
</header>
<p class="content">
<h1>未完成<span id="todocount"></span></h1>
<ol id="todolist">
</ol>
<h1>已完成<span id="donecount"></span></h1>
<ol id="donelist">
</ol>
</p>
<p id="clear">
<span style="white-space:pre;"> </span><button id="clearbutton"><h3>全部清除</h3></button>
</p>
<script src="todolist-primejs"></script>
</body>
</html>
JS代码及分析
创建一个数组对象来保存用户输入的数据,数组的每一项都是一个对象,对象的"todo"属性保存着用户输入的数据,"done"属性可理解为用户输入数据的标签,主要用来对"todo"值进行分类。
每次用户输入完数据,都要更新缓存,并初始化输入框。
function addTodolist(e) {
var obj_list = {
todo: "", //用于存储用户输入的数据
done: false //初始化用户输入的数据属性,以便对用户待办事项进行分类
};
documentgetElementById("add_list")value = documentgetElementById("add_list")valuetrim();
if (documentgetElementById("add_list")valuelength === 0){
alert("不能为空");
return;
}
obj_listtodo = documentgetElementById("add_list")value;
todolistpush(obj_list);
saveData(todolist);
documentgetElementById("add_list")value = ""; //初始化输入框
load(); //将用户输入的数据添加至dom节点
documentgetElementById("add_list")focus();
}
将输入的数据添加至dom节点,并且根据输入数据属性("done")的值进行分类。
<span style="font-size:14px;">function load(){
var todo = documentgetElementById("todolist"),
done = documentgetElementById("donelist"),
todocount = documentgetElementById("todocount"),
donecount = documentgetElementById("donecount"),
todoString = "",
doneString = "",
todoCount = 0,
doneCount = 0;
documentgetElementById("add_list")focus();
todolist = loadData();
//todolist数组对象里若包含用户输入数据,则将其添加至dom节点;若为空对象,则初始化页面。
if (todolist != null){
for (var i=0; i<todolistlength; i ++){
if(!todolist[i]done){
todoString += "<li>"
//通过onchange事件,复选框值有改变则调用update函数,并改变输入数据“done”属性的布尔值,这样
//下次load()后,这段数据会进入不同的分组,未完成的事项分入已完成事项组,已完成事项分入未完成事项组
//点击事项调用edit函数
//点击“-”,调用remove函数
+ "<input type='checkbox' onchange='update("+i+", \"done\", true)'>"
+ "<p id='p-"+i+"' onclick='edit("+i+")'>" + todolist[i]todo + "</p>" +
"<a onclick='remove("+i+")'>-</a>" +
"</li>"; //将每次用户输入的数据,通过节点<p>利用id标记,以便后续编辑功能定位
todoCount ++;
}
else{
doneString += "<li>"
+ "<input type='checkbox' "
+ "onchange='update("+i+", \"done\", false)' checked>"
+ "<p id='p-"+i+"' onclick='edit("+i+")'>" + todolist[i]todo + "</p>"
+ "<a onclick='remove("+i+")'>-</a>"
+ "</li>";
doneCount ++;
}
}
todoinnerHTML = todoString;
doneinnerHTML = doneString;
todocountinnerHTML = todoCount;
donecountinnerHTML = doneCount;
}
else {
todoinnerHTML = "";
doneinnerHTML = "";
todocountinnerHTML = 0;
donecountinnerHTML = 0;
}
}</span>
击事项触发编辑事件,将可编辑表单控件插入段落中,并将用户输入的值通过update函数对todolist数组里存储的数据进行更新
function edit(i) {
var p = documentgetElementById('p-' + i),
pContent = pinnerHTML,
inputId;
//通过upadate函数对todolist数组相应项进行更新,将用户输入的内容写入到todolist数组相应项的todo属性中
function confirm() {
if (inputIdvaluelength === 0) {
pinnerHTML = pContent;
alert("内容不能为空");
}
else {
update(i, "todo", inputIdvalue); //修改事项内容后,更新数组里对应项"todo"属性的值,以便更新dom节点
}
}
//结合keypress事件,按下enter键,调用confirm函数
function enter(e) {
if (ekeyCode == 13){
confirm();
}
}
pinnerHTML = "<input type='text' id='input-"+i+"' value='"+pContent+"'>";
inputId = documentgetElementById('input-'+i);
inputIdfocus();
inputIdsetSelectionRange(0, inputIdvaluelength);
inputIdonblur = confirm; //表单控件失去焦点,调用confirm函数,即对页面内容进行更新
inputIdonkeypress = enter; //对按键事件进行监控
}
将数组todolist相应项的属性(“todo”或“done”)进行更新,并加载
function update(i, field, value) {
todolist[i][field] = value;
saveData(todolist);
load();
}
删除相应项,并加载
function remove(i) {
todolistsplice(i, 1);
saveData(todolist); //相同名称的缓存会覆盖,更新缓存
load();
}
将用户数据保存至本地缓存
function saveData(data) {
localStoragesetItem("mytodolist", JSONstringify(data)); //JS对象转换成JSON对象存进本地缓存
}
从本地缓存中获取数据,有数据,赋值给todolist,这样刷新页面用户数据依旧存在
function loadData() {
var hisTory = localStoragegetItem("mytodolist");
if(hisTory !=null){
return JSONparse(hisTory); //JSON对象转换为JS对象
}
else { return []; }
}
清楚本地缓存
function clear() {
localStorageclear();
load();
}
一系列事件的监听
windowaddEventListener("load", load); //页面加载完毕调用load函数
documentgetElementById("clearbutton")onclick = clear;
documentgetElementById("add_list")onkeypress = function (event) {
if(eventkeyCode === 13){
addTodolist();
}
};
CSS
body {
margin: 0px;
padding: 0px;
font-size: 16px;
background-color: gainsboro;
}
header {
height: 50px;
background-color: cornflowerblue;
}
header section {
margin: 0 auto;
width: 40%;
}
header section label {
float: left;
line-height: 50px; /设置line-height和包含块高度一致,以实现行内元素垂直居中/
font-size: 20px;
}
#add_list {
float: right;
margin-top: 11px;
width: 60%;
height: 24px;
border-radius: 5px;
box-shadow: 0 1px 0 black;
font-size: 18px;
text-indent: 10px;
}
h1 {
position: relative;
}
h1 span {
position: absolute;
top: 1px;
right: 5px;
display: inline-block;
width: 23px;
height: 23px;
border-radius: 23px; /创建圆形标记/
line-height: 23px;
font-size: 18px;
text-align: center;
background: #E6E6FA;
}
content {
width: 40%;
margin: 0 auto;
}
li {
position: relative;
margin-bottom: 10px;
border-radius: 5px;
padding: 0 10px;
height: 32px;
box-shadow: 0 1px 0 black;
line-height: 32px;
background-color: burlywood;
list-style: none;
}
ol li input {
position: absolute;
top: 4px;
left: 10px;
width: 20px;
height: 20px;
cursor: pointer;
}
p{
margin: 0;
}
ol li p {
display: inline;
margin-left: 35px;
}
ol li p input{
top: 5px;
margin-left: 35px;
width: 70%;
height: 14px;
font-size: 14px;
line-height: 14px;
}
ol li a {
position: absolute;
top: 8px;
right: 10px;
display: inline-block;
border: 1px;
border-radius: 50%;
width: 16px;
height: 16px;
font-size: 32px;
line-height: 10px;
color: red;
font-weight: bolder;
cursor: pointer;
background-color: gray;
}
#clear {
width: 100px;
margin: 0 auto;
}
#clearbutton {
border-color: red;
border-radius: 5px;
box-shadow: 0 1px 0 yellow;
cursor: pointer;
}
button h3{
font-size: 13px;
line-height: 13px;
} 相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!
推荐阅读:
element UI怎么导出Excel
vue slot怎么在子组件中显示父组件传递
下面小编就为大家分享一篇原生js实现简单的焦点图效果实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
用到一些封装好的运动函数,主要是定时器
效果为和的描述定时自动更换。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
ul,
li,
p,
h3 {
padding: 0;
margin: 0;
list-style: none;
}
img {
border: none;
vertical-align: top;
}
#bg_box {
width: 1000px;
height: 590px;
margin: 50px auto;
position: relative;
background: url(img/bg1jpg) no-repeat;
}
pic {
width: 440px;
height: 274px;
position: absolute;
top: 50px;
left: 220px;
overflow: hidden;
}
li_box {
width: 1760px;
height: 274px;
position: absolute;
left: 0;
}
tags {
width: 440px;
height: 80px;
position: absolute;
bottom: -80px;
background-image: linear-gradient(0deg, rgba(0, 0, 0, 04) 0%, rgba(255, 255, 255, 0) 100%);
color: white;
padding-left: 20px;
padding-top: 15px;
box-sizing: border-box;
}
tags:nth-of-type(1) {
/bottom: 0;/
}
img {
float: left;
width: 440px;
height: 274px;
}
h3 {
font: bold 20px/30px "微软雅黑";
}
p {
font: 16px/30px "微软雅黑";
}
</style>
<script src="tweenjs"></script>
<script src="commomjs"></script>
<script type="text/javascript">
windowonload = function() {
//获取元素
var liBbox = $('ul')[0];
var li = $('li');
var tags = $('tags')
var num = 0; //设置初始位置
Change()
function Change() {
var M = tags[num];
MTween(M, 'bottom', 0, 500, 'px', 'linear', function() { //先让描述内容出现
num++
if(num > lilength - 1) { //边界设置。
return;
}
setTimeout(function() {
MTween(M, 'bottom', -80, 500, 'px', 'linear', function() { //让描述内容不显示
MTween(liBbox, 'left', -num 440, 800, 'px', 'linear', function() {
Change();
}); //切换
});
}, 1000)
});
}
}
</script>
</head>
<body>
<section id="bg_box">
<p class="pic">
<ul class="li_box">
<li>
<img class="img" src="img/a5gif">
</li>
<li>
<img class="img" src="img/a6gif">
</li>
<li>
<img class="img" src="img/a7gif">
</li>
<li>
<img class="img" src="img/a8gif">
</li>
</ul>
<p class="tags">
<h3 class="title">下雨了~~~</h3>
<p class="tag">这是一个适合在家睡觉的日子!!</p>
</p>
<p class="tags">
<h3 class="title">包饺子~~~</h3>
<p class="tag">一只会居家过日子的小狐狸!!</p>
</p>
<p class="tags">
<h3 class="title">生气了~~~</h3>
<p class="tag">吃掉好吃的就不生气了!!</p>
</p>
<p class="tags">
<h3 class="title">出发了~~~</h3>
<p class="tag">来一段说走就走的旅行!!</p>
</p>
</p>
</section>
</body>
</html>commomjs
function MTween(obj,attr,end,duration,unit,way,callBack){
if(objisAnim) return;
//obj开始运动了 自定义属性
objisAnim = true;
if(!way){ //如果用户没有选择运动方式就默认匀速
way = 'linear';
}
if(!unit){ //如果用户没有选择运动方式就默认匀速
unit = '';
}
var start = parseFloat(getStyle(obj,attr));//起始位置
// var end = 1000;//目标点
// var duration = 1000;//动画执行的总时间 单位是毫秒
var startTime = Datenow();
var s = end - start; //总路程
// var v = s/duration; //计算出来的速度
//每次20ms走一帧
clearInterval(timer);
var timer = 0;
timer = setInterval(function(){
var endTime = Datenow();
//计算出当前时间
var t = endTime-startTime;
if(t>=duration){
t = duration;
clearInterval(timer);//到达目标点要清除定时器
}
// objstyle[attr] = ts/duration+start+'px';
// consolelog(Tween[way](t,start,s,duration))
objstyle[attr] = Tween[way](t,start,s,duration)+unit;
//透明度的兼容处理
if(attr=='opacity'){
objstylefilter = 'Alpha(opacity='+Tween[way](t,start,s,duration)100+')';
}
if(t==duration){
objisAnim = false;
//等到上一个动画完成 然后再调用
if(callBack){
callBack();
}
}
},20);
}tweenjs
/
t : time 已过时间 当前时间-初始时间
b : begin 起始值
c : count 总的运动值 总路程
d : duration 持续时间 总时间
s = vt; => c = tc/d 这里只计算总共要运动的路程 ,不包括起始位置
attrVal = tc/d + b;
曲线方程
/
//Tweenlinear();
var Tween = {
linear: function (t, b, c, d){ //匀速
return ct/d + b;
},
easeIn: function(t, b, c, d){ //加速曲线
return c(t/=d)t + b;
},
easeOut: function(t, b, c, d){ //减速曲线
return -c (t/=d)(t-2) + b;
},
easeBoth: function(t, b, c, d){ //加速减速曲线
if ((t/=d/2) < 1) {
return c/2tt + b;
}
return -c/2 ((--t)(t-2) - 1) + b;
},
easeInStrong: function(t, b, c, d){ //加加速曲线
return c(t/=d)ttt + b;
},
easeOutStrong: function(t, b, c, d){ //减减速曲线
return -c ((t=t/d-1)ttt - 1) + b;
},
easeBothStrong: function(t, b, c, d){ //加加速减减速曲线
if ((t/=d/2) < 1) {
return c/2tttt + b;
}
return -c/2 ((t-=2)ttt - 2) + b;
},
elasticIn: function(t, b, c, d, a, p){ //正弦衰减曲线(弹动渐入)
if (t === 0) {
return b;
}
if ( (t /= d) == 1 ) {
return b+c;
}
if (!p) {
p=d03;
}
if (!a || a < Mathabs(c)) {
a = c;
var s = p/4;
} else {
var s = p/(2MathPI) Mathasin (c/a);
}
return -(aMathpow(2,10(t-=1)) Mathsin( (td-s)(2MathPI)/p )) + b;
},
elasticOut: function(t, b, c, d, a, p){ //正弦增强曲线(弹动渐出)
if (t === 0) {
return b;
}
if ( (t /= d) == 1 ) {
return b+c;
}
if (!p) {
p=d03;
}
if (!a || a < Mathabs(c)) {
a = c;
var s = p / 4;
} else {
var s = p/(2MathPI) Mathasin (c/a);
}
return aMathpow(2,-10t) Mathsin( (td-s)(2MathPI)/p ) + c + b;
},
elasticBoth: function(t, b, c, d, a, p){
if (t === 0) {
return b;
}
if ( (t /= d/2) == 2 ) {
return b+c;
}
if (!p) {
p = d(0315);
}
if ( !a || a < Mathabs(c) ) {
a = c;
var s = p/4;
}
else {
var s = p/(2MathPI) Mathasin (c/a);
}
if (t < 1) {
return - 05(aMathpow(2,10(t-=1))
Mathsin( (td-s)(2MathPI)/p )) + b;
}
return aMathpow(2,-10(t-=1))
Mathsin( (td-s)(2MathPI)/p )05 + c + b;
},
backIn: function(t, b, c, d, s){ //回退加速(回退渐入)
if (typeof s == 'undefined') {
s = 170158;
}
return c(t/=d)t((s+1)t - s) + b;
},
backOut: function(t, b, c, d, s){
if (typeof s == 'undefined') {
s = 370158; //回缩的距离
}
return c((t=t/d-1)t((s+1)t + s) + 1) + b;
},
backBoth: function(t, b, c, d, s){
if (typeof s == 'undefined') {
s = 170158;
}
if ((t /= d/2 ) < 1) {
return c/2(tt(((s=(1525))+1)t - s)) + b;
}
return c/2((t-=2)t(((s=(1525))+1)t + s) + 2) + b;
},
bounceIn: function(t, b, c, d){ //弹球减振(弹球渐出)
return c - Tween['bounceOut'](d-t, 0, c, d) + b;
},
bounceOut: function(t, b, c, d){//
if ((t/=d) < (1/275)) {
return c(75625tt) + b;
} else if (t < (2/275)) {
return c(75625(t-=(15/275))t + 075) + b;
} else if (t < (25/275)) {
return c(75625(t-=(225/275))t + 09375) + b;
}
return c(75625(t-=(2625/275))t + 0984375) + b;
},
bounceBoth: function(t, b, c, d){
if (t < d/2) {
return Tween['bounceIn'](t2, 0, c, d) 05 + b;
}
return Tween['bounceOut'](t2-d, 0, c, d) 05 + c05 + b;
}
}上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
详细介绍ES6中的代理模式(Proxy)
构建webpack的详细介绍
使用webpack如何实现文件打包
利用webpack搭建vue脚手架
使用Vue组件如何实现日历(详细教程)
下面是我给大家整理的如何在JS中实现打印的方式,有兴趣的同学可以去看看。
1JS实现打印的方式
方式一:windowprint()
windowprint();会弹出打印对话框,打印的是windowdocumentbodyinnerHTML中的内容,下面是从网上摘到的一个局部打印的例子,该例子的不足是打印会修改页面的内容。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>局部打印案例</title>
<script type="text/javascript">
function doPrint() {
bdhtml=windowdocumentbodyinnerHTML;
sprnstr="<!--startprint-->";
eprnstr="<!--endprint-->";
prnhtml=bdhtmlsubstr(bdhtmlindexOf(sprnstr)+17);
prnhtml=prnhtmlsubstring(0,prnhtmlindexOf(eprnstr));
windowdocumentbodyinnerHTML=prnhtml;
windowprint();
}
</script>
</head>
<body>
<p>1不需要打印的地方</p>
<p>2这里不要打印啊</p>
<!--startprint--><!--注意要加上html里star和end的这两个标记-->
<h1>打印标题</h1>
<p>打印内容~~</p>
<!--endprint-->
<button type="button" onclick="doPrint()">打印</button>
<p>不打印的地方啊哈哈哈哈</p>
<p>2</p>
</body>
</html>
[javascript] view plain copy
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>局部打印案例</title>
<script type="text/javascript">
function doPrint() {
bdhtml=windowdocumentbodyinnerHTML;
sprnstr="<!--startprint-->";
eprnstr="<!--endprint-->";
prnhtml=bdhtmlsubstr(bdhtmlindexOf(sprnstr)+17);
prnhtml=prnhtmlsubstring(0,prnhtmlindexOf(eprnstr));
windowdocumentbodyinnerHTML=prnhtml;
windowprint();
}
</script>
</head>
<body>
<p>1不需要打印的地方</p>
<p>2这里不要打印啊</p>
<!--startprint--><!--注意要加上html里star和end的这两个标记-->
<h1>打印标题</h1>
<p>打印内容~~</p>
<!--endprint-->
<button type="button" onclick="doPrint()">打印</button>
<p>不打印的地方啊哈哈哈哈</p>
<p>2</p>
</body>
</html>方式二:使用html 标签<object>引入Webbrowser控件
这种方式是其只兼容IE,其他浏览器不可使用,同时IE10以下的浏览器才可以使用,调用方式如下:
<body>
<object id="WebBrowser" classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height="0" width="0"> </object>
</body>
<script>
WebBrowserExecWB(1,1) //打开
WebBrowserExecWB(2,1) //关闭现在所有的IE窗口,并打开一个新窗口
WebBrowserExecWB(4,1) //保存网页
//--------------- 常用 ---------------
WebBrowserExecWB(6,1) //打印
WebBrowserExecWB(7,1) //打印预览
WebBrowserExecWB(8,1) //打印页面设置
//-------------------------------------
WebBrowserExecWB(10,1) //查看页面属性
WebBrowserExecWB(15,1) //撤销
WebBrowserExecWB(17,1) //全选
WebBrowserExecWB(22,1) //刷新
WebBrowserExecWB(45,1) //关闭窗体无提示
</script>
<body>
<object id="WebBrowser" classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height="0" width="0"> </object>
</body>
<script>
WebBrowserExecWB(1,1) //打开
WebBrowserExecWB(2,1) //关闭现在所有的IE窗口,并打开一个新窗口
WebBrowserExecWB(4,1) //保存网页
//--------------- 常用 ---------------
WebBrowserExecWB(6,1) //打印
WebBrowserExecWB(7,1) //打印预览
WebBrowserExecWB(8,1) //打印页面设置
//-------------------------------------
WebBrowserExecWB(10,1) //查看页面属性
WebBrowserExecWB(15,1) //撤销
WebBrowserExecWB(17,1) //全选
WebBrowserExecWB(22,1) //刷新
WebBrowserExecWB(45,1) //关闭窗体无提示
</script>这种方式优势是在IE下可以弹出打印预览,这是打印很人性化的功能,但是遗憾的是高版本的IE浏览器不支持WebBrowser了
方式三:采用documentexecCommand(”print”)
该方式也兼容各个版本的浏览器,同windowprint()一样,其启动的是打印对话框,chrome的打印对话框自带预览功能,但是IE、火狐仅仅只弹出打印设置对话框,没有预览功能。
上面是我整理给大家的如何在JS中实现打印的方式,希望今后会对大家有帮助。
相关文章:
有关在js中下载文件简单操作(附上代码,详细解答)
在 js中function前面加!方面的问题,代码附上
详细讲解JS和app交互的方式(代码附上 )
为什么要使用模块模式
因为在全局作用域中声明的变量和函数都自动成为全局对象Window的属性,这经常会导致命名冲突,还会导致一些非常重要的可维护性难题,全局变量越多,引入错误BUG的概率就越大!所以我们应当尽可能少地使用全局变量,模块化的目的之一就是为了解决该问题的!
零全局变量模式
该模式应用场景较少,通过一个IIFE(立即执行的匿名函数),将所有代码包装起来,这样一来所有的变量、函数都被隐藏在该函数内部,不会污染全局。
使用情景:
当该代码不会被其它代码所依赖时;
当不需要在运行时不断的扩展或修改该代码时;
当代码较短,且无需和其它代码产生交互时;
单全局变量模式
基本定义
单全局变量模式即只创建一个全局变量(或尽可能少地创建全局变量),且该全局变量的名称必须是独一无二的,不会和现在、将来的内置API产生冲突,将所有的功能代码都挂载到这个全局变量上。
它已经被广泛应用于各种流行的类库中,如:
YUI定义了唯一的YUI全局对象
JQuery定义了两个全局对象,$和JQuery
Dojo定义了一个dojo全局对象
Closure定义了一个goog全局对象
例子:
var Mymodule= {};
MymoduleBook = function(){};
MymoduleBookprototypegetName = function(){};
MymoduleCar = function(){};
MymoduleCarprototypegetWheels = function(){};一个模块的定义
模块是一种通用的功能片段,它并没有创建新的全局变量或命名空间,相反,所有的代码都存放于一个单函数中,可以用一个名称来表示这个模块,同样这个模块可以依赖其他模块。
function CoolModule(){
var something = 'cool';
var another = [1,2,3];
function doSomething(){
consolelog( something);
}
function doAnother(){
consolelog(anotherjoin('!'));
}
return {
doSomething: doSomething,
doAnother: doAnother
};
}
var foo = CoolModule();
foodoSomething(); //cool
foodoAnother(); //1!2!3这里的CoolModule
就是一个模块,不过它只是一个函数,这里调用CoolModule函数来创建一个模块的实例foo,此时就形成了闭包(因为CoolModule返回一个对象,其中的一个属性引用了内部函数),模块CoolModule返回的对象就是该模块的公共API(也可以直接返回一个内部函数)
所以,模块模式需要具备两个必要条件:
必须有外部的封闭函数,且该函数必须至少被调用一次(每次调用都会创建一个新的模块实例),如CoolModule
封闭函数必须至少有一个内部函数被返回,这样内部函数才能在私有作用域中形成闭包,并且可以访问或修改私有的状态
单例模块模式的实现:
var foo = ( function CoolModule(){
//代码同上例
})();
foodoSomething();
foodoAnother();还可以通过在模块内部保留对公共API对象的内部引用,这样就可以在内部对模块实例进行修改,包括添加、删除方法和属性
function CoolModule(){
var something = 'cool';
var another = [1,2,3];
function change() {
pubicAPIdoSomething = doAnother;
}
function doSomething(){
consolelog( something);
}
function doAnother(){
consolelog(anotherjoin('!'));
}
var pubicAPI = {
change: change,
doSomething: doSomething
};
return pubicAPI;
}
var foo = CoolModule();
foodoSomething(); //cool
foochange();
foodoSomething(); //1!2!3
var foo1 = CoolModule();
foo1doSomething(); //cool现代的模块机制
命名空间是简单的通过在全局变量中添加属性来表示的功能性分组。
将不同功能按照命名空间进行分组,可以让你的单全局变量变得井然有序,同时可以让团队成员能够知晓新功能应该在哪个部分中定义,或者去哪个部分查找已有功能。
例如:定义一个全局变量Y,YDOM下的所有方法都是和操作DOM相关的,YEvent下的所有方法都是和事件相关的。
常见的用法是为每一个单独的JS文件创建一个新的全局变量来声明自己的命名空间;
每个文件都需要给一个命名空间挂载功能;这时就需要首先保证该命名空间是已经存在的,可以在单全局变量中定义一个方法来处理该任务:该方法在创建新的命名空间时不会对已有的命名空间造成破坏,使用命名空间时也不需要再去判断它是否存在。
var MyGolbal = {
namespace: function (ns) {
var parts = nssplit(''),
obj = this,
i, len = partslength;
for(i=0;i<len;i++){
if(!obj[parts[i]]){
obj[parts[i]] = {}
}
obj = obj[parts[i]];
}
return obj;
}
};
MyGolbalnamespace('Book'); //创建Book
MyGolbalBook; //读取
MyGolbalnamespace('Car')prototypegetWheel = function(){}大多数模块依赖加载器或管理器,本质上都是将这种模块定义封装进一个友好的API
var MyModules = (function Manager() {
var modules = {};
function define(name, deps, impl) {
for(var i=0; i<depslength; i++){
deps[i] = modules[deps[i]];
}
modules[name] = implapply(impl,deps);
}
function get(name) {
return modules[name];
}
return {
define: define,
get: get
};
})();以上代码的核心是modules[name] =
implapply(impl,deps);,为了模块的定义引入了包装函数(可以传入任何依赖),并且将模块的API存储在一个根据名字来管理的模块列表modules对象中;
使用模块管理器MyModules来管理模块:
MyModulesdefine('bar',[],function () {
function hello(who) {
return 'let me introduce: '+who;
}
return{
hello: hello
};
});
MyModulesdefine('foo',['bar'],function (bar) {
var hungry = 'hippo';
function awesome() {
consolelog(barhello(hungry)toUpperCase());
}
return {
awesome: awesome
};
});
var foo = MyModulesget('foo');
fooawesome();//LET ME INTRODUCE: HIPPO异步模块定义(AMD):
define('my-books', ['dependency1','dependency2'],
function (dependency1, dependency2) {
var Books = {};
Booksauthor = {author: 'Mrzakas'};
return Books; //返回公共接口API
}
);通过调用全局函数define(),并给它传入模块名字、依赖列表、一个工厂方法,依赖列表加载完成后执行这个工厂方法。AMD模块模式中,每一个依赖都会对应到独立的参数传入到工厂方法里,即每个被命名的依赖最后都会创建一个对象被传入到工厂方法内。模块可以是匿名的(即可以省略第一个参数),因为模块加载器可以根据JavaScript文件名来当做模块名字。要使用AMD模块,需要通过使用与AMD模块兼容的模块加载器,如RequireJS、Dojo来加载AMD模块
requre(['my-books'] , function(books){
booksauthor;
}
)以上所说的模块都是是基于函数的模块,它并不是一个能被稳定识别的模式(编译器无法识别),它们的API语义只是在运行时才会被考虑进来。因此可以在运行时修改一个模块的API
未来的模块机制
ES6为模块增加了一级语法支持,每个模块都可以导入其它模块或模块的特定API成员,同样也可以导出自己的API成员;ES6的模块没有‘行内’格式,必须被定义在独立的文件中(一个文件一个模块)ES6的模块API更加稳定,由于编译器可以识别,在编译时就检查对导入的API成员的引用是否真实存在。若不存在,则编译器会在运行时就抛出‘早期’错误,而不会像往常一样在运行期采用动态的解决方案;
barjs
function hello(who) {
return 'let me introduce: '+who;
}
export hello; //导出API: hellofoojs
//导入bar模块的hello()
import hello from 'bar';
var hungry = 'hippo';
function awesome() {
consolelog(hello(hungry)toUpperCase());
}
export awesome;//导出API: awesomebazjs
//完整导入foo和bar模块
module foo from 'foo';
module bar from 'bar';
fooawesome();import可以将一个模块中的一个或多个API导入到当前作用域中,并分别绑定在一个变量上;
module会将整个模块的API导入并绑定到一个变量上;
export会将当前模块的一个标识符(变量、函数)导出为公共API;
模块文件中的内容会被当做好像包含在作用域闭包中一样来处理,就和函数闭包模块一样;
本篇文章是对在JS中Map和List的简单实现代码进行了详细的分析介绍 需要的朋友参考下 复制代码 代码如下: / MAP对象 实现MAP功能 接口 size() 获取MAP元素个数 isEmpty() 判断MAP是否为空 clear() 删除MAP所有元素 put(key value) 向MAP中增加元素(key value) remove(key) 删除指定KEY的元素 成功返回True 失败返回False get(key) 获取指定KEY的元素值VALUE 失败返回NULL element(index) 获取指定索引的元素(使用element key element value获取KEY和VALUE) 失败返回NULL containsKey(key) 判断MAP中是否含有指定KEY的元素 containsValue(value) 判断MAP中是否含有指定VALUE的元素 values() 获取MAP中所有VALUE的数组(ARRAY) keys() 获取MAP中所有KEY的数组(ARRAY) 例子 var map = new Map(); map put("key" "value"); var val = map get("key") …… / function Map() { this elements = new Array(); //获取MAP元素个数 this size = function() { return this elements length; }; //判断MAP是否为空 this isEmpty = function() { return (this elements length < ); }; //删除MAP所有元素 this clear = function() { this elements = new Array(); }; //向MAP中增加元素(key value) this put = function(_key _value) { this elements push( { key : _key value : _value }); }; //删除指定KEY的元素 成功返回True 失败返回False this remove = function(_key) { var bln = false; try { for (i = ; i < this elements length; i++) { if (this elements[i] key == _key) { this elements splice(i ); return true; } } } catch (e) { bln = false; } return bln; }; //获取指定KEY的元素值VALUE 失败返回NULL this get = function(_key) { try { for (i = ; i < this elements length; i++) { if (this elements[i] key == _key) { return this elements[i] value; } } } catch (e) { return null; } }; //获取指定索引的元素(使用element key element value获取KEY和VALUE) 失败返回NULL this element = function(_index) { if (_index < || _index >= this elements length) { return null; } return this elements[_index]; }; //判断MAP中是否含有指定KEY的元素 this containsKey = function(_key) { var bln = false; try { for (i = ; i < this elements length; i++) { if (this elements[i] key == _key) { bln = true; } } } catch (e) { bln = false; } return bln; }; //判断MAP中是否含有指定VALUE的元素 this containsValue = function(_value) { var bln = false; try { for (i = ; i < this elements length; i++) { if (this elements[i] value == _value) { bln = true; } } } catch (e) { bln = false; } return bln; }; //获取MAP中所有VALUE的数组(ARRAY) this values = function() { var arr = new Array(); for (i = ; i < this elements length; i++) { arr push(this elements[i] value); } return arr; }; //获取MAP中所有KEY的数组(ARRAY) this keys = function() { var arr = new Array(); for (i = ; i < this elements length; i++) { arr push(this elements[i] key); } return arr; }; } 复制代码 代码如下: / js实现list / function List() { this value = []; / 添加 / this add = function(obj) { return this value push(obj); }; / 大小 / this size = function() { return this value length; }; / 返回指定索引的值 / this get = function(index) { return this value[index]; }; / 删除指定索引的值 / this remove = function(index) { this value splice(index ); return this value; }; / 删除全部值 / this removeAll = function() { return this value = []; }; / 是否包含某个对象 / this constains = function(obj) { for ( var i in this value) { if (obj == this value[i]) { return true; } else { continue; } } return false; }; / 是否包含某个对象 / this getAll = function() { var allInfos = ; for ( var i in this value) { if(i != (value length )){ allInfos += this value[i]+" "; }else{ allInfos += this value[i]; } } alert(allInfos); return allInfos += this value[i]+" ";; }; } lishixinzhi/Article/program/Java/JSP/201311/20400
/
加法函数,用来得到精确的加法结果
说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
调用:accAdd(arg1,arg2)
返回值:arg1加上arg2的精确结果
/function accAdd(arg1, arg2) { var r1, r2, m, c; try {
r1 = arg1toString()split("")[1]length;
} catch (e) {
r1 = 0;
} try {
r2 = arg2toString()split("")[1]length;
} catch (e) {
r2 = 0;
}
c = Mathabs(r1 - r2);
m = Mathpow(10, Mathmax(r1, r2));
if (c > 0) { var cm = Mathpow(10, c); if (r1 > r2) {
arg1 = Number(arg1toString()replace("", ""));
arg2 = Number(arg2toString()replace("", "")) cm;
} else {
arg1 = Number(arg1toString()replace("", "")) cm;
arg2 = Number(arg2toString()replace("", ""));
}
} else {
arg1 = Number(arg1toString()replace("", ""));
arg2 = Number(arg2toString()replace("", ""));
} return (arg1 + arg2) / m;
}//给Number类型增加一个add方法,调用起来更加方便。
Numberprototypeadd = function
(arg) { return accAdd(arg, this);
};
扩展资料
var a = 1,
var b = 2,
var c = a + b
这样c得出来的解果是12,
使用Number()函数可以解决这个问题,如下
var c = Number(a) + Number(b)
这样c得出来的解果是3,
JavaScript Number() 函数对象的值转换为数字。
<script type="text/javascript">
var test1= new Boolean(true);
var test2= new Boolean(false);
var test3= new Date();
var test4= new String("999");
var test5= new String("999 888");
documentwrite(Number(test1)+ "<br />");
documentwrite(Number(test2)+ "<br />");
documentwrite(Number(test3)+ "<br />");
documentwrite(Number(test4)+ "<br />");
documentwrite(Number(test5)+ "<br />");</script>
这篇文章主要介绍了JS实现利用两个队列表示一个栈的方法,简单分析了使用两个队列表示一个栈的原理,并结合具体实例分析了javascript相关操作技巧,需要的朋友可以参考下
本文实例讲述了JS实现利用两个队列表示一个栈的方法。分享给大家供大家参考,具体如下:
先看原理图:
理清楚思路,再动笔写:
<!DOCTYPE html>
<html>
<head>
<title>2 Queue</title>
<meta charset="utf-8"/>
<script type="text/javascript">
var arr1 = [];
var arr2 = [];
function Queue(arr){
thispush = function(element){
return arrpush(element);
}
thispop = function(){
return arrshift();
}
thissize = function(){
return arrlength;
}
thisdisplay = function(){
consolelog(arr);
}
}
var queue1 = new Queue(arr1);
queue1push(1);
queue1push(4);
queue1push(5);
queue1push(7);
queue1display();
var queue2 = new Queue(arr2);
//利用两个队列实现栈。放在数组中打印
var res = [], k = 0;
while(queue1size()!=0){
var len = queue1size();
for(var i = 0; i<len-1; i++){
queue2push(queue1pop());
}
// 打印queue1最后一个元素,并出队
res[k] = queue1pop();
++k;
// 队列2的元素放置到队列1中
for(var i = 0; i<len-1; i++){
queue1push(queue2pop());
}
}
consolelog("res:" + res);
//利用两个队列实现栈。单个弹出
while(queue1size()!=0){
var len = queue1size();
for(var i = 0; i<len-1; i++){
queue2push(queue1pop());
}
// 打印queue1最后一个元素,并出队
consolelog(queue1pop());
// 队列2的元素放置到队列1中
for(var i = 0; i<len-1; i++){
queue1push(queue2pop());
}
}
</script>
</head>
<body>
</body>
</html>运行结果:
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
使用async-validator如何编写Form组件(详细教程)
使用微信小程序如何实现上传功能
使用vue如何实现CSS过渡效果
在js中如何实现上传并压缩功能(详细教程)
下面我就为大家分享一篇js实现HTML中Select二级联动的实例,具有很好的参考价值,希望对大家有所帮助。
效果图
选择后
js代码
<script language="javascript" type="text/javascript">
//定义 费用科目 数据数组
fylxArray = new Array();
fylxArray[0] = new Array("","");
fylxArray[1] = new Array("汽车费用","汽油费|过路费|修理费");
fylxArray[2] = new Array("房屋租赁费","分公司及办事处房租|宿舍房租|项目房租");
fylxArray[3] = new Array("差旅费用","餐费|住宿费|交通费");
fylxArray[4] = new Array("招待费","招待费");
fylxArray[5] = new Array("办公费","办公用品费|办公费");
fylxArray[6] = new Array("交通费","交通费");
fylxArray[7] = new Array("物业费","物业费");
fylxArray[8] = new Array("租车费","租车费");
fylxArray[9] = new Array("劳务费","劳务费");
fylxArray[10] = new Array("通讯费","通讯费");
fylxArray[11] = new Array("水费","水费");
fylxArray[12] = new Array("电费","电费|职工福利费");
fylxArray[13] = new Array("会议费","会议费");
fylxArray[14] = new Array("中介服务费","审计费|律师费|券商费|其他");
fylxArray[15] = new Array("快递费","快递费");
fylxArray[16] = new Array("招聘费","招聘费");
fylxArray[17] = new Array("加班餐费","加班餐费");
fylxArray[18] = new Array("投标费用","投标报名费|购买标书费");
fylxArray[19] = new Array("打印装订费","打印费|装订费|文件制作费");
fylxArray[20] = new Array("广告宣传费","展位费|广告费|设计费|印刷费");
fylxArray[21] = new Array("中标服务费","中标服务费");
fylxArray[22] = new Array("专家咨询费","专家咨询费");
fylxArray[23] = new Array("培训费","培训费");
fylxArray[24] = new Array("打印费","打印费");
fylxArray[25] = new Array("职工福利费","职工福利费");
fylxArray[26] = new Array("暖气费","暖气费");
fylxArray[27] = new Array("燃气费","燃气费");
fylxArray[28] = new Array("产检费","产检费");
fylxArray[29] = new Array("生育住院费","生育住院费");
fylxArray[30] = new Array("生育津贴","生育津贴");
fylxArray[31] = new Array("医疗保险费","医疗保险费");
fylxArray[32] = new Array("其他","其他");
//select 二级联动
function getChild(currFylx){
//当前 所选择 的费用类型
var currFylx_value = currFylxoptions[currFylxselectedIndex]value;
var currFylxid=currFylxidsubstr(0,6)
//清空 费用科目 下拉选单
//var currOption= documentgetElementById(currFylxid+'_fykm')
var currOption= $(currFylx)parent()next()children()[0]
currOptionlength=0
for (var i = 0 ;i <fylxArraylength;i++){
//得到 当前费用类型 在 费用科目数组中的位置
if(fylxArray[i][0]==currFylx_value){
//得到 当前费用类型 下的费用科目
var tmpfykmArray = fylxArray[i][1]split("|")
for(var j=0;j<tmpfykmArraylength;j++){
//填充 费用科目 下拉选单
currOptionoptions[currOptionlength] = new Option(tmpfykmArray[j],tmpfykmArray[j]);
}
}
}
}
</script>页面代码
<td class="ff"><select style="width:100px" name="select_name" onChange = "getChild(this)">
<option value="">--无--</option>
<option value="汽车费用">汽车费用</option>
<option value="房屋租赁费">房屋租赁费</option>
<option value="差旅费用">差旅费用</option>
<option value="招待费">招待费</option>
<option value="办公费">办公费</option>
<option value="交通费">交通费</option>
<option value="物业费">物业费</option>
<option value="租车费">租车费</option>
<option value="劳务费">劳务费</option>
<option value="通讯费">通讯费</option>
<option value="水费">水费</option>
<option value="电费">电费</option>
<option value="会议费">会议费</option>
<option value="中介服务费">中介服务费</option>
<option value="快递费">快递费</option>
<option value="招聘费">招聘费</option>
<option value="加班餐费">加班餐费</option>
<option value="投标费用">投标费用</option>
<option value="打印装订费">打印装订费</option>
<option value="广告宣传费">广告宣传费</option>
<option value="中标服务费">中标服务费</option>
<option value="专家咨询费">专家咨询费</option>
<option value="培训费">培训费</option>
<option value="打印费">打印费</option>
<option value="职工福利费">职工福利费</option>
<option value="暖气费">暖气费</option>
<option value="燃气费">燃气费</option>
<option value="产检费">产检费</option>
<option value="生育住院费">生育住院费</option>
<option value="生育津贴">生育津贴</option>
<option value="医疗保险费">医疗保险费</option>
<option value="其他">其他</option>
</select></td><!--费用类型-->
<td class="ff"><select style="width:100px" ><option>--无--</option></select></td><!--费用科目-->上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
在JS中如何改变单物体透明度
在JS中如何实现多物体运动(详细教程)
在vue中如何进行config配置(详细教程)
在JS中如何实现通过拖拽改变物体大小
源生JS怎样实现todolist功能
本文2023-10-04 03:20:13发表“资讯”栏目。
本文链接:https://www.lezaizhuan.com/article/169765.html