Taohong的博客


  • Home

  • Archives

DataURL与File,Blob,canvas对象之间的互相转换

Posted on 2018-01-30 | In 技术

DataURL与File,Blob,canvas对象之间的互相转换

canvas转换为dataURL

1
2
var dataurl = canvas.toDataURL('image/png');
var dataurl2 = canvas.toDataURL('image/jpeg', 0.8);

File对象、Blob对象转换为dataURL

File对象也是一个Blob对象,二者的处理相同。

1
2
3
4
5
6
7
8
9
10
11
12
function readBlobAsDataURL(blob, callback) {
var a = new FileReader();
a.onload = function(e) {callback(e.target.result);};
a.readAsDataURL(blob);
}
//example:
readBlobAsDataURL(blob, function (dataurl){
console.log(dataurl);
});
readBlobAsDataURL(file, function (dataurl){
console.log(dataurl);
});

dataURL转换为Blob对象

1
2
3
4
5
6
7
8
9
10
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
//test:
var blob = dataURLtoBlob('data:text/plain;base64,YWFhYWFhYQ==');

dataURL图片数据绘制到canvas

先构造Image对象,src为dataURL,图片onload之后绘制到canvas

1
2
3
4
5
var img = new Image();
img.onload = function(){
canvas.drawImage(img);
};
img.src = dataurl;

File,Blob的图片文件数据绘制到canvas
还是先转换成一个url,然后构造Image对象,src为dataURL,图片onload之后绘制到canvas

利用上面的 readBlobAsDataURL 函数,由File,Blob对象得到dataURL格式的url,再参考 dataURL图片数据绘制到canvas

1
2
3
4
5
6
7
readBlobAsDataURL(file, function (dataurl){
var img = new Image();
img.onload = function(){
canvas.drawImage(img);
};
img.src = dataurl;
});

Canvas转换为Blob

1
2
var dataurl = canvas.toDataURL('image/png');
var blob = dataURLtoBlob(dataurl);

Blob转换为File

1
2
3
4
5
6
7
8
9
10
11
12
13
function blobToFile(theBlob, fileName){
//A Blob() is almost a File() - it's just missing the two properties below which we will add
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}

// Usage
var myBlob = new Blob();

//do stuff here to give the blob some data...

var myFile = blobToFile(myBlob, "my-image.png");

可以使用File构造器

1
var file = new File([myBlob], "name");

##dataUrl转换为File
如果想用Ajax传递,不需要使用File,使用Blob即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}

var dataurl = 'data:text/plain;base64,aGVsbG8gd29ybGQ=';
var blob = dataURLtoBlob(dataurl);
var fd = new FormData();
fd.append("file", blob, "hello.txt");
var xhr = new XMLHttpRequest();
xhr.open('POST', '/server.php', true);
xhr.onload = function(){
alert('upload complete');
};
xhr.send(fd);

可以使用fetch将url转化为File
代码很简洁(可在chrome和firefox中使用)

1
2
3
4
5
6
7
8
9
10
//load src and convert to a File instance object
//work for any type of src, not only image src.
//return a promise that resolves with a File instance

function srcToFile(src, fileName, mimeType){
return (fetch(src)
.then(function(res){return res.arrayBuffer();})
.then(function(buf){return new File([buf], fileName, {type:mimeType});})
);
}

例子1:转化为File对象

1
2
3
4
5
6
7
8
srcToFile(
'data:text/plain;base64,aGVsbG8gd29ybGQ=',
'hello.txt',
'text/plain'
)
.then(function(file){
console.log(file);
})

例子2:转化为File对象并发送到服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
srcToFile(
'data:text/plain;base64,aGVsbG8gd29ybGQ=',
'hello.txt',
'text/plain'
)
.then(function(file){
console.log(file);
var fd = new FormData();
fd.append("file", file);
return fetch('/server.php', {method:'POST', body:fd});
})
.then(function(res){
return res.text();
})
.then(console.log)
.catch(console.error)
;

参考:

  1. http://blog.csdn.net/cuixiping/article/details/45932793
  2. https://stackoverflow.com/questions/6850276/how-to-convert-dataurl-to-file-object-in-javascript
  3. https://stackoverflow.com/questions/27159179/how-to-convert-blob-to-file-in-javascript

知识管理:搭建知识管理体系

Posted on 2018-01-18 | In 学习

知识管理:零基础搭建高效知识体系

Alt text
Alt text

如何高效学习

知识管理四象限

Alt text

  • 知道自己知道:保存
  • 知道自己不知道:重点
  • 不知道自己知道:盘点
  • 不知道自己不知道:发现

时间价值四象限

Alt text

  • 时间多价值高:替代
  • 时间多价值低:规避
  • 时间少价值高:最优
  • 时间少价值低:警惕

如何有效地保存知识

知识保存三大问题

  • 误把信息当知识
  • 保存信息无重点
  • 保存之后就忘了

有重点的保存
长回顾

常规式保存

  • 手抄本记笔记:知识点和流程
  • 电脑文件分类:分类三层以内
  • 网络工具收藏:划重点勤剔除

进阶式保存

  • 理解式保存
  • 协同式保存

画思维导图是一种不错的理解式保存方式
思维导图三步

  1. 完整的阅读
  2. 理解式画图
  3. 对照着修正

协同式保存

  • 网络百科
  • 人力资源

理解式保存:累人但出真知识
协同式保存:巧用资源型知识

如何让知识融汇贯通

  • 链接已知:规律
  • 对接生活:转化
  • 提炼要点:接口
  • 结构升华:概念
    找到规律解题公式,链接已知融合新知
    修辞手法转化新知,对接生活找共同点

隐性知识显性化,显性知识结构化

根据知识能否清晰的表述,分为显性知识和隐性知识

  • 分点
    • 分类结构
    • 空间接口
  • 分步
    • 步骤结构
    • 时间结构
  • 分层
    • 层次结构
    • 等级结构
  • 单一概念

显性知识结构化,结构知识概念化

  • 数字法
  • 子母法
  • 比喻法

    如何让知识知行合一

  • 陈述性知识:写和说
  • 程序性知识:画和练

  • 画

    • 动作图
    • 流程图
    • 模拟图
  • 练
    • 察觉需求
    • 明确标准
    • 着手联系
    • 持续反馈
    • 习惯固化

如何科学地知识创新

如何提升个人品牌力

IE针对Ajax请求结果的缓存的解决办法

Posted on 2017-11-08

IE针对Ajax请求结果的缓存的解决办法

本文转载自:https://www.cnblogs.com/artech/archive/2013/01/03/cache-4-ie.html

在默认情况下,IE会针对请求地址缓存Ajax请求的结果。换句话说,在缓存过期之前,针对相同地址发起的多个Ajax请求,只有第一次会真正发送到服务端。在某些情况下,这种默认的缓存机制并不是我们希望的(比如获取实时数据),这篇文章就来简单地讨论这个问题,以及介绍几种解决方案。

通过为URL地址添加后缀的方式解决问题

一般在请求url后添加时间戳

通过JQuery的Ajax设置解决问题

jQuery具有针对这个的Ajax设置,我们只需要按照如下的方式调用$.ajaxSetup方法禁止掉Ajaz的缓存机制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>

<head>
<script type="text/javascript">
$(function() {
$.ajaxSetup({ cache: false });
window.setInterval(function() {
$.ajax({
url: '@Url.Action("GetCurrentTime")',
success: function(result) {
$("ul").append("<li>" + result + "</li>");
}
});
}, 5000);
});
</script>
</head>

</html>

实际上jQuery的这个机制也是通过为请求地址添加不同的查询字符串后缀来实现的

通过定制响应解决问题

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Thu, 03 Jan 2013 12:54:56 GMT
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 4.0
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: text/html; charset=utf-8
Content-Length: 10
Connection: Close

hexo-设置阅读全文

Posted on 2017-11-08

hexo-设置阅读全文

  1. 在文章中使用<!--more-->手动进行截断
    这种方法可以根据文章的内容,自己在合适的位置添加<!--more-->标签,使用灵活,也是Hexo推荐的方法 ,这种方式也可以让 Hexo 中的插件更好的识别。

    1
    2
    3
    4
    5
    6
    7
    8
    ---
    title: Hello World
    ---
    Welcome to [Hexo](https://hexo.io/)! This is your very first post. Check [documentation](https://hexo.io/docs/) for more info. If you get any problems when using Hexo, you can find the answer in [troubleshooting](https://hexo.io/docs/troubleshooting.html) or you can ask me on [GitHub](https://github.com/hexojs/hexo/issues).
    <!--more-->
    ## Quick Start

    ### Create a new post
  2. 在文章中的front-matter中添加description,并提供文章摘录
    这种方式只会在首页列表中显示文章的摘要内容,进入文章详情后不会再显示。

    1
    2
    3
    4
    ---
    title: Hello World
    description: 这是摘要,进入文章详情后不会再显示。
    ---
  3. 自动形成摘要,在主题配置文件中添加
    默认截取的长度为 150 字符,可以根据需要自行设定

    1
    2
    3
    auto_excerpt:
    enable: true
    length: 150

charles本地调试之map功能

Posted on 2017-11-01

charles本地调试之map功能

map功能介绍

map功能,顾名思义就是将某个请求进行重定向,用重定向后的内容来响应请求的内容;
map功能分为map Local和map Remote, 二者区分是:

  • map Local:是将某个网络请求重定向到本地的某个文件
  • map Remote:是将某个网络请求重定向到另一个网络请求

二者除了重定向文件的位置不同之外,其他功能都是一样的。他们都可以对js、css、html以及api接口均可重定向,此外也可以使用通配符来进行简单的批量匹配,达到批量重定向的目的。

实例

这里介绍一下我最常用的功能api重定向

为了mock数据;一般使用map Remote功能来将本地的请求重定向到测试或者线上环境的网络请求。

例子如下:

1
http://127.0.0.1:8080/api/foo/bar ---> http://test.com/api/foo/bar

配置如下
edit map

注意上面map From中的Path配置项使用了*通配符,表示匹配127.0.0.1:8080/api/下的所有文件及子路径,将其重定向到test.com下的/api/路径下

map通配符

map隐射可以使用的模式匹配符有三种:

  • *: 可以匹配0个或者多个字符

  • ?: 可以匹配一个字符

  • [...]: 范围选择符,可以匹配范围中的任意一个字符

map配置实例

假设Map From配置中的各个项为空,表示匹配所有请求,然后Map To项的配置不同,代表不同含义,下表列出一个简单例子

Host配置值 Path配置值 配置产生的结果
charlesproxy.com 匹配所有的请求重定向到charlesproxy.com主机
*.charlesproxy.com 匹配所有的请求重定向到以.charlesproxy.com结尾的主机
charlesproxy.com /charles/ 匹配所有请求只重定向到charlesproxy.com/charles/路径下
charlesproxy.com /charles/* 匹配所有请求只重定向到charlesproxy.com/charles/路径下,包括路径下的文件及其路径的子路径
charlesproxy.com /charles 匹配所有请求只重定向到charlesproxy.com/charles下
charlesproxy.com /index.html 匹配所有请求重定向到charlesproxy.com/index.html
/charles/*.html 匹配所有请求重定向到任意主机下的以.html结尾的文件,该文件存放在主机的/charles/及其子目录下

hexo博客引用本地图片

Posted on 2017-11-01 | In 技术

使用插件

  1. 设置 _config.yml

    1
    post_asset_folder:true
  2. 安装插件

    1
    npm install https://github.com/CodeFalling/hexo-asset-image --save
  3. 引入图片

    1
    ![avatar](图片目录/logo.jpg)

avatar

使用标签

  1. 设置 _config.yml

    1
    post_asset_folder:true
  2. 使用标签

    1
    2
    3
    4
    5
    6
    {% asset_path slug %}
    {% asset_img slug [title] %}
    {% asset_link slug [title] %}

    如:
    {% asset_img avatar.jpg avatar %}

常用npm包

Posted on 2017-10-27 | In 技术

常用npm包

cross-env

介绍:解决跨平台设置NODE_ENV的问题。
这个迷你的包能够提供一个设置环境变量的scripts,让你能够以lunix方式设置环境变量,然后在windows上也能兼容运行。

使用方法:

  • 安装cross-env:npm install cross-env –save-dev
  • 在NODE_ENV=xxxxxxx前面添加cross-env就可以了。
1
2
3
4
5
{
"scripts": {
"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
}
}

DOM事件

Posted on 2017-08-24

DOM事件

DOM事件的级别

DOM0, element.onclick = function(){}
DOM2, element.addEventListener(’click’, ()=>{}, false)
DOM3, element.addEventListener(‘keyup’, ()=>{}, false)

DOM事件流

捕获阶段,目标阶段,冒泡阶段。

描述DOM事件捕获的具体流程

window –> document —>html —> body —> …… —> target

如何获取html标签:
document.body ==> 获取body
document.documentElement ==> 获取html

Event对象的常见应用

event.preventDefault()
event.stopPropagation()
event.stopImmediatePropagation()
event.currentTarget
event.target

target,currentTarget和this三者的区别

target在事件流的目标阶段;
currentTarget在事件流的捕获,目标及冒泡阶段。
只有当事件流处在目标阶段的时候,两个的指向才是一样的, 而当处于捕获和冒泡阶段的时候,target指向被单击的对象而currentTarget指向当前事件活动的对象(注册该事件的对象)(一般为父级)。this指向永远和currentTarget指向一致(只考虑this的普通函数调用)。

自定义事件

1
2
3
4
5
// 创建自定义事件
var eve = new Event('custome');
ev.addEventListener('custome', ()=>{})
// 触发自定义事件
ev.dispatch(eve)

JS(原生)事件委托:为动态创建的节点绑定事件
JS(原生)事件委托:为动态创建的节点绑定事件

页面布局

Posted on 2017-08-24

页面布局

布局方式有哪几种

  1. 文档流布局
  2. 定位布局
  3. flex布局
  4. table布局
  5. 网格布局

水平居中

  1. margin: 0 auto
  2. 将子元素设置为行内元素,然后父元素设置 text-align: center。
  3. 定位布局
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    .container{
    width: 300px;
    height: 200px;
    background: pink;
    position: relative;
    }
    .inner{
    width: 100px;
    height: 50px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -25px;
    margin-left: -50px;
    background: #fff;
    text-align: center;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.container{
width: 300px;
height: 200px;
background: pink;
position: relative;
}
.inner{
width: 100px;
height: 50px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #fff;
text-align: center;
}
  1. flex布局
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    .container{
    width: 250px;
    height: 200px;
    background: pink;
    display: flex;
    justify-content: center;
    padding: 20px;
    }
    .inner{
    background: #fff;
    width: 50px;
    height: 150px;
    margin-left: 10px;
    }

垂直居中

  1. 单行行内元素居中,只需要将子元素的行高等于高度就可以了
  2. table布局
  3. flex布局
    1
    2
    3
    4
    .box {
    display: flex;
    align-items: center;
    }

界面组件之导航菜单

Posted on 2017-08-22 | In 技术

本文转载自:segmentfault
链接:https://segmentfault.com/a/1190000002446160

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>界面组件之导航菜单</title>
<style>
/*纵向菜单*/

.vertical * {
margin: 0;
padding: 0;
}

nav.vertical {
margin: 50px;
width: 150px;
}

.list.vertical ul {
border: 1px solid #6a6b6c;
border-radius: 3px;
padding: 5px 10px 3px;
}

.list.vertical li {
list-style: none;
/*padding: 3px 10px;*/
}
/*2.横向菜单*/

.list.vertical li+li a {
/* 注意这里! */
border-top: 1px solid #6a6b6c;
}

.list.vertical a {
display: block;
/* 这里! */
padding: 3px 10px;
/* 还有这里! */
text-decoration: none;
padding: 3px 10px;
}

.list.vertical a:hover {
color: #069;
}


.list.transverse ul {
overflow: hidden;
/*强制 ul 包围浮动的 li 元素*/
}

.list.transverse li {
float: left;
/*让 li 元素水平排列*/
list-style: none;
}

.list.transverse a {
display: block;
/*让链接变成块级元素*/
padding: 0 16px;
text-decoration: none;
color: #999;
}

.list.transverse li+li a {
border-left: 1px solid #aaa;
}

.list.transverse a:hover {
color: #555;
}
/*下拉菜单*/
/*第1步-实现顶级菜单*/
/* ***************添加视觉样式************ */

.multi_drop_menu {
font: 1em helvetica, arial, sans-serif;
}

.multi_drop_menu a {
/*让链接充满列表项*/
display: block;

/*文本颜色*/
color: #555;

/*背景颜色*/
background-color: #eee;

/*链接的内边距*/
padding: .2em 1em;

/*分隔线宽度*/
border-width: 3px;

/*可以有颜色,也可以透明*/
border-color: transparent;
}
/*显示选择路径*/

.multi_drop_menu li:hover>a {
/*注意这里的选择符,使用了冒泡机制,后面会用到*/
/*悬停时的文本颜色*/
color: #fff;

/*悬停时的背景颜色*/
background-color: #aaa;
}
/* ***************添加功能样式************* */

.multi_drop_menu * {
margin: 0;
padding: 0;
}
/*强制ul包围li*/

.multi_drop_menu ul {
float: left;
}

.multi_drop_menu li {
/*水平排列菜单项*/
float: left;

/*去掉默认的项目符合*/
list-style: none;

/*为子菜单提供定位上下文*/
position: relative;
}

.multi_drop_menu li a {
/*让链接填充列表项*/
display: block;

/*给每个链接添加一个右边框*/
border-right-style: solid;

/*背景只出现在内边距区域后面*/
background-clip: padding-box;

/*去掉链接的下划线*/
text-decoration: none;
}
/*第2步-实现菜单的下拉部分*/
/*二级菜单宽度*/

.multi_drop_menu li ul {
width: 9em;
}

.multi_drop_menu li li a {
/*去掉继承的右边框*/
border-right-style: none;

/*添加上边框*/
border-top-style: solid;
}
/* 添加的功能样式 */

.multi_drop_menu li ul {
/*临时显示二级下拉菜单*/
display: block;
/*相对于父菜单项定位*/
position: absolute;
/*左边与父菜单项对齐*/
left: 0;
/*顶边与父菜单项底边对齐*/
top: 100%;
}

.multi_drop_menu li li {
/*停止浮动,恢复堆叠*/
float: none;
}

.multi_drop_menu li li ul {
/*继续隐藏三级下拉菜单*/
display: none;
}
/*第3步-让下拉菜单响应鼠标事件*/

.multi_drop_menu li ul {
/*隐藏二级下拉菜单*/
display: none;
/*相对于父菜单项定位*/
position: absolute;
/*左边与父菜单项对齐*/
left: 0;
/*顶边与父菜单项底边对齐*/
top: 100%;
}

.multi_drop_menu li:hover>ul {
/*父元素悬停时显示*/
display: block;
}
/*隐藏二级菜单*/

li ul {
display: none;
}
/*显示二级菜单*/

li:hover>ul {
display: block;
}
/*第4步-调整三级菜单的位置*/

.multi_drop_menu li li ul {
/*相对于父菜单定位*/
position: absolute;
/*与父菜单右侧对齐*/
left: 100%;
/*与父菜单项顶边对齐*/
top: 0;
}
/*其它-垂直的三级菜单*/
/*顶级垂直菜单宽度*/

.multi_drop_menu.vertical {
width: 8em;
}

.multi_drop_menu.vertical li a {
border-right-style: none;

border-top-style: solid;
}

.multi_drop_menu.vertical li li a {
border-left-style: solid;
}

.multi_drop_menu.vertical ul,
.multi_drop_menu.vertical li {
/*让顶级菜单垂直显示*/
float: none;
}

.multi_drop_menu.vertical li ul {
/*子菜单左边与上一级菜单右边对齐*/
left: 100%;

/*子菜单顶边与上一级菜单项顶边对齐*/
top: 0;
}

</style>
</head>

<body>
<section>
<h2>1.纵向菜单</h2>
<nav class="list vertical">
<ul>
<li><a href="#">a</a></li>
<li><a href="#">b</a></li>
<li><a href="#">c</a></li>
<li><a href="#">d</a></li>
</ul>
</nav>
</section>
<section>
<h2>2.横向菜单</h2>
<nav class="list transverse">
<ul>
<li><a href="#">a</a></li>
<li><a href="#">b</a></li>
<li><a href="#">c</a></li>
<li><a href="#">d</a></li>
</ul>
</nav>
</section>
<section>
<h2>3.下拉菜单</h2>
<nav class="multi_drop_menu">
<ul>
<!-- 一级开始 -->
<li><a href="#">Power</a></li>
<li><a href="#">Money</a></li>
<li><a href="#">Love</a></li>
<li><a href="#">Fame</a>
<ul>
<!-- 二级开始 -->
<li><a href="#">Sports Star</a></li>
<li><a href="#">Movie Star</a></li>
<li><a href="#">Rock Star</a>
<ul>
<!-- 三级开始 -->
<li><a href="#">Bruce Springsteen</a></li>
<li><a href="#">Bono</a></li>
<li><a href="#">Mick Jagger</a></li>
<li><a href="#">Bob Dylan</a></li>
</ul>
<!-- 三级结束 -->
</li>
</ul>
<!-- 二级结束 -->
</li>
</ul>
<!-- 一级结束 -->
</nav>
</section>
<section style="clear: both;margin-top: 200px;">
<h2>其它-垂直的三级菜单</h2>
<nav class="multi_drop_menu vertical">
<ul>
<!-- 一级开始 -->
<li><a href="#">Power</a></li>
<li><a href="#">Money</a></li>
<li><a href="#">Love</a></li>
<li><a href="#">Fame</a>
<ul>
<!-- 二级开始 -->
<li><a href="#">Sports Star</a></li>
<li><a href="#">Movie Star</a></li>
<li><a href="#">Rock Star</a>
<ul>
<!-- 三级开始 -->
<li><a href="#">Bruce Springsteen</a></li>
<li><a href="#">Bono</a></li>
<li><a href="#">Mick Jagger</a></li>
<li><a href="#">Bob Dylan</a></li>
</ul>
<!-- 三级结束 -->
</li>
</ul>
<!-- 二级结束 -->
</li>
</ul>
<!-- 一级结束 -->
</nav>
</section>
</body>
</html>
1…456…8

Taohong

记录前端技术,学习心得与生活感悟

80 posts
6 categories
65 tags
© 2020 Taohong
Powered by Hexo
|
Theme — NexT.Muse v5.1.4