JavaScript ES5面向对象实现一个todolist

todo-list

前言

最近阅读了JavaScript设计模式的面向对象篇,但是又苦于实践,便想到了写一个简单的todo-list来巩固自己JavaScript面向对象设计的思想。希望对和我一样的小白有帮助。本文代码使用的是ES5,并非ES6。

要求:了解原型链。

遵守

怕文中有人不明白为什么要这么写,所以这里先说一下一些地方为什么要这么写。

来自《编写可维护的JavaScript》

  • 将一些常量和不变的数据,放在配置文件里。
  • CSS和JavaScript分离。
  • 事件处理和业务逻辑单元分离。
// 如:
var config = {
    classShow: 'show',
    classHide: 'hide'
};

开始

布局

首先,先将HTML框架搭好,这里,就没有特别的做美化了。

<div>
    <input type="text" data-input="work">
    <ul data-list="work">
    </ul>
</div>

设计对象

这个地方,倒是花了我一部分事件,不知道到底该如何设计,因为自己之前写过Java,Java里封装类的思想是尽可能单一功能,和组件的思想很像。

而最开始,我就陷入了深深的思考中,因为我想将这个简单的todo-list封装成一个对象,如果按单一功能的思想的话,就得将input封装为一个对象,li封装为一个对象,ul封装为一个对象,显然,这是不可能的。

于是,我转变思想,将它们整个封装一个对象。

对象的属性

对象的属性有:input, ul, list。为了实例化多个对象,将name传入函数里。因此, 代码如下:

var TodoList = function(name) {
    this.list = document.querySelector('[data-list="' + name + '"]');
    this.childs = this.list.querySelectorAll('li');
    this.input = document.querySelector('[data-input="' + name + '"]');
}

事件绑定

仔细思考,其实就是一个增加、删除、查找的操作, 并且为了将事件处理和逻辑处理单元分隔开,所以事件绑定仅仅处理的是绑定事件。因此,代码如下:

var TodoList = function(name) {
    this.list = document.querySelector('[data-list="' + name + '"]');
    this.childs = this.list.querySelectorAll('li');
    this.input = document.querySelector('[data-input="' + name + '"]');

    // 绑定事件
    this.init = function() {
        
        // input按下enter键
        this.input.addEventListener('keyup', function(event) {
            this.handleKeyup(event);
        }.bind(this));

        // 事件委托,点击list
        this.list.addEventListener('click', function(event) {
            this.handleListClick(event);
        }.bind(this));
    
        // input的值改变时
        this.input.addEventListener('input', function(event) {
            this.handleInputChange(event);
        }.bind(this));
    };
};


/**
 *
 * 事件与应用单元分离
 * handleKeyup
 * 
 * {param} object event
 *
 */
TodoList.prototype.handleKeyup = function(event) {
    event.preventDefault();
    event.stopPropagation();
    this.addItem(event.keyCode, event.target);
}

/**
 * 事件和应用单元分离
 * 点击list,事件冒泡阶段处理, 委托事件
 * 
 * {param} object event
 */
TodoList.prototype.handleListClick = function(event) {
    event.preventDefault();
    event.stopPropagation();
    this.removeItem(event.target);
}


/**
 * 事件和应用单元分离
 * input内容改变,则模糊查找, 调用findItem()函数
 * 
 * {param} object event
 */
TodoList.prototype.handleInputChange = function(event) {
    var value = event.target.value;
    event.preventDefault();
    event.stopPropagation();
    this.findItem(value);
}

在上面,你可能不知道为什么要绑定this,你需要了解一下bind函数的用处。

而调用事件对象的两个API是为了阻止事件的默认行为 以及 防止事件对象传播。

业务逻辑单元的操作

对事件绑定结束后,就需要对

事件绑定成功后,就将进行逻辑单元的代码编写。

看下面的代码:

/**
 *
 * 增加一个todo-item
 * 注意,这里要绑定this
 *
 * {param} number event.keyCode
 * {param} object event.target
 *
 */
TodoList.prototype.addItem = function(keyCode, target) {

    if(event.keyCode == 13 && event.target.value.trim().length > 0) {
        this.append();
        this.clearInput();          
        this.childs = this.list.querySelectorAll('li');
    }
}


/**
 * 删除一个todo-item
 *
 * {param} object event.target
 */
TodoList.prototype.removeItem = function(target) {
        
    // 初始化执行的时候,不存在target
    if(target) {
        if(target.nodeName == 'BUTTON') {
            target.parentNode.parentNode.removeChild(target.parentNode);
            this.childs = this.list.querySelectorAll('li');
        }
    }
};

/**
 *
 * 查找输入字符串是否存在
 * 如果不存在,就显示所有的list
 * 如果存在,就显示存在的
 *
 */
TodoList.prototype.findItem = function(value) {

    var find = false;

    // 隐藏所有
    for(var i = 0;i < this.childs.length;i++) {
        this.childs[i].className = config.classHide;
    }

    // 如果存在就显示
    for(var i = 0;i < this.childs.length;i++) {
        var nowEl = this.childs[i];

        if(nowEl.firstChild.innerText.indexOf(value) != -1) {
            nowEl.className = config.classShow;
            find  = true;
        }
    }

    // 如果都没有就全部显示
    if(!find) {
        for(var i = 0;i < this.childs.length;i++) {
            this.childs[i].className = config.classShow;
        }
    }
}


/**
 *
 * 清空输入框
 *
 */
TodoList.prototype.clearInput = function() {
    this.input.value = '';
}


/**
 *
 * 为totolist append一个li标签
 *
 */
TodoList.prototype.append = function() {
    var oLi = document.createElement('li');
    var oBtn = document.createElement('button');
    var oSpan = document.createElement('span');
    oSpan.innerHTML = this.input.value.trim();
    oBtn.innerHTML = 'delete';
    oLi.appendChild(oSpan);
    oLi.appendChild(oBtn);
    this.list.appendChild(oLi);
};

实例化对象

var todo = new TodoList('work');
todo.init();

如果你想要查看这个简单的todo-list所有的代码,请点击这里

参考

  • 《编写可维护的JavaScript》
  • 《JavaScript设计模式》

转载于:https://www.cnblogs.com/yzfdjzwl/p/6690483.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值