本例是模仿vue.js中todoMVC的功能,使用jQuery进行开发,第一版的jQuery会显得有些混乱,后续将进行优化。
todoMVC具有添加、修改、删除、更改状态、分类等操作todos的功能。我的开发过程分为了以下几个步骤。
- 将整个应用进行功能拆分
- 分别实现每个子功能
- 合并功能
- 优化
具体实现
- 添加todos
var newtodoVul= $('#newtodo').val();
$("#newtodo").val('');
var tpl_html=$('.todo-li-template').clone(true);
tpl_html.find('.todo-name').text(newtodoVul);
tpl_html.removeClass('hidden');
tpl_html.removeClass('todo-li-template');
tpl_html.attr('data-id', String(id));
$('#list').prepend(tpl_html);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
生成一个tpl_html的模版,然后prepend()反向插入。
- 删除todos
function todosDel(){
$(".destroy").on('click',function(event){
$(this).addClass("btn-click");
setTimeout(function() {
$(event.target).parents('.todo').remove();
delToDos(Number($(event.target).parents('.todo').data('id')));
}, 200);
});
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
这里删除按钮有一个旋转的动画,执行时间是0.2s,所以需要setTimeout()函数来延迟执行删除函数,同时在数组中也将这条todos进行删除。
function delToDos(id){
arr.forEach(function (item,index){
if(item.id == id){
arr.splice(index,1);
}
})
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 更改todos状态
todos事件分为两种状态,一种是正在进行的’todo’,另一种为完成过后的’done’。创建一个数组保存todos的id、状态、和内容。input框回车事件会调用这个todosArrys(),然后传入id和text的值,存入数组当中。i = i + 1;
text = $(event.target).val();
todosArray(i, text);
function todosArray(id,text){
arr.push({
id: id,
status: 'todo',
text:text
});
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
每次状态更改,会获取当前checkbox点击事件的对象,通过对数组进行遍历,获取相同id的状态进行更改。
function todosToDonw(id) {
arr.forEach(function (item) {
if(item.id==id){
item.status='done';
}
});
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
-
todos分状态查看
1.ALL 查看全部列表
2.Active 查看正在进行的列表
3.Completed 查看已完成的列表
Active和Completed的实现方式是使用jQuery方法each()去遍历DOM,判断是否包含line这个Class再对DOM进行显示或隐藏。
function ActiveToDos() {
$("#list li").each(function(index,element){
if($(element).find(".todo-name").hasClass("line")){
$(element).hide();
}else{
$(element).show();
}
})
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 每个todos修改功能
想要实现修改功能就需要在每个label标签的上层覆盖一个input标签,当双击label标签时,显示input标签,将label标签的text值传入input的val(),然后回车事件绑定alterTod0()函数,为input再添加hidden样式,同时将修改过后的val()再写回label的text。
function editToDos() {
$("#list").dblclick(function (event) {
if ($(event.target).hasClass('todo-name')) {
var $newtodos = $(event.target).parents('.todo').find(".newtodos");
var resettodos = $(event.target).text();
$newtodos.removeClass("hidden");
$newtodos.val(resettodos);
$(event.target).siblings(".todo-icon").addClass("hidden");
}
})
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
function alterTodo(event){
if (event.keyCode == "13") {
$(event.target).siblings(".view").find(".todo-icon").removeClass("hidden");
$(event.target).parents(".todo").find(".todo-name").text($(event.target).val());
$(event.target).addClass("hidden");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
-
细节优化
1.为toggle-all(全部选定的那个checkbox按钮),添加旋转逻辑
当所有的子checkbox按钮全选or全不选的时候,toggle-all会自动调整自己的体位..咳咳
function toggleAll(){
$("#list li").each(function(){
if($("#list li").find(".toggle:checked").length==$("#list li").length){
$(".toggle-all").prop("checked",true);
}
if($("#list li").find(".toggle:checked").length===0){
$(".toggle-all").prop("checked",false);
}
})
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
2.无需二次点击Active或Completed按钮,遍历DOM,含有box样式的分类就调用该分类函数。
function isHasAct(){
$(".footbtn li").each(function(){
if($(".footbtn").find(".box").find("a").attr("id")=="act"){
ActiveToDos();
}
})
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- todos记数
function updateTodosCouts(){
var num=0;
arr.forEach(function(item){
if(item.status=='todo'){
num++;
}
})
$("#foot-num").text(num);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
有哪些坑
- 点击了每个toggle子checkbox后,无法用toggle-all进行checked状态修改,后来发现jQuery1.6版本后无法使用attr进行checked状态修改,改用prop()。
- 使用prepend()向DOM中插入内容的时候,会将模版显示在上面,所以将模版放在ul标签以外。
- 执行删除DOM节点之前,如果还有删除动画,那么用setTimeout(function(){../你的执行函数},time)延时执行函数。
经验值
- 学会Chrome设置断点进行调试,进行DOM操作的时候,需要明白函数event.target指代什么、this指代什么,因为JS每个函数又同时是对象,所以是可以像其它对象一样被传递,return可以返回一个函数的值。这样可以定义一个变量去接收函数的值。
-
使用包括JS数组迭代forEach(),jQueryDOM遍历Each(),修改属性attr(),prop(),插入DOM等。
-
下一步将对jQuery进行重构,结合Handlebars.js 模板引擎来开发第二版。
大爷,请赏我点铜板买喵粮自己吃,您的支持将鼓励我继续创作!(支付宝)