todolist的编写过程以及踩坑记录(3)

todolist

Posted by EWL on November 30, 2017

整体框架以及功能

功能 主函数 相关函数
点击详情 listen_task_detail show_task_detail hide_task_detail render_task_detail update_task refresh_task_list

编写过程

按照之前的规则还是将时间监听放在渲染函数的里面,等模板渲染结束之后再进行事件的绑定符合jquery的动态添加的规则。

function render_task_list(){       
        $task_list.html(null);       
        for(var i = 0, len = task_list.length; i < len; i++){              
              $task_list.append(render_task_item(task_list[i], i));          
        }       
        listen_task_delete();
        // 对就是我,要放在这个函数里面
        listen_task_detail();
    }

具体的listen_task_detail函数如下:

function listen_task_detail(){
        $detail_btn = $('.detail-btn');
        $detail_btn.on('click', function(){
            var $this = $(this),
                $item = $this.parents('.task-item'),
                index = $item.data('index');
            // 在点击详情之后使得遮罩层显示出来
            show_task_detail(index);
        });
        $('.task-item').dblclick(function(){
            var index = $(this).data('index');
            show_task_detail(index);
        });

        $task_detail_mask.click(function(){
            hide_task_detail();
        });
        
    }

分解开之后主要的几个部分就是: 点击详情显示详情提示框和遮罩层—双击task-item自身显示详情提示框和遮罩层—点击遮罩层以关闭遮罩层和提示框。

由此涉及到了show_task_detail 和 hide_task_detail,

function show_task_detail(index){
        // 渲染详情部分
        render_task_detail(index);
        $task_detail_mask.show();
        $task_detail.show();
    }    
    function hide_task_detail(){
        $task_detail_mask.hide();
        $task_detail.hide();
    }

显示的部分需要传入当前item的index以确保显示的详情内容正确,而隐藏就相对简单。并且显示函数中涉及到了详情的渲染,即在显示详情之前需要先将详情渲染出来,就要从task_list[index]中获取相应的数据来填充。

function render_task_detail(index){
        // 日常判断
        if(index === undefined || !task_list[index]){
            return;
        }

        var item = task_list[index];
       
        var tpl = 
        
        '<form><span class="close_cross">×</span>'+
        '<div class="content" name="content">'
        +(item.content || '')+'</div>'+
        '<div>'+  
        '<div> <input name="content_input" class="input_content_title" value='+ (item.content || '') 
        +'></div>'+                    
        '<div class="desc">'+
        '<textarea name="desc">'+(item.desc || '')
        +'</textarea>'+
        '</div>'+
        '</div>'+
        '<div class="remind">'+
        '<label title="提醒时间" class="remind_time_label">提醒时间</label> '+               
        '<input type="text" id="remind_date" class="date" value="'+(item.remind_date || '')+'" name="remind_date">'+                
        '</div>'+
        '<div><button type="submit" class="update_btn">更新</button></div>'+
        '</form>'        
        ;

        $task_detail.html(null);
        $task_detail.html(tpl);
        $('#remind_date').datetimepicker();

        // 获得form
        $update_form = $task_detail.find('form');
        $update_form.on('submit', function(e){
            e.preventDefault();
            var data = {}, $this = $(this);
            data.content = $this.find('[name=content_input]').val();
            data.desc = $this.find('[name=desc]').val();
            data.remind_date = $this.find('#remind_date').val();
            if(!$.trim(data.content)){
                warningObj.warningMsg('主题不能为空');
                return;
            }
            update_task(index, data);
            warningObj.warningMsg('更新详情成功');
            hide_task_detail();
        });

        $('.content').dblclick(function(){
            $(this).hide();
            $('.input_content_title').show().focus();
        });

        // 给叉号添加关闭事件,还是由于jquery的动态添加事件
        // 需要在渲染之后进行事件的绑定
        $close_cross = $('.close_cross');
        $close_cross.click(function(){
            hide_task_detail();
        });
    }

这个函数就有点长了,但是不方,往下看。 这个函数涉及到的部分有: 日常的对index的判断—渲染模板(需要提前将容器清空再写入模板,以防混乱,并加入datetimepicker的使用)—添加事件(提交事件 content双击显示输入框 叉号点击关闭事件)

需要注意的点:

  • 提交事件中涉及禁止按钮的默认行为,防止页面纯刷新不更新
  • 取得data数据时需要判断输入内容是否为空
  • 调用update_task来刷新task_list里的内容,之后调用隐藏函数

好的,又提及了update_task函数

function update_task(index, data){
        if(index===undefined || !task_list[index]){
            return;
        }
        task_list[index] = $.extend({}, task_list[index], data);
        refresh_task_list();
    }

日常进行index的判断,看来有必要将它包装成一个函数了 言归正传,此处使用了一个jquery的包装函数extend,他可以将多个对象融合起来,官方文档上是这么说的

The merge performed by $.extend() is not recursive by default; if a property of the first object is itself an object or array, it will be completely overwritten by a property with the same key in the second or subsequent object. The values are not merged. This can be seen in the example below by examining the value of banana. However, by passing true for the first function argument, objects will be recursively merged.

为什么要这么写呢?emmmm,简而言之,放一个{}在前面是为了保证后面两个都能保持他们各自的内容不变,新的内容将被融合写进{}里面,成为一个新的对象返回。

所以我们取得的task_list[index]实际上就是新的一个兼具data和原来task_list[index]对象属性的新对象,且是data的属性覆盖原来task_list[index]的属性。 完成之后,将这个task_list[index]交给refresh_task_list()以此更新localStorage里的task_list内容。迄今为止就完成了所有的更新。

总结

感觉这一节主要的内容就是函数。没啥可说的了。