Hexo


  • Startseite

  • Archiv

css选择器

Veröffentlicht am 2017-12-21

选择器主要是用来确定html的树形结构中的DOM元素节点。

我们把CSS选择器分开成四部分来介绍:

基本选择器 多元素的组合选择器 属性选择器 伪类选择器

part1:基本选择器

选择器 含义
* 通用元素选择器,匹配任何元素
E 标签选择器,匹配所有使用E标签的元素
.className 类选择器
#ID id选择器

补充:

选择器 含义
.className1.className2 多类选择器(ie6不支持)
  • 例子1:类选择器结合元素选择器
1
p.items {color: red;}   //匹配 p元素并且是其有一个类名叫“items”
  • 例子2:多类选择器
1
.info.items {background:#ccc;}   //选择器只对元素中同时包含了"info"和"items"两个类才能起作用

part2:多元素的组合选择器

选择器 含义
E,F 多元素选择器,同时匹配所有E元素或F元素,E和F之间用逗号分隔
E F 后代元素选择器,匹配所有属于E元素后代的F元素,E和F之间用空格分隔(所有后代元素)
E > F 子元素选择器,匹配所有E元素的子元素F(仅仅是子元素)
E + F 相邻兄弟元素选择器(相同的父元素),匹配所有紧随E元素之后的同级元素F
E ~ F 通用兄弟元素选择器,选择某元素后面的所有兄弟元素(注意是兄弟元素)
  • demo:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <ul>
    <li>1</li>
    <li class="active">2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>
    10
    <p>我是p元素</p>
    </li>
    </ul>
  • 例子:E + F

1
2
3
li + li {background: green;}  //选中2到10

.active + li {background: green;} //选中3
  • 例子:E ~ F
1
.active ~ li {color: red;} //选中3到10,p不会被选中

part3:属性选择器

选择器 含义
E[att] 匹配所有具有att属性的E元素,不考虑它的值。(注意:E在此处可以省略,比如”[cheacked]”。以下同。)
E[att=val] 匹配所有att属性等于”val”的E元素
E[att~=val] 匹配所有att属性具有多个空格分隔的值、其中一个值等于”val”的E元素
E[att^=”val”] 属性att的值以”val”开头的元素
E[att$=”val”] 属性att的值以”val”结尾的元素
E[att*=”val”] 属性att的值包含”val”字符串的元素
E[att I=val] 特定属性选择器,匹配所有att属性具有多个连字号分隔(hyphen-separated)的值、其中一个值以”val”开头的E元素,主要用于lang属性,比如”en”、”en-us”、”en-gb”等等
  • demo

    1
    2
    3
    4
    5
    6
    7
    <div class="demo">
    <a href="" class="" id="one" lang="zh-cn">1</a>
    <a href="http://git.linghit.com:666" class="" target="_blank">2</a>
    <a href="https://www.baidu.com" class="" title="hey man hello">3</a>
    <a href="" class="item4 info" lang="en-zh">4</a>
    <a href="" class="" id="five">5</a>
    </div>
  • 例子1:E[att] (单一属性的使用、多属性进行选择元素)

1
2
3
.demo a[id] {color:red;}  //选中1和5

.demo a[href][target] {color: yellow; } //选中2,同时具备href与target属性
  • 例子2:E[att=val]
1
2
3
.demo a[id="one"] {color:blue;}  // 选中1
/*也可以多个属性并写*/
.demo a[href="https://www.baidu.com/"][title] {color:#00ffc6;} //选中3

ps注意点:属性和属性值必须完全匹配

1
2
3
.demo a[class="item4"]{color: red};  //无法匹配到4
/*正确写法如下*/
.demo a[class="item4 info"]{color: red};
  • 例子3:E[att~=val],属性有多个值(空格隔开)是只需匹配到其中一个即可选中
1
2
//例子2中无法匹配到4,用下面这个就可以
.demo a[class~="item4"]{color: red};
  • 例子4:E[attr^=”value”]、E[att$=”val”]、E[att*=”val”]
1
2
3
4
5
6
7
.demo a[href^="http://"]{background:orange;} //选中2
.demo a[href^="https://"]{background:green;} //选中3

.demo a[href$="666"]{background:pink;} //选中2

/*只要你所选择的属性,其属性值中有这个"value"值都将被选中*/
.demo a[title*="hello"]{background:black;} //选中3
  • 例子5:E[attr|=”value”],这个选择器会选择attr属性值等于value或以value-开头的所有元素
1
.demo a[lang|="zh"]{background:yellow;}  //选中1

比如说你页面中有很多图片,图片文件名都是以”figure-1”,”figure-2”这样的方式来命名的,那么使用这种选择器选中图片就很方便

part4:伪类选择器

选择器 含义
E:lang(c) 匹配lang属性等于c的E元素

(1) 动态伪类

选择器 含义
E:link 匹配所有未被点击的链接
E:visited 匹配所有已被点击的链接
E:active 用于用户点击元素那一下的效果(正发生在点的那一下,松开鼠标左键此动作也就完成了)
E:hover 匹配鼠标悬停其上的E元素
E:focus 匹配获得当前焦点的E元素

(2)UI元素状态伪类(主要用于Form元素)

选择器 含义
E:enabled 匹配表单中激活的元素
E:disabled 匹配表单中禁用的元素
E:checked 匹配表单中被选中的radio(单选框)或checkbox(复选框)元素
E::selection 匹配用户当前选中的元素
  • “type=”text”有enable和disabled两种状态,前者为可写状态后者为不可状态;
  • type =”radio”和”type=”checkbox””有”checked”和”unchecked”两种状态。
1
input[type="text"]:disabled { background:#ddd; }

(3)结构性伪类

选择器 含义
E:first-child 选择某个元素的第一个子元素
E:last-child 选择某个元素的最后一个子元素
E:nth-child() 选择某个元素的一个或多个特定的子元素
E:nth-last-child() 选择某个元素的一个或多个特定的子元素,从这个元素的最后一个子元素开始算
E:nth-of-type() 选择指定的元素
E:nth-last-of-type() 选择指定的元素,从元素的最后一个开始计算
E:first-of-type 选择一个上级元素下的第一个同类子元素
E:last-of-type 选择一个上级元素的最后一个同类子元素
E:only-child 选择的元素是它的父元素的唯一一个了元素
E:only-of-type 选择一个元素是它的上级元素的唯一一个相同类型的子元素
E:empty 选择的元素里面没有任何内容
1
2
3
4
5
6
7
8
9
10
p:nth-child(3) { color:#f00; }
p:nth-child(odd) { color:#f00; } //奇数
p:nth-child(even) { color:#f00; } //偶数
p:nth-child(3n+0) { color:#f00; }
p:nth-child(3n) { color:#f00; }
tr:nth-child(2n+11) { background:#ff0; }
tr:nth-last-child(2) { background:#ff0; }
p:last-child { background:#ff0; }
p:only-child { background:#ff0; }
p:empty { background:#ff0; }

(4)伪元素

选择器 含义
E:first-line 匹配E元素的第一行
E:first-letter 匹配E元素的第一个字母
E:before 在E元素之前插入生成的内容
E:after 在E元素之后插入生成的内容
1
2
3
4
5
6
7
p:first-line { font-weight:bold; color;#600; }

.preamble:first-letter { font-size:1.5em; font-weight:bold; }

.cbb:before { content:""; display:block; height:17px; width:18px; background:url(top.png) no-repeat 0 0; margin:0 0 0 -18px; }

a:link:after { content: " (" attr(href) ") "; }

伪类选择器内容有待继续更进…

video标签使用小总结

Veröffentlicht am 2017-11-21
  • 属性
  • 方法
  • 事件

1. 示例:

1
2
3
<video src="movie.ogg" controls="controls">
您的浏览器不支持 video 标签。
</video>
1
2
3
4
5
<video width="320" height="240" controls>
<source src="movie.mp4" type="video/mp4">
<source src="movie.ogg" type="video/ogg">
您的浏览器不支持 video 标签。
</video>

ps: 标签用于规定字幕文件或其他包含文本的文件,当媒介播放时,这些文件是可见的。不过主流浏览器基本不支持所以不总结。

2. 标签属性

属性 说明
autoplay 视频加载完马上播放
controls 显示控件(用户可操作)
loop 重复播放
muted 视频的音频输出为静音
poster 规定视频正在下载时显示的图像,直到用户点击播放按钮
preload none:不预载, metadata:预载资源信息, auto:
src 视频的URL
height 视频播放器的高度
width 视频播放器的宽度

2.1 video对象属性

1
var Media = document.getElementById("myVideo");
属性 说明 示例 注意
src 设置或返回视频的 src 属性值。 Media.src=src -
currentSrc 获得当前视频的 URL Media.currentSrc (只读)
currentTime 当前播放时间,单位为秒。为其赋值将会使媒体跳到一个新的时间。 Media.currentTime -
duration 返回当前视频的长度 Media.duration (只读)不同的浏览器返回不同的值
buffered 返回 TimeRanges 对象(表示用户的音视频缓冲范围)。 Media.buffered.start(0)/Media.buffered.end(0) 缓冲范围指的是已缓冲音视频的时间范围。如果用户在音视频中跳跃播放,会得到多个缓冲范围
ended 返回视频是否已结束 Media.ended 返回true/false
error 获得视频的错误状态 Media.error.code (只读)1.用户终止 2.网络错误 3.解码错误 4.URL无效
paused 返回视频是否已暂停 Media.paused (只读)返回true/false
seeking 属性返回用户目前是否在音频/视频中寻址。寻址中(Seeking)指的是用户在音频/视频中移动/跳跃到新的位置。 - (只读)返回true/false
volume 设置或返回视频的当前音量 Media.volume/Media.volume=number number必须是介于 0.0 与 1.0 之间的数字。1默认(最高音量)
networkState 返回音频/视频的当前网络状态 Media.networkState 0.此元素未初始化 1.正常但没有使用网络 2.正在下载数据 3.没有找到资源
defaultPlaybackRate 设置或返回音频的默认播放速度 Media.defaultPlaybackRate/Media.defaultPlaybackRate=number 正常速度:1.0;设置该属性仅会改变默认的播放速度,而不是当前的。
playbackRate 设置或返回视频的当前播放速度。 Media.playbackRate/Media.playbackRate=playbackspeed 默认速度1.0
readyState 返回视频的当前就绪状态。 Media.readyState 0-没有关于音频/视频是否就绪的信息;1-关于音频/视频就绪的元数据;2-关于当前播放位置的数据是可用的,但没有足够的数据来播放下一帧/毫秒;3当前及至少下一帧的数据是可用的;4- 可用数据足以开始播放

ps:有些属性支持性不是很好就不总结,例如:defaultMuted

3. 方法

方法 说明 示例
play() 播放 Media.play()
pause() 暂停 Media.pause()
load() 重新加载音频/视频元素(在更改来源或其他设置后对音频/视频元素进行更新) Media.src = “movie.ogg”; Media.load();
canPlayType() 是否能播放某种格式的资源 返回值:”probably” - 最有可能支持;”maybe” - 可能支持;”” - (空字符串)不支持

4. 事件

(总结几个比较常用的事件)

语法举例(其他类似):

1
2
3
4
5
<video onplay="myScript">

video.onplay=function(){myScript};

video.addEventListener("play", myScript);

事件 说明
play 在音频/视频(audio/video)开始播放时触发。
playing 在音频/视频(audio/video)因缓冲而暂停或停止后已就绪时触发。
pause 在音频/视频(audio/video)暂停时触发。
ended 在音频/视频(audio/video)播放完成后触发。
waiting 在视频由于需要缓冲下一帧而停止时触发。
timeupdate 音频/视频(audio/video)的播放位置发生改变时触发。(移动视频播放位置可调用)
error 在音频/视频(audio/video)加载发生错误时触发。

当音频/视频处于加载过程中时,会依次发生以下事件:

事件 说明
loadstart 当加载过程开始时
durationchange 当指定音频/视频的时长数据发生变化时,会发生durationchange 事件。
loadedmetadata 当指定的音频/视频的元数据(时长、尺寸(仅视频)以及文本轨道)已加载时,会发生 loadedmetadata 事件。
loadeddata 当当前帧的数据已加载,但没有足够的数据来播放指定音频/视频的下一帧时,会发生 loadeddata 事件。
progress 当浏览器正在下载指定的音频/视频时,会发生 progress 事件。
canplay 当浏览器能够开始播放指定的音频/视频时
canplaythrough 当浏览器预计能够在不停下来进行缓冲的情况下持续播放指定的音频/视频时,会发生 canplaythrough 事件。

走过路过别错过,批评好评都接受,哈哈哈哈哈哈哈~~

DOM小总结

Veröffentlicht am 2017-11-06

1、基本概念

1.1、DOM

DOM是JavaScript操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个JavaScript对象,从而可以用脚本进行各种操作(比如增删内容)。

浏览器会根据DOM模型,将结构化文档(比如HTML和XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。

1.2、节点

DOM的最小组成单位叫做节点(node)。文档的树形结构(DOM树),就是由各种不同类型的节点组成。每个节点可以看作是文档树的一片叶子。
(==看图 go==)

根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:

  • 整个文档是一个文档节点
  • 每个 HTML 元素是元素节点
  • HTML 元素内的文本是文本节点
  • 每个 HTML 属性是属性节点
  • 注释是注释节点

1.3、DOM节点信息

(1)节点类型(nodeType)、节点名称(nodeName)

nodeType属性返回节点类型的常数值;nodeName返回当前节点的节点名称

类型 nodeType nodeName
Node.ELEMENT_NODE 1 大写的HTML元素名(标签)
Node.TEXT_NODE 3 #text
Node.PROCESSING_INSTRUCTION_NODE 7 一个用于XML文档的 ProcessingInstruction ,例如 <?xml-stylesheet … ?> 声明。
Node.COMMENT_NODE 8 #comment (注释节点)
Node.DOCUMENT_NODE 9 #document(文档节点)
Node.DOCUMENT_TYPE_NODE 10 描述文档类型的 DocumentType 节点。例如 <!DOCTYPE html> 就是用于 HTML5 的。等同于DocumentType.name
Node.DOCUMENT_FRAGMENT_NODE 11 #document-fragment,一个 DocumentFragment 节点(文档的片段)

备注: 另外还有五种节点类型已弃用

参考: https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeType

下表列出了所有类型的节点的nodeName属性的值. (看看就好。。)

接口 nodeName属性值
Attr 等同于 Attr.name 属性的值
CDATASection “#cdata-section”
Comment “#comment”
Document “#document”
DocumentFragment “#document-fragment”
DocumentType 等同于 DocumentType.name 属性的值
Element 等同于 Element.tagName 属性的值
Entity 实体名称
EntityReference 实体引用名称
Notation Notation名称
ProcessingInstruction 等同于 ProcessingInstruction.target 属性的值
text “#text”

栗子:

使用nodeType属性确定一个节点的类型,比较方便。

1
2
3
4
5
document.querySelector('a').nodeType === 1
// true

document.querySelector('a').nodeType === Node.ELEMENT_NODE
// true

ps:querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素。

(2)节点值(nodeValue)

Node.nodeValue属性返回一个字符串,表示当前节点本身的文本值,该属性可读写。

由于只有Text节点、Comment节点、XML文档的CDATA节点有文本值,因此只有这三类节点的nodeValue可以返回结果,其他类型的节点一律返回null。同样的,也只有这三类节点可以设置nodeValue属性的值。对于那些返回null的节点,设置nodeValue属性是无效的。

1.4 、节点关系

  • parentNode 父节点
  • childNodes 子节点
  • firstChild 父节点里的第一个子节点
  • lastChild 父节点里的最后一个子节点
  • nextSibling 与子节点并列的下一个兄弟节点
  • previousSibling 与子节点并列的上一个兄弟节点
1
2
3
4
5
6
7
8
9
<html>
<head>
<title>DOM</title>
</head>
<body>
<h1>我的父节点是谁?</h1>
<p>Hello world!</p>
</body>
</html>

(1)Node.parentNode

parentNode属性返回当前节点的父节点。对于一个节点来说,它的父节点只可能是三种类型:元素(Element )节点、文档(Document )节点、文档碎片(DocumentFragment)节点。

(2)Node.childNodes

childNodes属性返回一个NodeList集合,成员包括当前节点的所有子节点。注意,除了HTML元素节点,该属性返回的还包括Text节点和Comment节点。如果当前节点不包括任何子节点,则返回一个空的NodeList集合。由于NodeList对象是一个动态集合,一旦子节点发生变化,立刻会反映在返回结果之中。

1
var ulElementChildNodes = document.querySelector('ul').childNodes;

ps:

  1. NodeList 对象代表一个有顺序的节点列表。可通过节点列表中的节点索引号来访问列表中的节点(索引号由0开始);也可以用 length 属性来确定指定类名的元素个数。
1
2
//查看文档中有多少个样式 class="example" 的元素
document.getElementsByClassName("example").length;

(3)Node.firstChild,Node.lastChild
firstChild属性返回当前节点的第一个子节点,如果当前节点没有子节点,则返回null(注意,不是undefined)。

1
2
3
4
5
6
7
8
9
10
11
<p id="para-01">
<span>First span</span>
</p>
<p id="para-02"><span>First span</span> </p>

<script type="text/javascript">
console.log(
document.getElementById('para-01').firstChild.nodeName,
document.getElementById('para-02').firstChild.nodeName
) ; //??
</script>

(4)Node.nextSibling

Node.nextSibling属性返回紧跟在当前节点后面的第一个同级节点。如果当前节点后面没有同级节点,则返回null。注意,该属性还包括文本节点和评论节点。因此如果当前节点后面有空格,该属性会返回一个文本节点,内容为空格。

1
2
3
4
5
6
7
8
9
10
11
12
<div id="div-01">Here is div-01</div>
<div id="div-02">Here is div-02</div>

<script type="text/javascript">
var el = document.getElementById('div-01').nextSibling,
i = 1;
while (el) {
console.log(i + '. ' + el.nodeName); //??
el = el.nextSibling;
i++;
}
</script>

下面两个表达式指向同一个节点。

1
2
3
//???
document.childNodes[0].childNodes[1]
document.firstChild.firstChild.nextSibling

(5)Node.previousSibling

previousSibling属性返回当前节点前面的、距离最近的一个同级节点。如果当前节点前面没有同级节点,则返回null。

1
2
3
4
5
6
<div><span id="b1"></span><span id="b2"></span></div>

<script type="text/javascript">
document.getElementById("b1").previousSibling; // null
document.getElementById("b2").previousSibling.id; // "b1"
</script>

2、节点操作 (节点对象的一些方法)

方法是我们可以在节点(HTML 元素)上执行的动作。

列举一些常用的:

2.1、查找元素节点

  • document.getElementById(id) ,返回带有指定 ID 的元素。
  • document.getElementsByName(name),返回带有指定名称的对象的集合。(查询元素的 name 属性)
  • document.getElementsByTagName(tagname),返回带有指定标签名的对象的集合。
  • document.getElementsByClassName(classname),返回文档中所有指定类名的元素集合,作为 NodeList 对象。
  1. getElementsByClassName() 在 Internet Explorer 5,6,7,8 中无效。

栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<p>段落1</p>
<div id="main">
<p>段落2</p>
<p>段落3</p>
</div>
<input type="text" name="myInput">
<div class="color example">classname1</div>
<div class="color">classname2</div>


document.getElementById("main");
document.getElementsByName("myInput");
document.getElementById("main").getElementsByTagName("p");
document.getElementsByClassName("example color");

2.2、创建节点

Node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。

如需向 HTML DOM 添加新元素,必须首先创建该元素(元素节点),然后向一个已存在的元素追加该元素。

栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="div1">
<p id="p1">段落1</p>
<p id="p2">段落2</p>
</div>


<script>
var para=document.createElement("p");
var node=document.createTextNode("段落3");
para.appendChild(node);

var element=document.getElementById("div1");
element.appendChild(para);

//在节点前面插入
document.body.insertBefore(node, element);
</script>

解析:

  • createElement,创建新的

    元素

  • createTextNode,如需向

    元素添加文本,必须首先创建文本节点。

  • appendChild,向

    元素追加这个文本节点

  • 向一个已有的元素追加这个新元素。
  • Node.insertBefore(), 在当前节点的某个子节点之前再插入一个子节点。
  • insertBefore 方法与 appendChild 方法不同:appendChild方法传递一个参数,由依附点来调用,传递要挂载的段落;insertBefore 方法由document.body调用,传递两个参数,要挂在的段落内容 和 挂载的依附点名称,第一个参数为包含要添加内容的段落,第二个参数为依附点,即将第一个参数的段落插在第二个参数对象之前。

2.2.1、DocumentFragment(创建文档碎片节点)

在更新少量节点的时候可以直接向document.body节点中添加,但是当要向document中添加大量数据是,如果直接添加这些新节点,这个过程非常缓慢,因为每添加一个节点都会调用父节点的appendChild()方法,为了解决这个问题,可以创建一个文档碎片,把所有的新节点附加其上,然后把文档碎片一次性添加到document中。

栗子:

创建十个段落,使用常规的方式

1
2
3
4
5
6
7
//调用了十次document.body.appendChild(),每次都要产生一次页面渲染。
for(var i = 0 ; i < 10; i ++) {
var p = document.createElement("p");
var oTxt = document.createTextNode("段落" + i);
p.appendChild(oTxt);
document.body.appendChild(p);
}

创建文档碎片节点

1
2
3
4
5
6
7
8
var oFragment = document.createDocumentFragment();
for( var i = 0 ; i < 10; i ++ ) {
var p = document.createElement("p");
var oTxt = document.createTextNode("段落" + i);
p.appendChild(oTxt);
oFragment.appendChild(p);
}
document.body.appendChild(oFragment);

创建十个段落,使用常规的方式

2.3、删除节点

删除 HTML 元素,您必须首先获得该元素的父元素:

方法:Node.removeChild(),从DOM中删除一个子节点。返回删除的节点。

栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<div id="div1">
<p id="p1">段落1</p>
<p id="p2">段落2</p>
</div>


<script>
//先定位父节点,然后删除其子节点
//如果不是child不是parent的子节点会报错
var parent=document.getElementById("div1");
var child=document.getElementById("p1");
parent.removeChild(child);


//无须定位父节点,通过parentNode属性直接删除自身
var child=document.getElementById("p1");
if (child.parentNode) {
child.parentNode.removeChild(child);
}


// 移除一个元素节点的所有子节点
var element = document.getElementById("div1");
while (element.firstChild) {
element.removeChild(element.firstChild);
}
</script>

2.3、替换

replacedNode = parentNode.replaceChild(newChild, oldChild); ,用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="div1">
<p id="p1">段落1</p>
<p id="p2">段落2</p>
</div>

<script>
// 获得被替换节点和其父节点的引用.
var p1 = document.createTextNode("我就是要换掉段落2");
var p2 = document.getElementById("p2");
var parentDiv = p2.parentNode;

// 用新的p元素p1来替换掉p2
parentDiv.replaceChild(p1, p2);
</script>

2.4、修改

(1)创建 HTML 内容

1
2
3
4
5
<p id="p1">Hello World!</p>

<script>
document.getElementById("p1").innerHTML="New text!";
</script>

(2)改变 HTML 样式

1
document.getElementById("p1").style.color="blue";

2.5、Node.hasChildNodes()

Node.hasChildNodes方法返回一个布尔值,表示当前节点是否有子节点。

1
2
3
4
5
6
//如果foo节点有子节点,就移除第一个子节点。
var foo = document.getElementById("foo");

if (foo.hasChildNodes()) {
foo.removeChild(foo.childNodes[0]);
}

2.6、Node.cloneNode()

Node.cloneNode方法用于克隆一个节点。它接受一个布尔值作为参数,表示是否同时克隆子节点,默认是false,即不克隆子节点。

1
var cloneUL = document.querySelector('ul').cloneNode(true);

The slow crawling road of whiteMouse…

12

John Doe

13 Artikel
© 2019 John Doe
Erstellt mit Hexo
|
Theme — NexT.Muse v5.1.4