❶ 排他性
$("button").click(function() {
$(this).siblings().css("backgroundColor", "");
$(this).css("backgroundColor", "tomato");
})
❷ 隐藏下拉菜单
$(".nav>li").mouseover(function() { // 鼠标经过,ul显示
$(this).children("ul").show();
})
$(".nav>li").mouseout(function() { // 鼠标离开,ul隐藏
$(this).children("ul").hide();
})
// 优化(下拉动画效果)
$(".nav>li").hover(function() {
$(this.children("ul")).stop().slideToggle();
})
❸ tab栏切换(点击)
$("tab-list li").click(function() { // 隐式迭代
$(this).addClass("current").siblings().removeClass("current"); // 链式编程
var index = $(this).index();
$("tab-con li").eq(index).show().siblings().hide();
})
❹ 全选
// 关键思路(分别对应两个功能):
// 1. 当全选内勾选/取消时,所有的小按钮都被勾选/取消
// 2. 当小按钮被勾选/取消时,如何此时被选中的小按钮数===全部的小按钮数,则全选被勾选;否则不选中
// 全选按钮影响小按钮———勾选全选,所有按钮被勾选;取消全选,所有勾选被取消
$(".checkAll").change(function() {
$(".checkOne").prop("checked", $(this).prop("checked"));
})
// 小按钮影响全选按钮———当小按钮全被选中时候,全选按钮自动被勾选;否则,自动取消勾选
$(".checkOne").change(function() {
if ($(".checkOne:checked").length === $(".checkOne").length) { // length可以获得jQuery伪数组的长度
$(".checkAll").prop("checked", true); // :checked写在选择器中,可选出所有被勾选的按钮
} else {
$(".checkAll").prop("checked", false);
}
})
❺ 发布留言板(可删除留言)
<!-- 结构很简单 -->
<textarea name="" id="txt" cols="30" rows="10"></textarea>
<button class="btn">发布</button>
<ul></ul>
$(".btn").on("click", function() { // 点击发布按钮,就将文本域的内容发布到ul的li中
var li = $("<li></li>");
li.html($("#txt").val() + "<a href='javascript:;'>删除</a>");
$("ul").prepend(li);
$("#txt").val("");
})
$("ul").on("click", "a", function() { // 删除li
$(this).parent().remove();
})
// 优化:li出现时的下拉效果(以及删除时的上拉效果)
$(".btn").on("click", function() {
var li = $("<li></li>");
li.html($("#txt").val() + "<a href='javascript:;'>删除</a>");
$("ul").prepend(li);
li.slideDown(); // 在这之前,在css中将li设置为dispaly:none,防止append时直接出现
$("#txt").val("");
})
$("ul").on("click", "a", function() {
$(this).parent().slideUp(function() { // this指向【实际触发时间的a】而不是【绑定事件的ul】
$(this).remove(); // this指向调用者,这里当然是调用回调函数的li
});
})
/*
* 说几个重要的知识点:
* 1. 绑定删除事件时,采用了on的委托绑定写法;使用on是因为on可以给未来动态增加的新元素绑定事件
* 2. 删除li后的上拉效果,思路是"先上拉,再删除",且删除发生在上拉之后———正好可以使用回调函数
* 3. 注意一下上面标出的this的指向
*/
❻ 回到顶部
$(window).scroll(function() { // 小盒子出现和消失
if ($(document).scrollTop() >= n) {
$(".littleBox").fadeIn();
} else {
$(".littleBox").fadeOut();
}
})
$(".littleBox").on("click", function() { // 回到顶部
$(document).scrollTop(0);
})
$(".littleBox").on("click", function() { // 回到顶部(优化)
$("body, html").stop().animate({ // 用一个动画回到顶部,而不是直接跳到顶部; 元素才能做动画,千万不要写成了document文档
scrollTop: 0 // 这里的scorllTop是animate的一个属性
})
})
❼ todoList
>>> todoList的实现原理,
>>> 并不是 在每次check后,就把一个li在todoList和doneList移动————这样的话刷新后,数据绝对丢失
>>>
>>> 而是所有数据是一个对象: { title:..., done:...}; 所有数据(对象)组成一个数组
>>> 然后将整个数组转化为json格式,【存储在本地(浏览器中)】。再把这些数据读取为数组,渲染到浏览器上————★ 核心:修改的不是DOM而是本地数据
>>>
>>> 下面封装的三个函数是这个案例的核心,分别是:
1. getData,读取本地数据。并将json转换为数组
2. saveData,存储数据。getData的反操作,将数据转换为json并存入本地
3. ★ load,加载渲染数据。根据数据数组的done属性,分别渲染到todoList和doneList之中
>>>
>>>
>>> 下面,尝试不要从【DOM】而是从【本地数据+渲染】的思路去理解todoList的功能:
1. 回车添加新的待办事项: 从本地读取数据(一个数组),更新(追加)数据,存回去。渲染。
2. 删除事项: 本地读取数据(一个数组),删除对应元素(对象),存回去。渲染。
3. ★ todoList和doneList事项的转移 :读取数据(一个数组),更改对应元素(对象)的done属性。渲染。
<header>
<section class="w">
<label for="title">TodoList</label>
<!-- 输入框 -->
<input type="text" id="title" name="title" placeholder="添加ToDo" required="required" autocomplete="off">
</section>
</header>
<section class="w">
<h2>正在进行<span id="todoCount"></span></h2>
<ul class="todoList">
<!-- <li> 【li的示例】
<input type="checkbox">
<p>萝莉赛高</p>
<a href="#">删除</a>
</li> -->
</ul>
<h2>已经完成<span id="doneCount"></span></h2>
<ul class="doneList">
<li></li>
</ul>
</section>
// var todoList = [{title: '萝莉', done: false}, {title: '萝莉',done: false}] // 数组形式的数据【示例】
load(); // 打开页面就渲染一次
$("#title").on("keydown", function(e) { // 1. 思路:拿来本地原先的数据,追加后再存回去
if (e.keyCode === 13 && $(this).val() !== "") {
var local = getData();
local.push({
title: $(this).val(),
done: false
});
saveData(local);
load();
$(this).val("");
}
})
$("ul").on("click", "a", function() { // 2. 删除de思路:读取数据,删除数据,重新保存,渲染
var data = getData();
var index = $(this).attr("id");
data.splice(index, 1);
saveData(data);
load();
})
$(".todoList, .doneList").on("click", "input", function() { // 3. 切换done属性
var data = getData();
var index = $(this).siblings("a").attr("id");
data[index].done = $(this).prop("checked");
saveData(data);
load();
})
// 下面封装的三个函数是这个案例的核心,分别是:
// 1. getData,读取本地数据。并将json转换为数组
// 2. saveData,存储数据。getData的反操作,将数据转换为json并存入本地
// 3. load,加载渲染数据。根据数据数组的done属性,分别显示到todoList和doneList之中
function getData() { // 读取本地存储的数据
var data = localStorage.getItem("todoList");
if (data !== null) {
return JSON.parse(data); // 解析为存入时的数组格式(对象)
} else {
return []; // 返回一个空的数组对象
}
}
function saveData(data) { // 保存本地存储的数据
localStorage.setItem("todoList", JSON.stringify(data));
}
function load() { // 渲染数据
var data = getData();
$(".todoList, .doneList").empty();
// 计数
var todoCount = 0;
var doneCount = 0;
$.each(data, function(key, value) { // 每次渲染,都是删掉之前的li,遍历一次重新生成
if (value.done) {
$(".doneList").prepend("<li><input type='checkbox' checked='checked'><p>" + value.title + "</p><a href='#' id=" + key + ">删除</a></li>");
doneCount++;
} else {
$(".todoList").prepend("<li><input type='checkbox'><p>" + value.title + "</p><a href='#' id=" + key + ">删除</a></li>");
//id是给每条数据标识一下,点击a的时候可以对用这条数据(数组)(因为index方法没法对应到a上,因为a被li包裹,a之间不再是亲兄弟的关系)
todoCount++;
}
})
$("#todoCount").html(todoCount);
$("#doneCount").html(doneCount);
}
☀ Loli & JS
♫ Suki