(前言:看看就行,仅做记录,不断学习,以求最好)
2021年12月4日
结合之前所学,此次todos功能开发,在css部分引入了bootstrap,在js部分,使用了Ajax+Promise封装,ES6面向对象class类。
借鉴原官网(https://todomvc.com/examples/vue/#/all)的vuejs模板
首先是页面基础样式的实现:
1.大标题todos,放大字体,设置颜色。
2.小标题,文本输入框以及提示字。
3.显示列表,紧跟在输入框之后,由复选框+复选框自定义样式、文本框、span(删除)三个部分组成。并设置选中后的样式,由li标签上的是否有actived控制(bootstrap默认active有样式,所以重新编辑),当选中时表示已完成该事件,字体颜色变淡且贯穿线,自定义复选框显示选中状态。当鼠标移入li标签时(hover),显示删除按钮。
<--这是列表已完成和未完成的样式-->
<li class="list-group-item " id="list_34">
<label class="state">
<input type="checkbox" name="state">
<div><div class="act"></div></div>
</label>
<span class="badge">x</span>
<input type="text" id="contentInput" value="2" disabled="">
</li>
<li class="list-group-item actived" id="list_35">
<label class="state">
<input type="checkbox" name="state">
<div><div class="act"></div></div>
</label>
<span class="badge">x</span>
<input type="text" id="contentInput" value="3" disabled="">
</li>
4.底部操作栏,定义一个div紧跟在列表(ul)其后,内容居中,先设置三个按钮,分别表示显示全部、显示已完成和显示未完成,定义选中后的样式以及鼠标移入的样式。创建一个span标签表示总数量,定位在左侧,创建一个a标签,在有已完成任务时出现。
5.细节样式没有做修改,主要是完成功能。
其次思考页面功能:
准备工作:
static $$(tag) {
// 快捷获取节点对象函数
// 返回节点对象
return document.querySelector(tag);
}
static $$All(tag) {
// 返回节点对象群组
return document.querySelectorAll(tag)
}
// Ajax.request 参数
/*
@param {method,url,data,dataType,success,error} object
method 请求方式
url 请求地址
data 传输参数
dataType 返回值类型
以对象的方式传参,调用Ajax方法
返回promise函数
*/
// Todos 需要的参数
/*
@param {input,radio,ul,allBtn,activeBtn,completedBtn,clearAll,totalText,btnGroup,selectAll} object
input 输入内容框
ul 显示列表
radio 完成按钮
allBtn 显示全部任务按钮
activeBtn 显示已完成按钮
completedBtn 显示未完成按钮
clearAll 清除所有已完成
totalText 显示列表总数
activeClassName 已完成class类名
selectAll 全选按钮
属性值:id或者class
*/
1.新增任务
经测试,输入框采用onkeyup事件,当键码为13(即Enter)时触发(按一次只触发一次)。
此时获取输入框里的value,先判断是否为空,再发送Ajax请求。
成功后清空文本框内容,获取列表标记index的值(保存的是state),再使用刷新列表的函数
Todos.$$(this.input).onkeyup = function(e)
// 用keyup只触发一次
// enter键的键码是13 时才触发请求
if (e.keyCode === 13)
// 获取输入框内容
// 判断内容为空则不触发
Ajax.request({
method: 'get',
url: './lib/index.php',
data: {
fn: 'add',
content // 因为数据库设置,新增状态默认为未完成,也就是0,所以只需要传递内容就行
},
dataType: ''
})
// 成功后要对文本框内容清空
// 刷新当前显示页面
let state = Todos.$$(_this.ul).getAttribute('index');
Todos.show(state, _this.ul, _this.totalText);
// 判断有无内容显示底部操作界面
_this.examineSelectAll();
2.显示内容
获取列表内容并设置,定义三个参数,第一个是state状态,第二个是列表ul,第三个是存放显示总数文字的span。
首先判断参数state的内容,我定义的分别为“all”,1, 0,(all表示全部,1表示已完成,0表示未完成),state默认为all。
打开页面时获取全部内容,并输出,输出同时给ul设置自定义属性index存放state,给li设置选中或未选中的className
static show(state = 'all', ul, totalText)
// state 显示方式:全部('all')、已完成(1)、未完成(0)
// 判断条件是显示所有还是显示部分
if (state === 'all')
// 发送Ajax请求
Ajax.request({
method: 'get', //传输方式
url: './lib/index.php', //地址,要以HTML文件为准的相对地址
data: {
fn: 'getAll', // 调用对应函数
}
})
// 成功后
// 设置总共显示数目
Todos.$$(totalText).innerHTML = `${data[0]} item left`;
// 调用页面创建方法
// 输出内容
odos.$$(ul).innerHTML = Todos.createAllListHtml(data[1]);
// 给显示列表添加id标记此时需要显示什么
Todos.$$(ul).setAttribute('index', `${state}`)
// 这里要注意一定要给当前页面一个标记,这样在添加数据,修改状态和删除等操作时可以直接针对显示的内容进行刷新
Ajax.request({
method: 'get',
url: './lib/index.php',
data: {
fn: 'getState',
state
}
})
//注意,点击All、Active、Completed时,all是全查询,而后两个是条件查询,所以接受到的数值不一样
//成功后操作差不多,注意传参时只有一个data,当然也可以传一个数量
// php
// 获取数据的方法
function getAll(){
$sql1 = 'select count(id) as listAll from jstodos';
$listAll = select($sql1)[0]['listAll'];
$sql = "select * from jstodos order by id asc";
$res = select($sql);
print_r(json_encode([$listAll,$res]));
}
// 获取单个数据的方法
function getState(){
$state = $_GET['state'];
$sql = 'select * from jstodos where state='.$state;
$res = select($sql);
print_r(json_encode($res));
}
这里推荐使用innerHTML,有种无缝的感觉,避免因为每次先清空innerHTML再插入节点对象时造成ul标签闪烁影响观感
3.点击all、avtive、completed切换显示内容
先实现三个显示界面,获取三个按钮分别绑定。
这里要利用排他思想,给当前选中界面的按钮设置被选中样式的class,所以不能单独获取该按钮而是获取按钮组。
这个比较简单,再调用一次 Todos.show()就行了
4.写一个事件委托,在LI标签上
给列表中的复选框绑定事件,使用事件委托机制,因为列表中三个内容分别有功能。
Todos.$$(this.ul).onclick
let target = e.target;
// 点击复选框修改当前状态
if (target.name == 'state')
// 点击删除按钮直接删除
if (target.className == 'badge')
5.复选框修改状态
截止到今天,首先完成了复选框事件,点击复选框,获取到父级的父级的class,也就是到LI标签为止。
用indexOf判断当前内容是已完成还是未完成,如果已完成则有一个actived的css类名,并设置相反的状态。
然后发送Ajax请求,并在成功后用classList删除或新增actived修改样式。
// 首先肯定要获取Li标签的class 用parentNode方法
// 其次获取该行id 、我在前面定义时,id的组成是 list_(id),所以这里要用split('_')先分割成数组,再取第二项
// 在之前我直接用slice(-1)截取最后一位,不行,如果是两位数三位数id,那难不成还要手动去修改吗?
let state;
if (classStr.indexOf(`${this.activeClassName}`) === -1) {
state = 1;
} else {
state = 0;
}
// 我给已完成的li标签添加了一个叫做“actived”的类名,用index去匹配,没有返回-1,那该行就是未完成
Ajax.request({
method: 'get',
url: './lib/index.php',
data: {
fn: 'updateState',
state,
infoId //根据id修改state
},
dataType: ''
})
//成功后,要调用一个函数判断有没有已完成,因为涉及到一个按钮功能。
//其次根据上面的state来添加或删除class
//这里使用classList.add() 和 classList.remove() 不会对其他已存在的clss造成影响
if (state == 1) {
li.classList.add(`${this.activeClassName}`);
} else {
li.classList.remove(`${this.activeClassName}`);
}
//接着刷新当前显示界面
当日总结:
首先显示总列数是不变的,所以只需要在进入页面初始化时设置一次。
其次要分别获取每个状态下的内容,并且要在其他操作时看到改变,所以要给节点对象设置标记
复选框只需要判断li标签的class里面是否有actived来设置状态