写网页如搭积木:光会摆弄现成的还不够,得学会自己造积木、插积木、拆积木。 这一式,我们修炼节点的增删改——让页面像活水一样流动。
- 用
$('<li>')凭空造出元素,并用text/attr妆点它 - 掌握
append/prepend/after/before四个安放方位 - 分清
remove()与empty(),知道detach()留了一手 - 用
clone(true)连事件一起复制 - 会用
wrap/wrapAll/wrapInner/unwrap包装与拆包,replaceWith整段替换
凭空造一个节点
写页面时,很多节点是“后来才出生”的:新一条待办、新一张卡片。造节点的方法很轻巧——
把尖括号写进 $() 里。注意与找元素的选择器区别:$('li') 是“找现成的 li”,
$('<li>') 是“新造一个 li”。
第 2 步里全是熟面孔:text()、addClass()、attr() 都能链式连写。
appendTo 是 append 的反向写法——一个说“容器装元素”,一个说“元素进容器”,挑顺手的用。
放进去:append / prepend / after / before
安放方位一共四个,分清“子级”与“同级”就不乱:
append() / prepend() 以父元素为主语,插进子级的末尾 / 开头;
after() / before() 以元素自身为主语,插到同级的后面 / 前面。
我是本体:append / prepend 的徽章进框内,after / before 的徽章在框外。
每个徽章都是现场 $('<span>') 造出来的,再按四个方位安放。
框内框外的差别,就是“子级”与“同级”的差别。
拿掉:remove / empty / detach
有增就有删,三种删法各管一摊:
| 方法 | 效果 |
|---|---|
$el.remove() | 删掉元素自身与全部子孙,连同绑定的事件与数据一起清除 |
$el.empty() | 只清空里面的内容,元素自身这个“壳”还在 |
$el.detach() | 同 remove,但保留事件与数据——日后还能原样插回来 |
日常口诀:“清空列表用 empty,连根拔起用 remove,
暂时离场还想回来用 detach。”
合起来练:列表的增与删
把“造、放、删”串成一个小工具:输入任务、点击添加,列表末尾多一项;点“删除”按钮,那一项离场。 删除按钮是后来才出生的,所以用上一式学过的事件委托——把事件绑在列表身上。
- 每日一页 HTML
拆解两个关键:$(this).closest('li') 从删除按钮向上找到它所在的那一项再 remove();
事件绑在 #jq08-list 上、用选择器 '.jq08-del' 过滤——
于是以后每一条新加的任务都自带删除功能,不用再绑一遍。
复制:clone() 与 clone(true)
clone() 把元素连结构一起复印一份;但它不复印事件——
事件是登记在“原来那个元素”身上的。想让复制品也有灵魂,用 clone(true),
连事件与数据一起带走。
复制后点击各卡片:只有原版和 clone(true) 复制品会“已阅”变红。
修行卡
点我:已阅。
例 2 的删除按钮用的是事件委托(事件在父级 ul 身上),
新元素天生可响应,无需 clone(true);例 3 的事件直接绑在卡片自己身上,
复制时就必须 clone(true) 才能带走。两条路都通,知道自己在哪条路上就行。
包与换:wrap / replaceWith 与反向插入
节点操作还有两路细活:一路是“包装”——给现成的内容加一层外衣; 一路是“替换”——把旧节点整段换掉。它们各有几个方法,配对很好记:
| 方法 | 做什么 |
|---|---|
wrap(结构) | 给每一个选中元素各包一层 |
wrapAll(结构) | 把所有选中元素合起来包进同一层 |
wrapInner(结构) | 只把元素内部的内容包起来(外壳保留) |
unwrap() | 拆掉选中元素的父级(跟 wrap 反着来) |
replaceWith(新内容) | 把选中元素整段换成新内容 |
insertAfter(目标) / insertBefore(目标) | 与 after / before 效果相同,只是“主语宾语”互换 |
依次演示不同的包法;点「还原」随时回到最初。
- 给例 2 加两个按钮——“清空
empty()”和“连根拔起remove()”,点完再看列表还在不在。 - 把例 2 的
appendTo换成prependTo,让新任务插到列表顶部;并说明为什么放用户输入要用text()而不是html()。 - 思考题:为什么
clone()复制出来的卡片点不动,clone(true)复制出来的就行?
参考答案 1
empty 之后列表壳子还在,还能继续添加;remove 之后 ul 整个消失,
再点“添加”就没地方放了。所以“清空列表”要用 empty()。
参考答案 2
prependTo 与 prepend 对应,插到开头。安全上:text() 把输入当纯文字;
html() 会把输入当 HTML 解析——用户输入 <script>alert(1)</script>
之类的内容就会被执行,这叫 XSS 攻击。放用户输入,永远用 text()。
参考答案 3
事件是登记在“原来那个元素”身上的:clone() 只复印了 HTML 结构,
没复印 jQuery 记在元素上的事件与数据,所以复制品点不动;clone(true) 才连事件一起带走。
反观例 2 的删除按钮用的是事件委托(事件在父级身上),新元素天然可响应——委托场景下不需要 clone(true)。
本式小结
$('<li>')凭空造节点,text/attr/addClass妆点它;append/prepend插进子级末尾 / 开头,after/before插到同级后 / 前,appendTo等是反向写法;remove()连事件一起删,empty()只清内容,detach()删而留事件;clone(true)连事件一起复制,复制品也有灵魂;wrap各自包、wrapAll合成包、wrapInner包内容、unwrap拆父级;replaceWith换掉整个节点。
下一式,页面不刷新也能取数据——Ajax。