html + jquery 原生开发ToDo网页
相信做前端的大家都见过这个网页吧
TodoMVC
Vue的入门网页
今天我用原生html实现一下
首先看一下html部分的代码:
<html>
<head>
<meta charset="utf-8">
<title>幸运记事</title>
<link rel="stylesheet" href="./css/app.css">
</head>
<body>
<section id="todoapp" class="todoapp">
<header class="header">
<h1 id="title" onmouseover="todo.method().hover()" >记</br>事</h1>
</header>
<section class="main">
<section class="input">
<input type="checkbox" class="all-checker" onclick="allChecked(this)">
<img class= "input-img" src="./img/arrow_down.svg">
<input id="add-todo" class="new-todo" placeholder="诗和远方..." autofocus="autofocus" autocomplete="off"
onkeyup="todo.method().addItem(event)">
</input>
</section>
<ul id="list" class="todo-items">
</ul>
<section id="listFoot" class="foot">
<span class="todo-count">
待办
<span id = "count">0</span>
</span>
<ul class="filters">
<li id = "do-border" class="filter" onclick="todo.method().doFilter(this)">
<span >全部</span>
</li>
<li class="filter" onclick="todo.method().doFilter(this)">
<span >未完成</span>
</li>
<li class="filter" onclick="todo.method().doFilter(this)">
<span >已完成</span>
</li>
</ul>
<span id = "removeCom" class="rmv-complete" onclick="rmvCompleted()">
移除已完成
</span>
</section>
</section>
<footer class="footer">
</footer>
</section>
</body>
<script src="./js/app.js"></script>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script>
</script>
</html>
比较简单哈!
再看下简单的css吧
ul{
padding: 0;
margin: 0;
}
body{
display: flex;
flex-direction: column;
align-items: center;
}
.todoapp{
display: flex;
flex-direction: column;
width: 60%;
}
.header{
font-size: 3rem;
color: red;
opacity: 0.6;
/* display: flex; */
text-align: center;
width: 100%;
}
.new-todo{
width: 100%;
font-size: 1.5rem;
font-style: italic;
opacity: 0.8;
padding: 1.5rem 1rem 1.5rem 4rem;
border: none;
box-shadow: 2px 2px 5px #333333;
}
.main{
margin: 0 auto;
width: 100%;
display: flex;
flex-direction: column;
border:1px solid #F2F2F2;
box-shadow: 2px 2px 7px #3333339a;
}
.todo-items{
margin: 0;
list-style: none;
display: none;
padding: 0;
}
#count{
color:red;
}
.todo-item{
display: flex;
flex-direction: row;
justify-items: center;
margin: 0;
font-size: 1.4rem;
opacity: 0.8;
padding: 1.3rem 1rem 1.3rem 0.8rem;
font-style: normal;
border-bottom: 1px solid #dddcdcb2;
font-weight: 100;
}
.rmv-complete{
color: #f84747ee;
cursor: pointer;
display: none;
margin-left: 10%;
margin-right: 4%;
}
.li_img{
margin-left: auto;
cursor: pointer;
}
.todo-item:hover{
background-color: #F2F2F2;
font-size: 1.7rem;
}
.foot{
display: none;
flex-direction: row;
width: 100%;
margin: 0;
font-size: 1.2rem;
color: #747171ee;
opacity: 0.8;
padding: 1rem 1rem 1rem 0;
border-bottom: 1px solid #dddcdcb2;
}
.todo-count{
margin-left: 7%;
display: flex;
}
.filters{
display: flex;
list-style: none;
margin-left: auto;
}
.filter{
display: flex;
padding: 0;
display: block;
padding:0 0.5rem;
/* border: 1px solid #ff780ab2; */
border-radius: 5px;
text-align: center;
margin-left: 10px;
cursor: pointer;
}
.complete{
margin-left: auto;
margin-right: 5%;
}
.footer{
width: 100%;
}
.input{
display: flex;
flex-direction: row;
}
.input-img{
position: absolute;
margin-top: 20 ;
margin-left: 15;
}
.input-img:hover{
opacity: 0.8;
}
.check{
position: absolute;
z-index: 2;
width: 30;
height:30;
margin-left: 10;
}
.li-text{
padding-left: 4rem;
}
.all-checker{
z-index: 2;
cursor: pointer;
opacity: 0;
width: 50;
height:50;
position: absolute;
margin-left: 10;
margin-top: 10;
}
最后再看看简单的js
哈哈,开个玩笑
先上代码吧,后面我们来分析一下
(function () {
const todo = {
mounted: function () {
this.method().startBorder();
},
data: {
context: document.getElementById("title"),
},
method: function () {
return {
startBorder: () => {
document.getElementById("do-border").style.border = "1px solid #ff780ab2";
},
/**
* 鼠标滑过标题
*/
hover: () => {
switch (this.data.context.innerText) {
case "记\n事":
this.data.context.innerText = "幸\n运";
break;
case "幸\n运":
this.data.context.innerText = "记\n事";
break;
}
},
/**
* 回车添加
*/
addItem: (event) => {
if (event.keyCode == "13") {
var text = document.getElementById("add-todo").value;
if (text.replace(/\s/g, "").length == 0) { //空字符检测
return;
}
var list = document.getElementById("list");
var foot = document.getElementById("listFoot");
var count = list.getElementsByTagName("li").length;
document.getElementById("count").innerHTML = parseInt(count) + 1;
foot.style.display = "flex";
list.style.display = "block";
addLi(text);
document.getElementById("add-todo").value = "";
}
},
/**
* 筛选器
*/
doFilter: (obj) => {
var children = obj.parentNode.children;
var index = $(obj).index();
for (var i = 0; i != 3; i++) {
if (index == i) {
children[i].style.border = "1px solid #ff780ab2";
} else {
children[i].style.border = "";
}
}
this.method().filterResult(obj);
},
/**
* 筛选显示结果
*/
filterResult: (obj) => {
switch ($(obj).index()) {
case 0:
$("#list li").each(function () {
$(this).show();
})
break;
case 1:
$("#list li").each(function () {
$(this).show();
if ($(this)[0].children[0].checked)
$(this).hide();
})
break;
case 2:
$("#list li").each(function () {
$(this).show();
if (!$(this)[0].children[0].checked)
$(this).hide();
})
break;
}
}
}
}
}
window.todo = todo
window.todo.mounted()
})()
/**
* 创建li元素
* @param {string} text
*/
function addLi(text) {
var ele_li = document.createElement("li");
ele_li.setAttribute("class", "todo-item");
addEle(ele_li, text);
list.appendChild(ele_li);
}
/**
* 全选操作
* @param {checkbox} obj
*/
function allChecked(obj) {
var li_list = document.getElementById("list").getElementsByTagName("li");
if (li_list.length == 0)
return;
if (obj.checked) {
for (var i = 0; i != li_list.length; i++) {
deleteLine(li_list[i].getElementsByTagName("span")[0], 1);
li_list[i].getElementsByTagName("input")[0].checked = true;
document.getElementById("count").innerHTML = 0;
}
} else {
for (var i = 0; i != li_list.length; i++) {
deleteLine(li_list[i].getElementsByTagName("span")[0], -1);
li_list[i].getElementsByTagName("input")[0].checked = false;
document.getElementById("count").innerHTML = i + 1;
}
}
rmvComp();
}
/**
* 增加或删除 删除线
* @param {*} text
*/
function deleteLine(text, num) {
if (num == 1) {
text.style.textDecoration = "line-through";
} else {
text.style.textDecoration = "none";
}
}
/**
* 为li添加子元素
* @param {*} li
* @param {*} text
*/
function addEle(li, text) {
//checkbox
var ele_check = document.createElement("input");
ele_check.setAttribute("class", "check");
ele_check.setAttribute("type", "checkbox");
ele_check.setAttribute("onclick", "isChecked(this)");
//事项内容
var ele_span = document.createElement("span");
ele_span.setAttribute("class", "li-text");
ele_span.setAttribute("ondblclick" ,"updateItem()")
ele_span.setAttribute("id", "li-span")
ele_span.innerHTML = text;
//删除图标
var ele_img = document.createElement("img");
ele_img.setAttribute("class", "li_img");
ele_img.setAttribute("src", "./img/delete.svg");
ele_img.setAttribute("onclick", "deleteItem(this)");
//加入子元素
li.appendChild(ele_check);
li.appendChild(ele_span);
li.appendChild(ele_img);
}
function updateItem(){
}
//为删除按钮添加删除节点功能
function deleteItem(obj) {
var li = obj.parentNode;
var ul = li.parentNode;
//alert($(li).index());
if (!li.getElementsByTagName("input")[0].checked) {
var count = document.getElementById("count").innerHTML;
document.getElementById("count").innerHTML = parseInt(count) - 1;
}
ul.removeChild(li);
rmvComp();
}
function isChecked(obj) {
var count = document.getElementById("count").innerHTML;
if (obj.checked) {
deleteLine(obj.parentNode.getElementsByTagName("span")[0], 1);
document.getElementById("count").innerHTML = parseInt(count) - 1;
} else {
deleteLine(obj.parentNode.getElementsByTagName("span")[0], -1);
document.getElementById("count").innerHTML = parseInt(count) + 1;
}
rmvComp();
}
function rmvComp() {
var needRmv = false;
$("#list li").each(function () {
if ($(this)[0].children[0].checked) {
needRmv = true;
return;
}
})
if (needRmv) {
$("#removeCom").show();
} else {
$("#removeCom").hide();
}
}
function rmvCompleted() {
$("#list li").each(function () {
if ($(this)[0].children[0].checked) {
$(this).remove();
}
})
}
大家可以看到,一开始就是一个function,然后里面是一些变量,方法之类的
看起来是不是很像vue啊
其实大概就是这样,利用js的闭包特性,共享包内属性,还能都储存在内存中
(function(){
...})()
这是立即执行函数的一种写法。
然后定义常量,里面再次定义变量,返回方法的方法