diff --git "a/00-\345\211\215\347\253\257\345\267\245\345\205\267/01-VS Code\347\232\204\344\275\277\347\224\250.md" "b/00-\345\211\215\347\253\257\345\267\245\345\205\267/01-VS Code\347\232\204\344\275\277\347\224\250.md" index e31cb3fb..b8def8b1 100644 --- "a/00-\345\211\215\347\253\257\345\267\245\345\205\267/01-VS Code\347\232\204\344\275\277\347\224\250.md" +++ "b/00-\345\211\215\347\253\257\345\267\245\345\205\267/01-VS Code\347\232\204\344\275\277\347\224\250.md" @@ -1,3 +1,14 @@ +--- +title: 01-VS Code的使用 +publish: true +--- + + + + + + + ## 前言 > 文章标题:《第一次使用 VS Code 时你应该知道的一切配置》。本文的最新内容,更新于 2020-06-19。大家完全不用担心这篇文章会过时,因为随着 VS Code 的版本更新和插件更新,本文也会随之更新。 @@ -612,6 +623,10 @@ VS Code 默认支持 Emmet。更多 Emmet 语法规则,请自行查阅。 我们还可以选择「右键 -> Diff with Remote」,就可以将本地的代码和 ftp 服务器上的代码做对比。 +### 28、设置tab的缩进 + +在配置里搜索`Detect Indentation`,修改为false。参考链接:https://www.yisu.com/zixun/327399.html + ## 七、VS Code 配置云同步 我们可以将配置云同步,这样的话,当我们换个电脑时,即可将配置一键同步到本地,就不需要重新安装插件了,也不需要重新配置软件。 diff --git "a/00-\345\211\215\347\253\257\345\267\245\345\205\267/02-Git\347\232\204\344\275\277\347\224\250.md" "b/00-\345\211\215\347\253\257\345\267\245\345\205\267/02-Git\347\232\204\344\275\277\347\224\250.md" index 840c42f4..7e77a5de 100644 --- "a/00-\345\211\215\347\253\257\345\267\245\345\205\267/02-Git\347\232\204\344\275\277\347\224\250.md" +++ "b/00-\345\211\215\347\253\257\345\267\245\345\205\267/02-Git\347\232\204\344\275\277\347\224\250.md" @@ -1,6 +1,5 @@ --- title: 02-Git的使用 -publish: true --- diff --git "a/01-HTML/01-\350\256\244\350\257\206Web\345\222\214Web\346\240\207\345\207\206.md" "b/01-HTML/01-\350\256\244\350\257\206Web\345\222\214Web\346\240\207\345\207\206.md" index 8412c6ec..b6534784 100644 --- "a/01-HTML/01-\350\256\244\350\257\206Web\345\222\214Web\346\240\207\345\207\206.md" +++ "b/01-HTML/01-\350\256\244\350\257\206Web\345\222\214Web\346\240\207\345\207\206.md" @@ -1,3 +1,10 @@ +--- +title: 01-认识Web和Web标准 +publish: true +--- + + + ## Web、网页、浏览器 diff --git "a/01-HTML/02-\346\265\217\350\247\210\345\231\250\347\232\204\344\273\213\347\273\215.md" "b/01-HTML/02-\346\265\217\350\247\210\345\231\250\347\232\204\344\273\213\347\273\215.md" index ac7eb1b9..e2cb2055 100644 --- "a/01-HTML/02-\346\265\217\350\247\210\345\231\250\347\232\204\344\273\213\347\273\215.md" +++ "b/01-HTML/02-\346\265\217\350\247\210\345\231\250\347\232\204\344\273\213\347\273\215.md" @@ -1,3 +1,10 @@ +--- +title: 02-浏览器的介绍 +publish: true +--- + + + ## 常见的浏览器 diff --git "a/01-HTML/03-\345\210\235\350\257\206HTML.md" "b/01-HTML/03-\345\210\235\350\257\206HTML.md" index 7e193ab5..50471b92 100644 --- "a/01-HTML/03-\345\210\235\350\257\206HTML.md" +++ "b/01-HTML/03-\345\210\235\350\257\206HTML.md" @@ -1,3 +1,9 @@ +--- +title: 03-初识HTML +publish: true +--- + + diff --git "a/01-HTML/04-HTML\346\240\207\347\255\276\357\274\232\346\216\222\347\211\210\346\240\207\347\255\276.md" "b/01-HTML/04-HTML\346\240\207\347\255\276\357\274\232\346\216\222\347\211\210\346\240\207\347\255\276.md" index b8cf0f17..291414e5 100644 --- "a/01-HTML/04-HTML\346\240\207\347\255\276\357\274\232\346\216\222\347\211\210\346\240\207\347\255\276.md" +++ "b/01-HTML/04-HTML\346\240\207\347\255\276\357\274\232\346\216\222\347\211\210\346\240\207\347\255\276.md" @@ -1,3 +1,9 @@ +--- +title: 04-HTML标签:排版标签 +publish: true +--- + + ## 本文主要内容 diff --git "a/01-HTML/05-HTML\346\240\207\347\255\276\357\274\232\345\255\227\344\275\223\346\240\207\347\255\276\345\222\214\350\266\205\351\223\276\346\216\245.md" "b/01-HTML/05-HTML\346\240\207\347\255\276\357\274\232\345\255\227\344\275\223\346\240\207\347\255\276\345\222\214\350\266\205\351\223\276\346\216\245.md" index 53556d3e..f62a06f3 100644 --- "a/01-HTML/05-HTML\346\240\207\347\255\276\357\274\232\345\255\227\344\275\223\346\240\207\347\255\276\345\222\214\350\266\205\351\223\276\346\216\245.md" +++ "b/01-HTML/05-HTML\346\240\207\347\255\276\357\274\232\345\255\227\344\275\223\346\240\207\347\255\276\345\222\214\350\266\205\351\223\276\346\216\245.md" @@ -1,3 +1,9 @@ +--- +title: 05-HTML标签:字体标签和超链接 +publish: true +--- + + ## 本文主要内容 diff --git "a/01-HTML/06-HTML\346\240\207\347\255\276\357\274\232\345\233\276\347\211\207\346\240\207\347\255\276.md" "b/01-HTML/06-HTML\346\240\207\347\255\276\357\274\232\345\233\276\347\211\207\346\240\207\347\255\276.md" index cf7642f2..d244f3cc 100644 --- "a/01-HTML/06-HTML\346\240\207\347\255\276\357\274\232\345\233\276\347\211\207\346\240\207\347\255\276.md" +++ "b/01-HTML/06-HTML\346\240\207\347\255\276\357\274\232\345\233\276\347\211\207\346\240\207\347\255\276.md" @@ -1,3 +1,9 @@ +--- +title: 06-HTML标签:图片标签 +publish: true +--- + + ## img标签介绍 diff --git "a/01-HTML/07-html\346\240\207\347\255\276\345\233\276\346\226\207\350\257\246\350\247\243\357\274\210\344\272\214\357\274\211.md" "b/01-HTML/07-html\346\240\207\347\255\276\345\233\276\346\226\207\350\257\246\350\247\243\357\274\210\344\272\214\357\274\211.md" index 240b86fd..57e8e14d 100644 --- "a/01-HTML/07-html\346\240\207\347\255\276\345\233\276\346\226\207\350\257\246\350\247\243\357\274\210\344\272\214\357\274\211.md" +++ "b/01-HTML/07-html\346\240\207\347\255\276\345\233\276\346\226\207\350\257\246\350\247\243\357\274\210\344\272\214\357\274\211.md" @@ -1,3 +1,9 @@ +--- +title: 07-html标签图文详解(二) +publish: true +--- + + ## 本文主要内容 diff --git "a/01-HTML/08-HTML5\350\257\246\350\247\243.md" "b/01-HTML/08-HTML5\350\257\246\350\247\243.md" index 6f7e4c9a..e0523d73 100644 --- "a/01-HTML/08-HTML5\350\257\246\350\247\243.md" +++ "b/01-HTML/08-HTML5\350\257\246\350\247\243.md" @@ -1,8 +1,10 @@ +--- +title: 08-HTML5详解 +publish: true +--- + -> 本文最初发表于[博客园](https://www.cnblogs.com/smyhvae/p/8424230.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 - -> 以下是正文。 ## HTML5的介绍 diff --git "a/01-HTML/09-HTML5\344\270\276\344\276\213\357\274\232\347\256\200\345\215\225\347\232\204\350\247\206\351\242\221\346\222\255\346\224\276\345\231\250.md" "b/01-HTML/09-HTML5\344\270\276\344\276\213\357\274\232\347\256\200\345\215\225\347\232\204\350\247\206\351\242\221\346\222\255\346\224\276\345\231\250.md" index a2c89669..796dacbe 100644 --- "a/01-HTML/09-HTML5\344\270\276\344\276\213\357\274\232\347\256\200\345\215\225\347\232\204\350\247\206\351\242\221\346\222\255\346\224\276\345\231\250.md" +++ "b/01-HTML/09-HTML5\344\270\276\344\276\213\357\274\232\347\256\200\345\215\225\347\232\204\350\247\206\351\242\221\346\222\255\346\224\276\345\231\250.md" @@ -1,3 +1,9 @@ +--- +title: 09-HTML5举例:简单的视频播放器 +publish: true +--- + + 我们采用 Bootstrap 网站的图标字体,作为播放器的按钮图标。 diff --git "a/01-HTML/10-HTML5\350\257\246\350\247\243\357\274\210\344\272\214\357\274\211.md" "b/01-HTML/10-HTML5\350\257\246\350\247\243\357\274\210\344\272\214\357\274\211.md" index d58cf439..9c416188 100644 --- "a/01-HTML/10-HTML5\350\257\246\350\247\243\357\274\210\344\272\214\357\274\211.md" +++ "b/01-HTML/10-HTML5\350\257\246\350\247\243\357\274\210\344\272\214\357\274\211.md" @@ -1,3 +1,9 @@ +--- +title: 10-HTML5详解(二) +publish: true +--- + + ## 本文主要内容 diff --git "a/01-HTML/11-HTML5\350\257\246\350\247\243\357\274\210\344\270\211\357\274\211.md" "b/01-HTML/11-HTML5\350\257\246\350\247\243\357\274\210\344\270\211\357\274\211.md" index e8dde34f..3861e530 100644 --- "a/01-HTML/11-HTML5\350\257\246\350\247\243\357\274\210\344\270\211\357\274\211.md" +++ "b/01-HTML/11-HTML5\350\257\246\350\247\243\357\274\210\344\270\211\357\274\211.md" @@ -1,3 +1,9 @@ +--- +title: 11-HTML5详解(三) +publish: true +--- + + ## Web 存储 diff --git "a/01-HTML/12-HTML\345\237\272\347\241\200\345\233\236\351\241\276.md" "b/01-HTML/12-HTML\345\237\272\347\241\200\345\233\236\351\241\276.md" index fb6d4d00..9b6b5cd1 100644 --- "a/01-HTML/12-HTML\345\237\272\347\241\200\345\233\236\351\241\276.md" +++ "b/01-HTML/12-HTML\345\237\272\347\241\200\345\233\236\351\241\276.md" @@ -1,3 +1,9 @@ +--- +title: 12-HTML基础回顾 +publish: true +--- + + ## 本文主要内容 diff --git "a/02-CSS\345\237\272\347\241\200/01-CSS\345\261\236\346\200\247\357\274\232\345\255\227\344\275\223\345\261\236\346\200\247\345\222\214\346\226\207\346\234\254\345\261\236\346\200\247.md" "b/02-CSS\345\237\272\347\241\200/01-CSS\345\261\236\346\200\247\357\274\232\345\255\227\344\275\223\345\261\236\346\200\247\345\222\214\346\226\207\346\234\254\345\261\236\346\200\247.md" index b6ebd76e..9212bac7 100644 --- "a/02-CSS\345\237\272\347\241\200/01-CSS\345\261\236\346\200\247\357\274\232\345\255\227\344\275\223\345\261\236\346\200\247\345\222\214\346\226\207\346\234\254\345\261\236\346\200\247.md" +++ "b/02-CSS\345\237\272\347\241\200/01-CSS\345\261\236\346\200\247\357\274\232\345\255\227\344\275\223\345\261\236\346\200\247\345\222\214\346\226\207\346\234\254\345\261\236\346\200\247.md" @@ -1,3 +1,9 @@ +--- +title: 01-CSS属性:字体属性和文本属性 +publish: true +--- + + ## 本文重要内容 diff --git "a/02-CSS\345\237\272\347\241\200/02-CSS\345\261\236\346\200\247\357\274\232\350\203\214\346\231\257\345\261\236\346\200\247.md" "b/02-CSS\345\237\272\347\241\200/02-CSS\345\261\236\346\200\247\357\274\232\350\203\214\346\231\257\345\261\236\346\200\247.md" index 6b78113e..1fd0f55c 100644 --- "a/02-CSS\345\237\272\347\241\200/02-CSS\345\261\236\346\200\247\357\274\232\350\203\214\346\231\257\345\261\236\346\200\247.md" +++ "b/02-CSS\345\237\272\347\241\200/02-CSS\345\261\236\346\200\247\357\274\232\350\203\214\346\231\257\345\261\236\346\200\247.md" @@ -1,8 +1,10 @@ +--- +title: 02-CSS属性:背景属性 +publish: true +--- + -> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8277895.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 - -> 以下是正文。 ## background 的常见背景属性 diff --git "a/02-CSS\345\237\272\347\241\200/03-CSS\346\240\267\345\274\217\350\241\250\345\222\214\351\200\211\346\213\251\345\231\250.md" "b/02-CSS\345\237\272\347\241\200/03-CSS\346\240\267\345\274\217\350\241\250\345\222\214\351\200\211\346\213\251\345\231\250.md" index 24abd4cd..a2663699 100644 --- "a/02-CSS\345\237\272\347\241\200/03-CSS\346\240\267\345\274\217\350\241\250\345\222\214\351\200\211\346\213\251\345\231\250.md" +++ "b/02-CSS\345\237\272\347\241\200/03-CSS\346\240\267\345\274\217\350\241\250\345\222\214\351\200\211\346\213\251\345\231\250.md" @@ -1,4 +1,9 @@ -> 本文最初于 2015-10-03 发表于[博客园](http://www.cnblogs.com/smyhvae/p/4853995.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在 GitHub 上关注我,一起入门和进阶前端。 +--- +title: 03-CSS样式表和选择器 +publish: true +--- + + ## 本文主要内容 diff --git "a/02-CSS\345\237\272\347\241\200/04-CSS\351\200\211\346\213\251\345\231\250\357\274\232\344\274\252\347\261\273.md" "b/02-CSS\345\237\272\347\241\200/04-CSS\351\200\211\346\213\251\345\231\250\357\274\232\344\274\252\347\261\273.md" index 5d286cd2..b7ec272d 100644 --- "a/02-CSS\345\237\272\347\241\200/04-CSS\351\200\211\346\213\251\345\231\250\357\274\232\344\274\252\347\261\273.md" +++ "b/02-CSS\345\237\272\347\241\200/04-CSS\351\200\211\346\213\251\345\231\250\357\274\232\344\274\252\347\261\273.md" @@ -1,7 +1,10 @@ +--- +title: 04-CSS选择器:伪类 +publish: true +--- -> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8280814.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 + -> 以下是正文。 ## 伪类(伪类选择器) diff --git "a/02-CSS\345\237\272\347\241\200/05-CSS\346\240\267\345\274\217\350\241\250\347\232\204\347\273\247\346\211\277\346\200\247\345\222\214\345\261\202\345\217\240\346\200\247.md" "b/02-CSS\345\237\272\347\241\200/05-CSS\346\240\267\345\274\217\350\241\250\347\232\204\347\273\247\346\211\277\346\200\247\345\222\214\345\261\202\345\217\240\346\200\247.md" index 48dbeed7..035b743a 100644 --- "a/02-CSS\345\237\272\347\241\200/05-CSS\346\240\267\345\274\217\350\241\250\347\232\204\347\273\247\346\211\277\346\200\247\345\222\214\345\261\202\345\217\240\346\200\247.md" +++ "b/02-CSS\345\237\272\347\241\200/05-CSS\346\240\267\345\274\217\350\241\250\347\232\204\347\273\247\346\211\277\346\200\247\345\222\214\345\261\202\345\217\240\346\200\247.md" @@ -1,7 +1,10 @@ +--- +title: 05-CSS样式表的继承性和层叠性 +publish: true +--- -> 本文最初于2017-07-29发表于[博客园](http://www.cnblogs.com/smyhvae/p/7253929.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 + -> 以下是正文。 ## 本文重点 diff --git "a/02-CSS\345\237\272\347\241\200/06-CSS\347\233\222\346\250\241\345\236\213\350\257\246\350\247\243.md" "b/02-CSS\345\237\272\347\241\200/06-CSS\347\233\222\346\250\241\345\236\213\350\257\246\350\247\243.md" index e03930ba..c40c4951 100644 --- "a/02-CSS\345\237\272\347\241\200/06-CSS\347\233\222\346\250\241\345\236\213\350\257\246\350\247\243.md" +++ "b/02-CSS\345\237\272\347\241\200/06-CSS\347\233\222\346\250\241\345\236\213\350\257\246\350\247\243.md" @@ -1,6 +1,10 @@ +--- +title: 06-CSS盒模型详解 +publish: true +--- + -> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/7256371.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新。以下是正文。 ## 盒子模型 diff --git "a/02-CSS\345\237\272\347\241\200/07-\346\265\256\345\212\250.md" "b/02-CSS\345\237\272\347\241\200/07-\346\265\256\345\212\250.md" index c19a728f..bdc56bf3 100644 --- "a/02-CSS\345\237\272\347\241\200/07-\346\265\256\345\212\250.md" +++ "b/02-CSS\345\237\272\347\241\200/07-\346\265\256\345\212\250.md" @@ -1,8 +1,9 @@ +--- +title: 07-浮动 +publish: true +--- - - -> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/7297736.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新。以下是正文。 - + diff --git "a/02-CSS\345\237\272\347\241\200/08-CSS\345\261\236\346\200\247\357\274\232\345\256\232\344\275\215\345\261\236\346\200\247.md" "b/02-CSS\345\237\272\347\241\200/08-CSS\345\261\236\346\200\247\357\274\232\345\256\232\344\275\215\345\261\236\346\200\247.md" index 72cdc58b..f5b76ca9 100644 --- "a/02-CSS\345\237\272\347\241\200/08-CSS\345\261\236\346\200\247\357\274\232\345\256\232\344\275\215\345\261\236\346\200\247.md" +++ "b/02-CSS\345\237\272\347\241\200/08-CSS\345\261\236\346\200\247\357\274\232\345\256\232\344\275\215\345\261\236\346\200\247.md" @@ -1,8 +1,10 @@ +--- +title: 08-CSS属性:定位属性 +publish: true +--- + -> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8296748.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 - -> 以下是正文。 diff --git "a/02-CSS\345\237\272\347\241\200/09-CSS\346\241\210\344\276\213\350\256\262\350\247\243\357\274\232\345\215\232\351\233\205\344\272\222\345\212\250.md" "b/02-CSS\345\237\272\347\241\200/09-CSS\346\241\210\344\276\213\350\256\262\350\247\243\357\274\232\345\215\232\351\233\205\344\272\222\345\212\250.md" index 0c1b382a..b02be51c 100644 --- "a/02-CSS\345\237\272\347\241\200/09-CSS\346\241\210\344\276\213\350\256\262\350\247\243\357\274\232\345\215\232\351\233\205\344\272\222\345\212\250.md" +++ "b/02-CSS\345\237\272\347\241\200/09-CSS\346\241\210\344\276\213\350\256\262\350\247\243\357\274\232\345\215\232\351\233\205\344\272\222\345\212\250.md" @@ -1,3 +1,9 @@ +--- +title: 09-CSS案例讲解:博雅互动 +publish: true +--- + + ## 前言 diff --git "a/02-CSS\345\237\272\347\241\200/10-CSS3\351\200\211\346\213\251\345\231\250\350\257\246\350\247\243.md" "b/02-CSS\345\237\272\347\241\200/10-CSS3\351\200\211\346\213\251\345\231\250\350\257\246\350\247\243.md" index 88a7ec0b..d0a02ff8 100644 --- "a/02-CSS\345\237\272\347\241\200/10-CSS3\351\200\211\346\213\251\345\231\250\350\257\246\350\247\243.md" +++ "b/02-CSS\345\237\272\347\241\200/10-CSS3\351\200\211\346\213\251\345\231\250\350\257\246\350\247\243.md" @@ -1,3 +1,9 @@ +--- +title: 10-CSS3选择器详解 +publish: true +--- + + diff --git "a/02-CSS\345\237\272\347\241\200/11-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\210\344\270\200\357\274\211.md" "b/02-CSS\345\237\272\347\241\200/11-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\210\344\270\200\357\274\211.md" index 5e7300e9..c5c1c191 100644 --- "a/02-CSS\345\237\272\347\241\200/11-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\210\344\270\200\357\274\211.md" +++ "b/02-CSS\345\237\272\347\241\200/11-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\210\344\270\200\357\274\211.md" @@ -1,7 +1,10 @@ +--- +title: 11-CSS3属性详解(一) +publish: true +--- -> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8430898.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 + -> 以下是正文。 ## 前言 diff --git "a/02-CSS\345\237\272\347\241\200/12-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\232\345\212\250\347\224\273\350\257\246\350\247\243.md" "b/02-CSS\345\237\272\347\241\200/12-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\232\345\212\250\347\224\273\350\257\246\350\247\243.md" index ffaeaa3f..8816b161 100644 --- "a/02-CSS\345\237\272\347\241\200/12-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\232\345\212\250\347\224\273\350\257\246\350\247\243.md" +++ "b/02-CSS\345\237\272\347\241\200/12-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\232\345\212\250\347\224\273\350\257\246\350\247\243.md" @@ -1,7 +1,10 @@ +--- +title: 12-CSS3属性详解:动画详解 +publish: true +--- -> 本文最初发表于[博客园](),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 + -> 以下是正文。 ## 前言 diff --git "a/02-CSS\345\237\272\347\241\200/13-CSS3\345\261\236\346\200\247\357\274\232Flex\345\270\203\345\261\200\345\233\276\346\226\207\350\257\246\350\247\243.md" "b/02-CSS\345\237\272\347\241\200/13-CSS3\345\261\236\346\200\247\357\274\232Flex\345\270\203\345\261\200\345\233\276\346\226\207\350\257\246\350\247\243.md" index 827d5815..01b2641d 100644 --- "a/02-CSS\345\237\272\347\241\200/13-CSS3\345\261\236\346\200\247\357\274\232Flex\345\270\203\345\261\200\345\233\276\346\226\207\350\257\246\350\247\243.md" +++ "b/02-CSS\345\237\272\347\241\200/13-CSS3\345\261\236\346\200\247\357\274\232Flex\345\270\203\345\261\200\345\233\276\346\226\207\350\257\246\350\247\243.md" @@ -1,3 +1,9 @@ +--- +title: 13-CSS3属性:Flex布局图文详解 +publish: true +--- + + ## 前言 diff --git "a/02-CSS\345\237\272\347\241\200/14-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\232Web\345\255\227\344\275\223.md" "b/02-CSS\345\237\272\347\241\200/14-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\232Web\345\255\227\344\275\223.md" index e4a882e1..453bb8c2 100644 --- "a/02-CSS\345\237\272\347\241\200/14-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\232Web\345\255\227\344\275\223.md" +++ "b/02-CSS\345\237\272\347\241\200/14-CSS3\345\261\236\346\200\247\350\257\246\350\247\243\357\274\232Web\345\255\227\344\275\223.md" @@ -1,3 +1,9 @@ +--- +title: 14-CSS3属性详解:Web字体 +publish: true +--- + + diff --git "a/02-CSS\345\237\272\347\241\200/15-Sass\345\205\245\351\227\250.md" "b/02-CSS\345\237\272\347\241\200/15-Sass\345\205\245\351\227\250.md" index 6be0d03d..e1786680 100644 --- "a/02-CSS\345\237\272\347\241\200/15-Sass\345\205\245\351\227\250.md" +++ "b/02-CSS\345\237\272\347\241\200/15-Sass\345\205\245\351\227\250.md" @@ -1,3 +1,9 @@ +--- +title: 15-Sass入门 +publish: true +--- + + ## Sass简介 diff --git "a/02-CSS\345\237\272\347\241\200/16-\346\265\217\350\247\210\345\231\250\347\232\204\345\205\274\345\256\271\346\200\247\351\227\256\351\242\230.md" "b/02-CSS\345\237\272\347\241\200/16-\346\265\217\350\247\210\345\231\250\347\232\204\345\205\274\345\256\271\346\200\247\351\227\256\351\242\230.md" index e59a103d..5c848757 100644 --- "a/02-CSS\345\237\272\347\241\200/16-\346\265\217\350\247\210\345\231\250\347\232\204\345\205\274\345\256\271\346\200\247\351\227\256\351\242\230.md" +++ "b/02-CSS\345\237\272\347\241\200/16-\346\265\217\350\247\210\345\231\250\347\232\204\345\205\274\345\256\271\346\200\247\351\227\256\351\242\230.md" @@ -1,3 +1,9 @@ +--- +title: 16-浏览器的兼容性问题 +publish: false +--- + + 我们在div里放一个img,发现: @@ -17,13 +23,13 @@ margin: 0px; padding: 0px; } - +
- -
+ + ``` diff --git "a/02-CSS\345\237\272\347\241\200/17-CSS3\347\232\204\345\270\270\350\247\201\350\276\271\346\241\206\346\261\207\346\200\273.md" "b/02-CSS\345\237\272\347\241\200/17-CSS3\347\232\204\345\270\270\350\247\201\350\276\271\346\241\206\346\261\207\346\200\273.md" new file mode 100644 index 00000000..1ffd6289 --- /dev/null +++ "b/02-CSS\345\237\272\347\241\200/17-CSS3\347\232\204\345\270\270\350\247\201\350\276\271\346\241\206\346\261\207\346\200\273.md" @@ -0,0 +1,583 @@ +--- +title: 17-CSS3的常见边框汇总 +publish: true +--- + + + + +## CSS3 常见边框汇总 + +```html + + + + + CSS3 边框 + + + +
+
+

CSS3 边框圆角

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +``` + +效果如下: + +![](http://img.smyhvae.com/20180208_1730.png) + + +## 爱心 + +```html + + + + + + + + +
+ +
+ + +``` + + +效果如下: + +![](http://img.smyhvae.com/20180208_1737.png) + +它其实是下面这两个盒子叠起来的: + +![](http://img.smyhvae.com/20180208_1738.png) + +改变 `.heart::after` 的 left值,即可叠起来。 + + + diff --git "a/02-CSS\345\237\272\347\241\200/others.md" "b/02-CSS\345\237\272\347\241\200/others.md" index 3296345b..ced39e0b 100644 --- "a/02-CSS\345\237\272\347\241\200/others.md" +++ "b/02-CSS\345\237\272\347\241\200/others.md" @@ -1,4 +1,6 @@ - +--- +publish: false +--- ```html diff --git "a/03-CSS\350\277\233\351\230\266/00-\345\207\206\345\244\207.md" "b/03-CSS\350\277\233\351\230\266/00-\345\207\206\345\244\207.md" index b75fd460..d11300ce 100644 --- "a/03-CSS\350\277\233\351\230\266/00-\345\207\206\345\244\207.md" +++ "b/03-CSS\350\277\233\351\230\266/00-\345\207\206\345\244\207.md" @@ -1,3 +1,9 @@ +--- +title: 00-准备 +publish: true +--- + + ## 前言 diff --git "a/03-CSS\350\277\233\351\230\266/01-CSS\344\270\255\347\232\204\351\235\236\345\270\203\345\261\200\346\240\267\345\274\217.md" "b/03-CSS\350\277\233\351\230\266/01-CSS\344\270\255\347\232\204\351\235\236\345\270\203\345\261\200\346\240\267\345\274\217.md" index 2e114f02..e897dfac 100644 --- "a/03-CSS\350\277\233\351\230\266/01-CSS\344\270\255\347\232\204\351\235\236\345\270\203\345\261\200\346\240\267\345\274\217.md" +++ "b/03-CSS\350\277\233\351\230\266/01-CSS\344\270\255\347\232\204\351\235\236\345\270\203\345\261\200\346\240\267\345\274\217.md" @@ -1,3 +1,9 @@ +--- +title: 01-CSS中的非布局样式 +publish: true +--- + + ## 前言 diff --git "a/03-CSS\350\277\233\351\230\266/02-CSS\345\270\203\345\261\200.md" "b/03-CSS\350\277\233\351\230\266/02-CSS\345\270\203\345\261\200.md" index 0c6c29c8..7d9a1986 100644 --- "a/03-CSS\350\277\233\351\230\266/02-CSS\345\270\203\345\261\200.md" +++ "b/03-CSS\350\277\233\351\230\266/02-CSS\345\270\203\345\261\200.md" @@ -1,3 +1,9 @@ +--- +title: 02-CSS布局 +publish: true +--- + + ## 前言 diff --git "a/03-CSS\350\277\233\351\230\266/03-\347\275\221\351\241\265\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221\344\270\255\357\274\214\345\205\263\344\272\216\345\255\227\344\275\223\347\232\204\345\270\270\350\257\206.md" "b/03-CSS\350\277\233\351\230\266/03-\347\275\221\351\241\265\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221\344\270\255\357\274\214\345\205\263\344\272\216\345\255\227\344\275\223\347\232\204\345\270\270\350\257\206.md" index 7dacebca..1626d362 100644 --- "a/03-CSS\350\277\233\351\230\266/03-\347\275\221\351\241\265\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221\344\270\255\357\274\214\345\205\263\344\272\216\345\255\227\344\275\223\347\232\204\345\270\270\350\257\206.md" +++ "b/03-CSS\350\277\233\351\230\266/03-\347\275\221\351\241\265\350\256\276\350\256\241\345\222\214\345\274\200\345\217\221\344\270\255\357\274\214\345\205\263\344\272\216\345\255\227\344\275\223\347\232\204\345\270\270\350\257\206.md" @@ -1,6 +1,10 @@ +--- +title: 03-网页设计和开发中,关于字体的常识 +publish: true +--- + -> 本文的最新内容将在[GitHub](https://github.com/qianguyihao/Web/tree/master/03-CSS%E8%BF%9B%E9%98%B6)上实时更新。欢迎在GitHub上关注我,一起入门和进阶前端。 ## 前言 diff --git "a/03-CSS\350\277\233\351\230\266/04-\345\246\202\344\275\225\350\256\251\344\270\200\344\270\252\345\205\203\347\264\240\346\260\264\345\271\263\345\236\202\347\233\264\345\261\205\344\270\255\357\274\237.md" "b/03-CSS\350\277\233\351\230\266/04-\345\246\202\344\275\225\350\256\251\344\270\200\344\270\252\345\205\203\347\264\240\346\260\264\345\271\263\345\236\202\347\233\264\345\261\205\344\270\255\357\274\237.md" index 50b09492..4106c782 100644 --- "a/03-CSS\350\277\233\351\230\266/04-\345\246\202\344\275\225\350\256\251\344\270\200\344\270\252\345\205\203\347\264\240\346\260\264\345\271\263\345\236\202\347\233\264\345\261\205\344\270\255\357\274\237.md" +++ "b/03-CSS\350\277\233\351\230\266/04-\345\246\202\344\275\225\350\256\251\344\270\200\344\270\252\345\205\203\347\264\240\346\260\264\345\271\263\345\236\202\347\233\264\345\261\205\344\270\255\357\274\237.md" @@ -1,7 +1,15 @@ +--- +title: 04-如何让一个元素水平垂直居中? +publish: true +--- + + + + ![](http://img.smyhvae.com/20191108_2130.png) -> 本文的最新内容将在[GitHub](https://github.com/qianguyihao/Web/tree/master/03-CSS%E8%BF%9B%E9%98%B6)上实时更新。欢迎在GitHub上关注我,一起入门和进阶前端。 + ## 前言 diff --git "a/03-CSS\350\277\233\351\230\266/CSS\345\274\200\345\217\221\347\247\257\347\264\257.md" "b/03-CSS\350\277\233\351\230\266/CSS\345\274\200\345\217\221\347\247\257\347\264\257.md" index 8191578b..f34b3729 100644 --- "a/03-CSS\350\277\233\351\230\266/CSS\345\274\200\345\217\221\347\247\257\347\264\257.md" +++ "b/03-CSS\350\277\233\351\230\266/CSS\345\274\200\345\217\221\347\247\257\347\264\257.md" @@ -1,3 +1,9 @@ +--- +title: 认识Web和Web标准 +publish: false +--- + + ### 让flex盒子中的子元素们,居中 diff --git "a/03-CSS\350\277\233\351\230\266/CSS\346\226\207\347\253\240\346\216\250\350\215\220.md" "b/03-CSS\350\277\233\351\230\266/CSS\346\226\207\347\253\240\346\216\250\350\215\220.md" index db37ca0f..c3c1b143 100644 --- "a/03-CSS\350\277\233\351\230\266/CSS\346\226\207\347\253\240\346\216\250\350\215\220.md" +++ "b/03-CSS\350\277\233\351\230\266/CSS\346\226\207\347\253\240\346\216\250\350\215\220.md" @@ -1,3 +1,9 @@ +--- +title: 认识Web和Web标准 +publish: false +--- + + diff --git "a/03-CSS\350\277\233\351\230\266/CSS\347\232\204\344\270\200\344\272\233\345\260\217\347\237\245\350\257\206.md" "b/03-CSS\350\277\233\351\230\266/CSS\347\232\204\344\270\200\344\272\233\345\260\217\347\237\245\350\257\206.md" index a1246d08..e7ac3eb9 100644 --- "a/03-CSS\350\277\233\351\230\266/CSS\347\232\204\344\270\200\344\272\233\345\260\217\347\237\245\350\257\206.md" +++ "b/03-CSS\350\277\233\351\230\266/CSS\347\232\204\344\270\200\344\272\233\345\260\217\347\237\245\350\257\206.md" @@ -1,3 +1,9 @@ +--- +title: 认识Web和Web标准 +publish: false +--- + + diff --git "a/03-CSS\350\277\233\351\230\266/CSS\351\235\242\350\257\225\351\242\230.md" "b/03-CSS\350\277\233\351\230\266/CSS\351\235\242\350\257\225\351\242\230.md" index 1dc1ea72..ad750ea8 100644 --- "a/03-CSS\350\277\233\351\230\266/CSS\351\235\242\350\257\225\351\242\230.md" +++ "b/03-CSS\350\277\233\351\230\266/CSS\351\235\242\350\257\225\351\242\230.md" @@ -1,3 +1,9 @@ +--- +title: 认识Web和Web标准 +publish: false +--- + + ## 常见问题 diff --git "a/04-JavaScript\345\237\272\347\241\200/00-\347\274\226\347\250\213\350\257\255\350\250\200.md" "b/04-JavaScript\345\237\272\347\241\200/00-\347\274\226\347\250\213\350\257\255\350\250\200.md" index 309eb5cf..5defdf34 100644 --- "a/04-JavaScript\345\237\272\347\241\200/00-\347\274\226\347\250\213\350\257\255\350\250\200.md" +++ "b/04-JavaScript\345\237\272\347\241\200/00-\347\274\226\347\250\213\350\257\255\350\250\200.md" @@ -1,3 +1,9 @@ +--- +title: 00-编程语言 +publish: true +--- + + ## 编程语言 diff --git "a/04-JavaScript\345\237\272\347\241\200/01-JS\347\256\200\344\273\213.md" "b/04-JavaScript\345\237\272\347\241\200/01-JS\347\256\200\344\273\213.md" index 9b100783..b6831f06 100644 --- "a/04-JavaScript\345\237\272\347\241\200/01-JS\347\256\200\344\273\213.md" +++ "b/04-JavaScript\345\237\272\347\241\200/01-JS\347\256\200\344\273\213.md" @@ -1,3 +1,9 @@ +--- +title: 01-JS简介 +publish: true +--- + + ## JavaScript背景 diff --git "a/04-JavaScript\345\237\272\347\241\200/02-\345\217\230\351\207\217.md" "b/04-JavaScript\345\237\272\347\241\200/02-\345\217\230\351\207\217.md" index 906a6adc..681a805c 100644 --- "a/04-JavaScript\345\237\272\347\241\200/02-\345\217\230\351\207\217.md" +++ "b/04-JavaScript\345\237\272\347\241\200/02-\345\217\230\351\207\217.md" @@ -1,3 +1,9 @@ +--- +title: 02-变量 +publish: true +--- + + ## 字面量:数字和字符串 diff --git "a/04-JavaScript\345\237\272\347\241\200/03-\345\217\230\351\207\217\347\232\204\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\345\222\214\345\274\225\347\224\250\346\225\260\346\215\256\347\261\273\345\236\213.md" "b/04-JavaScript\345\237\272\347\241\200/03-\345\217\230\351\207\217\347\232\204\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\345\222\214\345\274\225\347\224\250\346\225\260\346\215\256\347\261\273\345\236\213.md" index 9dc1c464..d22450b1 100644 --- "a/04-JavaScript\345\237\272\347\241\200/03-\345\217\230\351\207\217\347\232\204\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\345\222\214\345\274\225\347\224\250\346\225\260\346\215\256\347\261\273\345\236\213.md" +++ "b/04-JavaScript\345\237\272\347\241\200/03-\345\217\230\351\207\217\347\232\204\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\345\222\214\345\274\225\347\224\250\346\225\260\346\215\256\347\261\273\345\236\213.md" @@ -1,3 +1,9 @@ +--- +title: 03-变量的数据类型:基本数据类型和引用数据类型 +publish: true +--- + + ## 变量的数据类型 diff --git "a/04-JavaScript\345\237\272\347\241\200/04-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232String \345\222\214 Boolean.md" "b/04-JavaScript\345\237\272\347\241\200/04-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232String \345\222\214 Boolean.md" index 7f3b04e1..169fef9e 100644 --- "a/04-JavaScript\345\237\272\347\241\200/04-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232String \345\222\214 Boolean.md" +++ "b/04-JavaScript\345\237\272\347\241\200/04-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232String \345\222\214 Boolean.md" @@ -1,3 +1,9 @@ +--- +title: 04-基本数据类型:String 和 Boolean +publish: true +--- + + diff --git "a/04-JavaScript\345\237\272\347\241\200/05-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232Number.md" "b/04-JavaScript\345\237\272\347\241\200/05-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232Number.md" index ec1343b1..6ec672b8 100644 --- "a/04-JavaScript\345\237\272\347\241\200/05-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232Number.md" +++ "b/04-JavaScript\345\237\272\347\241\200/05-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232Number.md" @@ -1,3 +1,9 @@ +--- +title: 05-基本数据类型:Number +publish: true +--- + + ## 数值型:Number diff --git "a/04-JavaScript\345\237\272\347\241\200/06-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232Null \345\222\214 Undefined.md" "b/04-JavaScript\345\237\272\347\241\200/06-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232Null \345\222\214 Undefined.md" index d1995fc6..3387f1cd 100644 --- "a/04-JavaScript\345\237\272\347\241\200/06-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232Null \345\222\214 Undefined.md" +++ "b/04-JavaScript\345\237\272\347\241\200/06-\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213\357\274\232Null \345\222\214 Undefined.md" @@ -1,3 +1,9 @@ +--- +title: 06-基本数据类型:Null 和 Undefined +publish: true +--- + + 很多其他的语言中,只有 null;但 JS 语言中,既有 null,又有 undefined。很多人会弄混,由此觉得 JS 语言很麻烦。其实不然,学习完这篇文章后,你会发现 null 和 undefined 的区别很容易理解。 diff --git "a/04-JavaScript\345\237\272\347\241\200/07-typeof\345\222\214\346\225\260\346\215\256\347\261\273\345\236\213\350\275\254\346\215\242.md" "b/04-JavaScript\345\237\272\347\241\200/07-typeof\345\222\214\346\225\260\346\215\256\347\261\273\345\236\213\350\275\254\346\215\242.md" index 17effdba..aae6f2cf 100644 --- "a/04-JavaScript\345\237\272\347\241\200/07-typeof\345\222\214\346\225\260\346\215\256\347\261\273\345\236\213\350\275\254\346\215\242.md" +++ "b/04-JavaScript\345\237\272\347\241\200/07-typeof\345\222\214\346\225\260\346\215\256\347\261\273\345\236\213\350\275\254\346\215\242.md" @@ -1,3 +1,9 @@ +--- +title: 07-typeof和数据类型转换 +publish: true +--- + + ## 前言 **变量的数据类型转换**:将一种数据类型转换为另外一种数据类型。 diff --git "a/04-JavaScript\345\237\272\347\241\200/08-\350\277\220\347\256\227\347\254\246.md" "b/04-JavaScript\345\237\272\347\241\200/08-\350\277\220\347\256\227\347\254\246.md" index 9124ae82..516ee656 100644 --- "a/04-JavaScript\345\237\272\347\241\200/08-\350\277\220\347\256\227\347\254\246.md" +++ "b/04-JavaScript\345\237\272\347\241\200/08-\350\277\220\347\256\227\347\254\246.md" @@ -1,3 +1,9 @@ +--- +title: 08-运算符 +publish: true +--- + + 我们在本文件夹的第 02 篇里讲到了JS中**变量**的概念,本篇文章讲一下**运算符**和表达式。 diff --git "a/04-JavaScript\345\237\272\347\241\200/09-\346\265\201\347\250\213\346\216\247\345\210\266\350\257\255\345\217\245\357\274\232\351\200\211\346\213\251\347\273\223\346\236\204\357\274\210if\345\222\214switch\357\274\211.md" "b/04-JavaScript\345\237\272\347\241\200/09-\346\265\201\347\250\213\346\216\247\345\210\266\350\257\255\345\217\245\357\274\232\351\200\211\346\213\251\347\273\223\346\236\204\357\274\210if\345\222\214switch\357\274\211.md" index 29bd048e..dba9b7dc 100644 --- "a/04-JavaScript\345\237\272\347\241\200/09-\346\265\201\347\250\213\346\216\247\345\210\266\350\257\255\345\217\245\357\274\232\351\200\211\346\213\251\347\273\223\346\236\204\357\274\210if\345\222\214switch\357\274\211.md" +++ "b/04-JavaScript\345\237\272\347\241\200/09-\346\265\201\347\250\213\346\216\247\345\210\266\350\257\255\345\217\245\357\274\232\351\200\211\346\213\251\347\273\223\346\236\204\357\274\210if\345\222\214switch\357\274\211.md" @@ -1,3 +1,12 @@ +--- +title: 09-流程控制语句:选择结构(if和switch) +publish: true +--- + + + + + ## 代码块 用`{}`包围起来的代码,就是代码块。 diff --git "a/04-JavaScript\345\237\272\347\241\200/10-\346\265\201\347\250\213\346\216\247\345\210\266\350\257\255\345\217\245\357\274\232\345\276\252\347\216\257\347\273\223\346\236\204\357\274\210for\345\222\214while\357\274\211.md" "b/04-JavaScript\345\237\272\347\241\200/10-\346\265\201\347\250\213\346\216\247\345\210\266\350\257\255\345\217\245\357\274\232\345\276\252\347\216\257\347\273\223\346\236\204\357\274\210for\345\222\214while\357\274\211.md" index 4953de55..3f26af42 100644 --- "a/04-JavaScript\345\237\272\347\241\200/10-\346\265\201\347\250\213\346\216\247\345\210\266\350\257\255\345\217\245\357\274\232\345\276\252\347\216\257\347\273\223\346\236\204\357\274\210for\345\222\214while\357\274\211.md" +++ "b/04-JavaScript\345\237\272\347\241\200/10-\346\265\201\347\250\213\346\216\247\345\210\266\350\257\255\345\217\245\357\274\232\345\276\252\347\216\257\347\273\223\346\236\204\357\274\210for\345\222\214while\357\274\211.md" @@ -1,3 +1,11 @@ +--- +title: 10-流程控制语句:循环结构(for和while) +publish: true +--- + + + + ## 前言 循环语句:通过循环语句可以反复的执行一段代码多次。 @@ -228,7 +236,7 @@ do...while语句在执行时,会先执行循环体: ### break -- break 可以用来退出 switch 语句或退出**整个**循环语句(循环语句包括 for 循环、while 循环。不包括 if。if 里不能用 break 和 continue,否则会报错)。 +- break 可以用来退出 switch 语句或退出**整个**循环语句(循环语句包括 for 循环、while 循环。不包括 if。单独的if 语句里不能用 break 和 continue,否则会报错)。 - break 会立即终止离它**最近**的那个循环语句。 diff --git "a/04-JavaScript\345\237\272\347\241\200/11-\345\257\271\350\261\241\347\256\200\344\273\213.md" "b/04-JavaScript\345\237\272\347\241\200/11-\345\257\271\350\261\241\347\256\200\344\273\213.md" index c760a438..517de2bc 100644 --- "a/04-JavaScript\345\237\272\347\241\200/11-\345\257\271\350\261\241\347\256\200\344\273\213.md" +++ "b/04-JavaScript\345\237\272\347\241\200/11-\345\257\271\350\261\241\347\256\200\344\273\213.md" @@ -1,3 +1,11 @@ +--- +title: 11-对象简介 +publish: true +--- + + + + ## 对象简介 diff --git "a/04-JavaScript\345\237\272\347\241\200/12-\345\237\272\346\234\254\345\214\205\350\243\205\347\261\273\345\236\213.md" "b/04-JavaScript\345\237\272\347\241\200/12-\345\237\272\346\234\254\345\214\205\350\243\205\347\261\273\345\236\213.md" index 7a5e930b..905e7c83 100644 --- "a/04-JavaScript\345\237\272\347\241\200/12-\345\237\272\346\234\254\345\214\205\350\243\205\347\261\273\345\236\213.md" +++ "b/04-JavaScript\345\237\272\347\241\200/12-\345\237\272\346\234\254\345\214\205\350\243\205\347\261\273\345\236\213.md" @@ -1,3 +1,11 @@ +--- +title: 12-基本包装类型 +publish: true +--- + + + + ## 基本数据类型不能绑定属性和方法 diff --git "a/04-JavaScript\345\237\272\347\241\200/13-\345\206\205\347\275\256\345\257\271\350\261\241 String\357\274\232\345\255\227\347\254\246\344\270\262\347\232\204\345\270\270\350\247\201\346\226\271\346\263\225.md" "b/04-JavaScript\345\237\272\347\241\200/13-\345\206\205\347\275\256\345\257\271\350\261\241 String\357\274\232\345\255\227\347\254\246\344\270\262\347\232\204\345\270\270\350\247\201\346\226\271\346\263\225.md" index 9c8f1ac0..7e01ba88 100644 --- "a/04-JavaScript\345\237\272\347\241\200/13-\345\206\205\347\275\256\345\257\271\350\261\241 String\357\274\232\345\255\227\347\254\246\344\270\262\347\232\204\345\270\270\350\247\201\346\226\271\346\263\225.md" +++ "b/04-JavaScript\345\237\272\347\241\200/13-\345\206\205\347\275\256\345\257\271\350\261\241 String\357\274\232\345\255\227\347\254\246\344\270\262\347\232\204\345\270\270\350\247\201\346\226\271\346\263\225.md" @@ -1,3 +1,11 @@ +--- +title: 13-基本包装类型 +publish: true +--- + + + + ## 内置对象简介 diff --git "a/04-JavaScript\345\237\272\347\241\200/14-\345\206\205\347\275\256\345\257\271\350\261\241\357\274\232Number\345\222\214Math.md" "b/04-JavaScript\345\237\272\347\241\200/14-\345\206\205\347\275\256\345\257\271\350\261\241\357\274\232Number\345\222\214Math.md" index 3e825f58..f7b0c584 100644 --- "a/04-JavaScript\345\237\272\347\241\200/14-\345\206\205\347\275\256\345\257\271\350\261\241\357\274\232Number\345\222\214Math.md" +++ "b/04-JavaScript\345\237\272\347\241\200/14-\345\206\205\347\275\256\345\257\271\350\261\241\357\274\232Number\345\222\214Math.md" @@ -1,3 +1,11 @@ +--- +title: 14-内置对象:Number和Math +publish: true +--- + + + + ## 内置对象 Number 的常见方法 diff --git "a/04-JavaScript\345\237\272\347\241\200/15-\345\206\205\347\275\256\345\257\271\350\261\241\357\274\232Date.md" "b/04-JavaScript\345\237\272\347\241\200/15-\345\206\205\347\275\256\345\257\271\350\261\241\357\274\232Date.md" index 038c127c..7f6c38e7 100644 --- "a/04-JavaScript\345\237\272\347\241\200/15-\345\206\205\347\275\256\345\257\271\350\261\241\357\274\232Date.md" +++ "b/04-JavaScript\345\237\272\347\241\200/15-\345\206\205\347\275\256\345\257\271\350\261\241\357\274\232Date.md" @@ -1,3 +1,11 @@ +--- +title: 15-内置对象:Date +publish: true +--- + + + + ## 内置对象:Date diff --git "a/04-JavaScript\345\237\272\347\241\200/16-\346\225\260\347\273\204\347\256\200\344\273\213.md" "b/04-JavaScript\345\237\272\347\241\200/16-\346\225\260\347\273\204\347\256\200\344\273\213.md" index a6184a0e..7a73da65 100644 --- "a/04-JavaScript\345\237\272\347\241\200/16-\346\225\260\347\273\204\347\256\200\344\273\213.md" +++ "b/04-JavaScript\345\237\272\347\241\200/16-\346\225\260\347\273\204\347\256\200\344\273\213.md" @@ -1,3 +1,11 @@ +--- +title: 16-数组简介 +publish: true +--- + + + + > 之前学习的数据类型,只能存储一个值(字符串也为一个值)。如果我们想存储多个值,就可以使用数组。 ## 数组简介 diff --git "a/04-JavaScript\345\237\272\347\241\200/17-\346\225\260\347\273\204\347\232\204\345\270\270\350\247\201\346\226\271\346\263\225.md" "b/04-JavaScript\345\237\272\347\241\200/17-\346\225\260\347\273\204\347\232\204\345\270\270\350\247\201\346\226\271\346\263\225.md" index 27ce092b..1c688cca 100644 --- "a/04-JavaScript\345\237\272\347\241\200/17-\346\225\260\347\273\204\347\232\204\345\270\270\350\247\201\346\226\271\346\263\225.md" +++ "b/04-JavaScript\345\237\272\347\241\200/17-\346\225\260\347\273\204\347\232\204\345\270\270\350\247\201\346\226\271\346\263\225.md" @@ -1,3 +1,11 @@ +--- +title: 17-数组的常见方法 +publish: true +--- + + + + ## 数组的方法清单 ### 数组的类型相关 diff --git "a/04-JavaScript\345\237\272\347\241\200/18-\345\207\275\346\225\260.md" "b/04-JavaScript\345\237\272\347\241\200/18-\345\207\275\346\225\260.md" index f834204b..62995990 100644 --- "a/04-JavaScript\345\237\272\347\241\200/18-\345\207\275\346\225\260.md" +++ "b/04-JavaScript\345\237\272\347\241\200/18-\345\207\275\346\225\260.md" @@ -1,3 +1,11 @@ +--- +title: 18-函数 +publish: true +--- + + + + ## 前言 diff --git "a/04-JavaScript\345\237\272\347\241\200/19-\344\275\234\347\224\250\345\237\237\345\222\214\345\217\230\351\207\217\346\217\220\345\215\207.md" "b/04-JavaScript\345\237\272\347\241\200/19-\344\275\234\347\224\250\345\237\237\345\222\214\345\217\230\351\207\217\346\217\220\345\215\207.md" index 8c458e62..f9a8df2e 100644 --- "a/04-JavaScript\345\237\272\347\241\200/19-\344\275\234\347\224\250\345\237\237\345\222\214\345\217\230\351\207\217\346\217\220\345\215\207.md" +++ "b/04-JavaScript\345\237\272\347\241\200/19-\344\275\234\347\224\250\345\237\237\345\222\214\345\217\230\351\207\217\346\217\220\345\215\207.md" @@ -1,3 +1,11 @@ +--- +title: 19-作用域和变量提升 +publish: true +--- + + + + > 作用域、变量提升的知识点,面试时会经常遇到。 diff --git "a/04-JavaScript\345\237\272\347\241\200/20-\351\242\204\347\274\226\350\257\221.md" "b/04-JavaScript\345\237\272\347\241\200/20-\351\242\204\347\274\226\350\257\221.md" index c6dfe604..e0d9dd36 100644 --- "a/04-JavaScript\345\237\272\347\241\200/20-\351\242\204\347\274\226\350\257\221.md" +++ "b/04-JavaScript\345\237\272\347\241\200/20-\351\242\204\347\274\226\350\257\221.md" @@ -1,3 +1,11 @@ +--- +title: 20-预编译 +publish: true +--- + + + + > 我们在上一篇文章《作用域》中简单讲过“变量提升”,今天来讲一下预编译,这对我们深入理解变量提升会有帮助。 diff --git "a/04-JavaScript\345\237\272\347\241\200/21-this\346\214\207\345\220\221.md" "b/04-JavaScript\345\237\272\347\241\200/21-this\346\214\207\345\220\221.md" index 8cb154b8..0b93ed63 100644 --- "a/04-JavaScript\345\237\272\347\241\200/21-this\346\214\207\345\220\221.md" +++ "b/04-JavaScript\345\237\272\347\241\200/21-this\346\214\207\345\220\221.md" @@ -1,3 +1,11 @@ +--- +title: 21-this指向 +publish: true +--- + + + + ## 执行期上下文 当**函数执行**时(准确来说,是在函数发生预编译的前一刻),会创建一个执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境。 diff --git "a/04-JavaScript\345\237\272\347\241\200/22-call\343\200\201apply \345\222\214 bind.md" "b/04-JavaScript\345\237\272\347\241\200/22-call\343\200\201apply \345\222\214 bind.md" index d70254ea..04add649 100644 --- "a/04-JavaScript\345\237\272\347\241\200/22-call\343\200\201apply \345\222\214 bind.md" +++ "b/04-JavaScript\345\237\272\347\241\200/22-call\343\200\201apply \345\222\214 bind.md" @@ -1,3 +1,11 @@ +--- +title: 22-call、apply 和 bind +publish: true +--- + + + + ## 前言 JS 专门为我们提供了一些方法来改变函数内部的 this 指向。常见的方法有 call()、apply()、bind() 方法。 diff --git "a/04-JavaScript\345\237\272\347\241\200/23-\351\253\230\351\230\266\345\207\275\346\225\260.md" "b/04-JavaScript\345\237\272\347\241\200/23-\351\253\230\351\230\266\345\207\275\346\225\260.md" index 469cf2e4..b9c3075d 100644 --- "a/04-JavaScript\345\237\272\347\241\200/23-\351\253\230\351\230\266\345\207\275\346\225\260.md" +++ "b/04-JavaScript\345\237\272\347\241\200/23-\351\253\230\351\230\266\345\207\275\346\225\260.md" @@ -1,3 +1,11 @@ +--- +title: 23-高阶函数 +publish: true +--- + + + + ## 高阶函数 ### 高阶函数的概念 diff --git "a/04-JavaScript\345\237\272\347\241\200/24-\351\227\255\345\214\205.md" "b/04-JavaScript\345\237\272\347\241\200/24-\351\227\255\345\214\205.md" index ff7072e4..3cf338fc 100644 --- "a/04-JavaScript\345\237\272\347\241\200/24-\351\227\255\345\214\205.md" +++ "b/04-JavaScript\345\237\272\347\241\200/24-\351\227\255\345\214\205.md" @@ -1,3 +1,11 @@ +--- +title: 24-闭包 +publish: true +--- + + + + ## 闭包的引入 我们知道,变量根据作用域的不同分为两种:全局变量和局部变量。 diff --git "a/04-JavaScript\345\237\272\347\241\200/25-\351\235\242\345\220\221\345\257\271\350\261\241\346\246\202\350\277\260.md" "b/04-JavaScript\345\237\272\347\241\200/25-\351\235\242\345\220\221\345\257\271\350\261\241\346\246\202\350\277\260.md" index 38465759..45b78cf0 100644 --- "a/04-JavaScript\345\237\272\347\241\200/25-\351\235\242\345\220\221\345\257\271\350\261\241\346\246\202\350\277\260.md" +++ "b/04-JavaScript\345\237\272\347\241\200/25-\351\235\242\345\220\221\345\257\271\350\261\241\346\246\202\350\277\260.md" @@ -1,3 +1,11 @@ +--- +title: 25-面向对象概述 +publish: true +--- + + + + ## 面向过程和面向对象 ### 面向过程 diff --git "a/04-JavaScript\345\237\272\347\241\200/26-\345\257\271\350\261\241\347\232\204\345\210\233\345\273\272&\346\236\204\351\200\240\345\207\275\346\225\260.md" "b/04-JavaScript\345\237\272\347\241\200/26-\345\257\271\350\261\241\347\232\204\345\210\233\345\273\272&\346\236\204\351\200\240\345\207\275\346\225\260.md" index 7e3912c2..422e21b2 100644 --- "a/04-JavaScript\345\237\272\347\241\200/26-\345\257\271\350\261\241\347\232\204\345\210\233\345\273\272&\346\236\204\351\200\240\345\207\275\346\225\260.md" +++ "b/04-JavaScript\345\237\272\347\241\200/26-\345\257\271\350\261\241\347\232\204\345\210\233\345\273\272&\346\236\204\351\200\240\345\207\275\346\225\260.md" @@ -1,3 +1,11 @@ +--- +title: 26-对象的创建&构造函数 +publish: true +--- + + + + > 在看本文之前,可以先复习前面的一篇文章:《04-JavaScript 基础/11-对象简介.md》 ## 创建自定义对象的几种方法 diff --git "a/04-JavaScript\345\237\272\347\241\200/27-\345\257\271\350\261\241\347\232\204\345\237\272\346\234\254\346\223\215\344\275\234.md" "b/04-JavaScript\345\237\272\347\241\200/27-\345\257\271\350\261\241\347\232\204\345\237\272\346\234\254\346\223\215\344\275\234.md" index 4de5b8f1..78f5c346 100644 --- "a/04-JavaScript\345\237\272\347\241\200/27-\345\257\271\350\261\241\347\232\204\345\237\272\346\234\254\346\223\215\344\275\234.md" +++ "b/04-JavaScript\345\237\272\347\241\200/27-\345\257\271\350\261\241\347\232\204\345\237\272\346\234\254\346\223\215\344\275\234.md" @@ -1,3 +1,11 @@ +--- +title: 27-对象的基本操作 +publish: true +--- + + + + ## 对象的基本操作 ### 创建对象 diff --git "a/04-JavaScript\345\237\272\347\241\200/28-\346\265\205\346\213\267\350\264\235\345\222\214\346\267\261\346\213\267\350\264\235.md" "b/04-JavaScript\345\237\272\347\241\200/28-\346\265\205\346\213\267\350\264\235\345\222\214\346\267\261\346\213\267\350\264\235.md" index d12a8f17..788e0eb5 100644 --- "a/04-JavaScript\345\237\272\347\241\200/28-\346\265\205\346\213\267\350\264\235\345\222\214\346\267\261\346\213\267\350\264\235.md" +++ "b/04-JavaScript\345\237\272\347\241\200/28-\346\265\205\346\213\267\350\264\235\345\222\214\346\267\261\346\213\267\350\264\235.md" @@ -1,3 +1,11 @@ +--- +title: 28-浅拷贝和深拷贝 +publish: true +--- + + + + ## 概念 - 浅拷贝:只拷贝最外面一层的数据;更深层次的对象,只拷贝引用。 diff --git "a/04-JavaScript\345\237\272\347\241\200/29-\345\257\271\350\261\241\347\232\204\351\253\230\347\272\247\346\223\215\344\275\234\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" "b/04-JavaScript\345\237\272\347\241\200/29-\345\257\271\350\261\241\347\232\204\351\253\230\347\272\247\346\223\215\344\275\234\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" index e88d0014..59ce5c14 100644 --- "a/04-JavaScript\345\237\272\347\241\200/29-\345\257\271\350\261\241\347\232\204\351\253\230\347\272\247\346\223\215\344\275\234\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" +++ "b/04-JavaScript\345\237\272\347\241\200/29-\345\257\271\350\261\241\347\232\204\351\253\230\347\272\247\346\223\215\344\275\234\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" @@ -1,3 +1,11 @@ +--- +title: 29-对象的高级操作(待更新) +publish: false +--- + + + + ## Object.freeze() 冻结对象 diff --git "a/04-JavaScript\345\237\272\347\241\200/30-\345\216\237\345\236\213\351\223\276\345\222\214\345\216\237\345\236\213\347\273\247\346\211\277\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" "b/04-JavaScript\345\237\272\347\241\200/30-\345\216\237\345\236\213\351\223\276\345\222\214\345\216\237\345\236\213\347\273\247\346\211\277\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" index b6e4bdd1..f61fd218 100644 --- "a/04-JavaScript\345\237\272\347\241\200/30-\345\216\237\345\236\213\351\223\276\345\222\214\345\216\237\345\236\213\347\273\247\346\211\277\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" +++ "b/04-JavaScript\345\237\272\347\241\200/30-\345\216\237\345\236\213\351\223\276\345\222\214\345\216\237\345\236\213\347\273\247\346\211\277\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" @@ -1,3 +1,11 @@ +--- +title: 30-原型链和原型继承(待更新) +publish: false +--- + + + + ## 前言 在 ES6 中,我们可以通过 ES6 引入的**类 Class** 来实现面向对象的编程(下一篇文章会讲到)。但是**在 ES6 之前,我们是通过构造函数和原型,来模拟类的实现机制**。 diff --git "a/04-JavaScript\345\237\272\347\241\200/31-\347\261\273\345\222\214\346\236\204\351\200\240\347\273\247\346\211\277\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" "b/04-JavaScript\345\237\272\347\241\200/31-\347\261\273\345\222\214\346\236\204\351\200\240\347\273\247\346\211\277\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" index e69de29b..93735484 100644 --- "a/04-JavaScript\345\237\272\347\241\200/31-\347\261\273\345\222\214\346\236\204\351\200\240\347\273\247\346\211\277\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" +++ "b/04-JavaScript\345\237\272\347\241\200/31-\347\261\273\345\222\214\346\236\204\351\200\240\347\273\247\346\211\277\357\274\210\345\276\205\346\233\264\346\226\260\357\274\211.md" @@ -0,0 +1,8 @@ +--- +title: 31-类和构造继承(待更新) +publish: false +--- + + + + diff --git "a/04-JavaScript\345\237\272\347\241\200/32-\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" "b/04-JavaScript\345\237\272\347\241\200/32-\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" index 7d9c1309..f0be6c20 100644 --- "a/04-JavaScript\345\237\272\347\241\200/32-\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" +++ "b/04-JavaScript\345\237\272\347\241\200/32-\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" @@ -1,3 +1,11 @@ +--- +title: 32-正则表达式 +publish: true +--- + + + + ## 正则表达式简介 diff --git "a/04-JavaScript\345\237\272\347\241\200/33-\344\272\213\344\273\266\347\256\200\344\273\213.md" "b/04-JavaScript\345\237\272\347\241\200/33-\344\272\213\344\273\266\347\256\200\344\273\213.md" index 4f8d2a9e..0367caec 100644 --- "a/04-JavaScript\345\237\272\347\241\200/33-\344\272\213\344\273\266\347\256\200\344\273\213.md" +++ "b/04-JavaScript\345\237\272\347\241\200/33-\344\272\213\344\273\266\347\256\200\344\273\213.md" @@ -1,7 +1,13 @@ +--- +title: 33-事件简介 +publish: true +--- + + + + -> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8366012.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 -> 以下是正文。 ## 事件简介 diff --git "a/04-JavaScript\345\237\272\347\241\200/34-DOM\347\256\200\344\273\213\345\222\214DOM\346\223\215\344\275\234.md" "b/04-JavaScript\345\237\272\347\241\200/34-DOM\347\256\200\344\273\213\345\222\214DOM\346\223\215\344\275\234.md" index 882fedf1..5abcc4d7 100644 --- "a/04-JavaScript\345\237\272\347\241\200/34-DOM\347\256\200\344\273\213\345\222\214DOM\346\223\215\344\275\234.md" +++ "b/04-JavaScript\345\237\272\347\241\200/34-DOM\347\256\200\344\273\213\345\222\214DOM\346\223\215\344\275\234.md" @@ -1,3 +1,11 @@ +--- +title: 34-DOM简介和DOM操作 +publish: true +--- + + + + ## 常见概念 diff --git "a/04-JavaScript\345\237\272\347\241\200/35-\351\200\232\350\277\207style\345\257\271\350\261\241\350\216\267\345\217\226\345\222\214\350\256\276\347\275\256\350\241\214\345\206\205\346\240\267\345\274\217.md" "b/04-JavaScript\345\237\272\347\241\200/35-\351\200\232\350\277\207style\345\257\271\350\261\241\350\216\267\345\217\226\345\222\214\350\256\276\347\275\256\350\241\214\345\206\205\346\240\267\345\274\217.md" index 663d8bba..bc074530 100644 --- "a/04-JavaScript\345\237\272\347\241\200/35-\351\200\232\350\277\207style\345\257\271\350\261\241\350\216\267\345\217\226\345\222\214\350\256\276\347\275\256\350\241\214\345\206\205\346\240\267\345\274\217.md" +++ "b/04-JavaScript\345\237\272\347\241\200/35-\351\200\232\350\277\207style\345\257\271\350\261\241\350\216\267\345\217\226\345\222\214\350\256\276\347\275\256\350\241\214\345\206\205\346\240\267\345\274\217.md" @@ -1,3 +1,11 @@ +--- +title: 35-通过style对象获取和设置行内样式 +publish: true +--- + + + + ## style属性的获取和修改 diff --git "a/04-JavaScript\345\237\272\347\241\200/36-offset\347\233\270\345\205\263\345\261\236\346\200\247\345\222\214\345\214\200\351\200\237\345\212\250\347\224\273(\345\220\253\350\275\256\346\222\255\345\233\276\347\232\204\345\256\236\347\216\260).md" "b/04-JavaScript\345\237\272\347\241\200/36-offset\347\233\270\345\205\263\345\261\236\346\200\247\345\222\214\345\214\200\351\200\237\345\212\250\347\224\273(\345\220\253\350\275\256\346\222\255\345\233\276\347\232\204\345\256\236\347\216\260).md" index 1b975645..452bd3fc 100644 --- "a/04-JavaScript\345\237\272\347\241\200/36-offset\347\233\270\345\205\263\345\261\236\346\200\247\345\222\214\345\214\200\351\200\237\345\212\250\347\224\273(\345\220\253\350\275\256\346\222\255\345\233\276\347\232\204\345\256\236\347\216\260).md" +++ "b/04-JavaScript\345\237\272\347\241\200/36-offset\347\233\270\345\205\263\345\261\236\346\200\247\345\222\214\345\214\200\351\200\237\345\212\250\347\224\273(\345\220\253\350\275\256\346\222\255\345\233\276\347\232\204\345\256\236\347\216\260).md" @@ -1,3 +1,11 @@ +--- +title: 36-offset相关属性和匀速动画(含轮播图的实现) +publish: true +--- + + + + ## 前言 diff --git "a/04-JavaScript\345\237\272\347\241\200/37-scroll\347\233\270\345\205\263\345\261\236\346\200\247\345\222\214\347\274\223\345\212\250\345\212\250\347\224\273.md" "b/04-JavaScript\345\237\272\347\241\200/37-scroll\347\233\270\345\205\263\345\261\236\346\200\247\345\222\214\347\274\223\345\212\250\345\212\250\347\224\273.md" index 4e129fca..5b3b2554 100644 --- "a/04-JavaScript\345\237\272\347\241\200/37-scroll\347\233\270\345\205\263\345\261\236\346\200\247\345\222\214\347\274\223\345\212\250\345\212\250\347\224\273.md" +++ "b/04-JavaScript\345\237\272\347\241\200/37-scroll\347\233\270\345\205\263\345\261\236\346\200\247\345\222\214\347\274\223\345\212\250\345\212\250\347\224\273.md" @@ -1,3 +1,11 @@ +--- +title: 37-scroll相关属性和缓动动画 +publish: true +--- + + + + ## scroll 相关属性 diff --git "a/04-JavaScript\345\237\272\347\241\200/38-client(\345\217\257\350\247\206\345\214\272)\347\233\270\345\205\263\345\261\236\346\200\247.md" "b/04-JavaScript\345\237\272\347\241\200/38-client(\345\217\257\350\247\206\345\214\272)\347\233\270\345\205\263\345\261\236\346\200\247.md" index aaacb32a..462360c6 100644 --- "a/04-JavaScript\345\237\272\347\241\200/38-client(\345\217\257\350\247\206\345\214\272)\347\233\270\345\205\263\345\261\236\346\200\247.md" +++ "b/04-JavaScript\345\237\272\347\241\200/38-client(\345\217\257\350\247\206\345\214\272)\347\233\270\345\205\263\345\261\236\346\200\247.md" @@ -1,3 +1,11 @@ +--- +title: 38-client(可视区)相关属性 +publish: true +--- + + + + diff --git "a/04-JavaScript\345\237\272\347\241\200/39-\344\272\213\344\273\266\347\232\204\347\273\221\345\256\232\345\222\214\344\272\213\344\273\266\345\257\271\350\261\241Event.md" "b/04-JavaScript\345\237\272\347\241\200/39-\344\272\213\344\273\266\347\232\204\347\273\221\345\256\232\345\222\214\344\272\213\344\273\266\345\257\271\350\261\241Event.md" index 5df4787c..9e7b3513 100644 --- "a/04-JavaScript\345\237\272\347\241\200/39-\344\272\213\344\273\266\347\232\204\347\273\221\345\256\232\345\222\214\344\272\213\344\273\266\345\257\271\350\261\241Event.md" +++ "b/04-JavaScript\345\237\272\347\241\200/39-\344\272\213\344\273\266\347\232\204\347\273\221\345\256\232\345\222\214\344\272\213\344\273\266\345\257\271\350\261\241Event.md" @@ -1,3 +1,11 @@ +--- +title: 39-事件的绑定和事件对象Event +publish: true +--- + + + + ## 绑定事件的两种方式/DOM事件的级别 diff --git "a/04-JavaScript\345\237\272\347\241\200/40-\344\272\213\344\273\266\347\232\204\344\274\240\346\222\255\345\222\214\344\272\213\344\273\266\345\206\222\346\263\241.md" "b/04-JavaScript\345\237\272\347\241\200/40-\344\272\213\344\273\266\347\232\204\344\274\240\346\222\255\345\222\214\344\272\213\344\273\266\345\206\222\346\263\241.md" index 86a275d8..c94c795a 100644 --- "a/04-JavaScript\345\237\272\347\241\200/40-\344\272\213\344\273\266\347\232\204\344\274\240\346\222\255\345\222\214\344\272\213\344\273\266\345\206\222\346\263\241.md" +++ "b/04-JavaScript\345\237\272\347\241\200/40-\344\272\213\344\273\266\347\232\204\344\274\240\346\222\255\345\222\214\344\272\213\344\273\266\345\206\222\346\263\241.md" @@ -1,3 +1,11 @@ +--- +title: 40-事件的传播和事件冒泡 +publish: true +--- + + + + ## DOM事件流 diff --git "a/04-JavaScript\345\237\272\347\241\200/41-\344\272\213\344\273\266\345\247\224\346\211\230.md" "b/04-JavaScript\345\237\272\347\241\200/41-\344\272\213\344\273\266\345\247\224\346\211\230.md" index ecde81bb..41d678eb 100644 --- "a/04-JavaScript\345\237\272\347\241\200/41-\344\272\213\344\273\266\345\247\224\346\211\230.md" +++ "b/04-JavaScript\345\237\272\347\241\200/41-\344\272\213\344\273\266\345\247\224\346\211\230.md" @@ -1,3 +1,11 @@ +--- +title: 41-事件委托 +publish: true +--- + + + + ## 事件委托 diff --git "a/04-JavaScript\345\237\272\347\241\200/42-\351\224\256\347\233\230\344\272\213\344\273\266.md" "b/04-JavaScript\345\237\272\347\241\200/42-\351\224\256\347\233\230\344\272\213\344\273\266.md" index a719a995..8f450737 100644 --- "a/04-JavaScript\345\237\272\347\241\200/42-\351\224\256\347\233\230\344\272\213\344\273\266.md" +++ "b/04-JavaScript\345\237\272\347\241\200/42-\351\224\256\347\233\230\344\272\213\344\273\266.md" @@ -1,3 +1,11 @@ +--- +title: 42-键盘事件 +publish: true +--- + + + + ## 鼠标的拖拽事件 diff --git "a/04-JavaScript\345\237\272\347\241\200/43-BOM\347\256\200\344\273\213\345\222\214navigator.userAgent&History&Location.md" "b/04-JavaScript\345\237\272\347\241\200/43-BOM\347\256\200\344\273\213\345\222\214navigator.userAgent&History&Location.md" index f4472125..e37ab6e1 100644 --- "a/04-JavaScript\345\237\272\347\241\200/43-BOM\347\256\200\344\273\213\345\222\214navigator.userAgent&History&Location.md" +++ "b/04-JavaScript\345\237\272\347\241\200/43-BOM\347\256\200\344\273\213\345\222\214navigator.userAgent&History&Location.md" @@ -1,3 +1,11 @@ +--- +title: 43-BOM简介和navigator.userAgent&History&Location +publish: true +--- + + + + ## 常见概念 diff --git "a/04-JavaScript\345\237\272\347\241\200/44-\345\256\232\346\227\266\345\231\250.md" "b/04-JavaScript\345\237\272\347\241\200/44-\345\256\232\346\227\266\345\231\250.md" index 2583f3a5..8e4d94c6 100644 --- "a/04-JavaScript\345\237\272\347\241\200/44-\345\256\232\346\227\266\345\231\250.md" +++ "b/04-JavaScript\345\237\272\347\241\200/44-\345\256\232\346\227\266\345\231\250.md" @@ -1,3 +1,11 @@ +--- +title: 44-定时器 +publish: true +--- + + + + ## 定时器的常见方法 diff --git "a/04-JavaScript\345\237\272\347\241\200/45-jQuery\347\232\204\344\273\213\347\273\215\345\222\214\351\200\211\346\213\251\345\231\250.md" "b/04-JavaScript\345\237\272\347\241\200/45-jQuery\347\232\204\344\273\213\347\273\215\345\222\214\351\200\211\346\213\251\345\231\250.md" index 58f93354..23065965 100644 --- "a/04-JavaScript\345\237\272\347\241\200/45-jQuery\347\232\204\344\273\213\347\273\215\345\222\214\351\200\211\346\213\251\345\231\250.md" +++ "b/04-JavaScript\345\237\272\347\241\200/45-jQuery\347\232\204\344\273\213\347\273\215\345\222\214\351\200\211\346\213\251\345\231\250.md" @@ -1,8 +1,14 @@ +--- +title: 45-jQuery的介绍和选择器 +publish: true +--- + + + + -> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8414627.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 -> 以下是正文。 diff --git "a/04-JavaScript\345\237\272\347\241\200/46-jQuery\345\212\250\347\224\273\350\257\246\350\247\243.md" "b/04-JavaScript\345\237\272\347\241\200/46-jQuery\345\212\250\347\224\273\350\257\246\350\247\243.md" index 953f59e3..7d4a6e3a 100644 --- "a/04-JavaScript\345\237\272\347\241\200/46-jQuery\345\212\250\347\224\273\350\257\246\350\247\243.md" +++ "b/04-JavaScript\345\237\272\347\241\200/46-jQuery\345\212\250\347\224\273\350\257\246\350\247\243.md" @@ -1,8 +1,14 @@ +--- +title: 46-jQuery动画详解 +publish: true +--- + + + + -> 本文最初发表于[博客园](),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 -> 以下是正文。 ## 前言 diff --git "a/04-JavaScript\345\237\272\347\241\200/47-jQuery\346\223\215\344\275\234DOM.md" "b/04-JavaScript\345\237\272\347\241\200/47-jQuery\346\223\215\344\275\234DOM.md" index aebb6c84..3fe65adf 100644 --- "a/04-JavaScript\345\237\272\347\241\200/47-jQuery\346\223\215\344\275\234DOM.md" +++ "b/04-JavaScript\345\237\272\347\241\200/47-jQuery\346\223\215\344\275\234DOM.md" @@ -1,3 +1,11 @@ +--- +title: 47-jQuery操作DOM +publish: true +--- + + + + diff --git "a/04-JavaScript\345\237\272\347\241\200/48-jQuery\347\232\204\344\272\213\344\273\266\346\234\272\345\210\266\345\222\214\345\205\266\344\273\226\347\237\245\350\257\206.md" "b/04-JavaScript\345\237\272\347\241\200/48-jQuery\347\232\204\344\272\213\344\273\266\346\234\272\345\210\266\345\222\214\345\205\266\344\273\226\347\237\245\350\257\206.md" index be037d49..c65d8493 100644 --- "a/04-JavaScript\345\237\272\347\241\200/48-jQuery\347\232\204\344\272\213\344\273\266\346\234\272\345\210\266\345\222\214\345\205\266\344\273\226\347\237\245\350\257\206.md" +++ "b/04-JavaScript\345\237\272\347\241\200/48-jQuery\347\232\204\344\272\213\344\273\266\346\234\272\345\210\266\345\222\214\345\205\266\344\273\226\347\237\245\350\257\206.md" @@ -1,3 +1,11 @@ +--- +title: 48-jQuery的事件机制和其他知识 +publish: true +--- + + + + ## jQuery 设置宽度和高度 diff --git "a/04-JavaScript\345\237\272\347\241\200/49-Zepto\345\205\245\351\227\250.md" "b/04-JavaScript\345\237\272\347\241\200/49-Zepto\345\205\245\351\227\250.md" index df0ad13a..99f84cb5 100644 --- "a/04-JavaScript\345\237\272\347\241\200/49-Zepto\345\205\245\351\227\250.md" +++ "b/04-JavaScript\345\237\272\347\241\200/49-Zepto\345\205\245\351\227\250.md" @@ -1,3 +1,11 @@ +--- +title: 49-Zepto入门 +publish: true +--- + + + + diff --git "a/04-JavaScript\345\237\272\347\241\200/BOM\347\232\204\345\270\270\350\247\201\345\206\205\347\275\256\346\226\271\346\263\225\345\222\214\345\206\205\347\275\256\345\257\271\350\261\241.md" "b/04-JavaScript\345\237\272\347\241\200/BOM\347\232\204\345\270\270\350\247\201\345\206\205\347\275\256\346\226\271\346\263\225\345\222\214\345\206\205\347\275\256\345\257\271\350\261\241.md" index bc338692..10d5d54a 100644 --- "a/04-JavaScript\345\237\272\347\241\200/BOM\347\232\204\345\270\270\350\247\201\345\206\205\347\275\256\346\226\271\346\263\225\345\222\214\345\206\205\347\275\256\345\257\271\350\261\241.md" +++ "b/04-JavaScript\345\237\272\347\241\200/BOM\347\232\204\345\270\270\350\247\201\345\206\205\347\275\256\346\226\271\346\263\225\345\222\214\345\206\205\347\275\256\345\257\271\350\261\241.md" @@ -1,3 +1,9 @@ +--- +publish: false +--- + + + > 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8401662.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 diff --git "a/04-JavaScript\345\237\272\347\241\200/\345\216\237\345\236\213\345\257\271\350\261\241.md" "b/04-JavaScript\345\237\272\347\241\200/\345\216\237\345\236\213\345\257\271\350\261\241.md" index 66a29191..407084b8 100644 --- "a/04-JavaScript\345\237\272\347\241\200/\345\216\237\345\236\213\345\257\271\350\261\241.md" +++ "b/04-JavaScript\345\237\272\347\241\200/\345\216\237\345\236\213\345\257\271\350\261\241.md" @@ -1,3 +1,9 @@ +--- +publish: false +--- + + + > 在看本文之前,我们可以先复习上一篇文章:《03-JavaScript基础/12-对象的创建&构造函数.md》 diff --git "a/04-JavaScript\345\237\272\347\241\200/\345\216\237\345\236\213\351\223\276.md" "b/04-JavaScript\345\237\272\347\241\200/\345\216\237\345\236\213\351\223\276.md" index 679cce39..be1840bd 100644 --- "a/04-JavaScript\345\237\272\347\241\200/\345\216\237\345\236\213\351\223\276.md" +++ "b/04-JavaScript\345\237\272\347\241\200/\345\216\237\345\236\213\351\223\276.md" @@ -1,3 +1,7 @@ +--- +publish: false +--- + ## 常见概念 diff --git "a/04-JavaScript\345\237\272\347\241\200/\345\270\270\350\247\201\344\273\243\347\240\201\350\247\243\350\257\273.md" "b/04-JavaScript\345\237\272\347\241\200/\345\270\270\350\247\201\344\273\243\347\240\201\350\247\243\350\257\273.md" index 7ff80028..3c34d40c 100644 --- "a/04-JavaScript\345\237\272\347\241\200/\345\270\270\350\247\201\344\273\243\347\240\201\350\247\243\350\257\273.md" +++ "b/04-JavaScript\345\237\272\347\241\200/\345\270\270\350\247\201\344\273\243\347\240\201\350\247\243\350\257\273.md" @@ -1,3 +1,7 @@ +--- +publish: false +--- + ### `callback && callback()`的含义 @@ -14,13 +18,13 @@ callback && callback() ```javascript function foo(callback) { { - // do something + // do something } - callback && callback() // 不传 callback 参数,则不会执行 callback() 函数 + callback && callback() // 不传 callback 参数,则不会执行 callback() 函数 } -foo(); // 只执行do something中的代码 -foo(callback);//callback是另一个函数,将此函数传入 foo,将会执行callback() +foo(); // 只执行do something中的代码 +foo(callback);//callback是另一个函数,将此函数传入 foo,将会执行callback() ``` diff --git "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/01-ES6\347\232\204\344\273\213\347\273\215\345\222\214\347\216\257\345\242\203\351\205\215\347\275\256.md" "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/01-ES6\347\232\204\344\273\213\347\273\215\345\222\214\347\216\257\345\242\203\351\205\215\347\275\256.md" index 8166cff4..24e1b1b8 100644 --- "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/01-ES6\347\232\204\344\273\213\347\273\215\345\222\214\347\216\257\345\242\203\351\205\215\347\275\256.md" +++ "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/01-ES6\347\232\204\344\273\213\347\273\215\345\222\214\347\216\257\345\242\203\351\205\215\347\275\256.md" @@ -1,3 +1,10 @@ +--- +title: 01-ES6的介绍和环境配置 +publish: true +--- + + + ## 前言 ### ECMAScript 简介 diff --git "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/02-ES5\344\270\255\347\232\204\344\270\245\346\240\274\346\250\241\345\274\217.md" "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/02-ES5\344\270\255\347\232\204\344\270\245\346\240\274\346\250\241\345\274\217.md" index 1770fc16..c99a114b 100644 --- "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/02-ES5\344\270\255\347\232\204\344\270\245\346\240\274\346\250\241\345\274\217.md" +++ "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/02-ES5\344\270\255\347\232\204\344\270\245\346\240\274\346\250\241\345\274\217.md" @@ -1,3 +1,10 @@ +--- +title: 02-ES5中的严格模式 +publish: true +--- + + + diff --git "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/03-ES5\344\270\255\347\232\204\344\270\200\344\272\233\346\211\251\345\261\225.md" "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/03-ES5\344\270\255\347\232\204\344\270\200\344\272\233\346\211\251\345\261\225.md" index 95a87956..525c66e0 100644 --- "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/03-ES5\344\270\255\347\232\204\344\270\200\344\272\233\346\211\251\345\261\225.md" +++ "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/03-ES5\344\270\255\347\232\204\344\270\200\344\272\233\346\211\251\345\261\225.md" @@ -1,3 +1,10 @@ +--- +title: 03-ES5中的一些扩展 +publish: true +--- + + + ## JSON 对象 diff --git "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/04-ES6\357\274\232\345\217\230\351\207\217 let\343\200\201const \345\222\214\345\235\227\347\272\247\344\275\234\347\224\250\345\237\237.md" "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/04-ES6\357\274\232\345\217\230\351\207\217 let\343\200\201const \345\222\214\345\235\227\347\272\247\344\275\234\347\224\250\345\237\237.md" index 274dd6f9..7fba763f 100644 --- "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/04-ES6\357\274\232\345\217\230\351\207\217 let\343\200\201const \345\222\214\345\235\227\347\272\247\344\275\234\347\224\250\345\237\237.md" +++ "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/04-ES6\357\274\232\345\217\230\351\207\217 let\343\200\201const \345\222\214\345\235\227\347\272\247\344\275\234\347\224\250\345\237\237.md" @@ -1,3 +1,10 @@ +--- +title: 04-ES6:变量 let、const 和块级作用域 +publish: true +--- + + + ## ES6 的变量声明 ES5 中,使用 `var` 定义**全局变量**( var 是 variable 的简写)。 diff --git "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/05-ES6\357\274\232\345\217\230\351\207\217\347\232\204\350\247\243\346\236\204\350\265\213\345\200\274.md" "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/05-ES6\357\274\232\345\217\230\351\207\217\347\232\204\350\247\243\346\236\204\350\265\213\345\200\274.md" index 4de97526..9b877318 100644 --- "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/05-ES6\357\274\232\345\217\230\351\207\217\347\232\204\350\247\243\346\236\204\350\265\213\345\200\274.md" +++ "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/05-ES6\357\274\232\345\217\230\351\207\217\347\232\204\350\247\243\346\236\204\350\265\213\345\200\274.md" @@ -1,3 +1,10 @@ +--- +title: 05-ES6:变量的解构赋值 +publish: true +--- + + + ## 解构赋值的概念 **解构赋值**:ES6 允许我们,按照一一对应的方式,从数组或者对象中**提取值**,再将提取出来的值赋值给变量。 diff --git "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/06-ES6\357\274\232\347\256\255\345\244\264\345\207\275\346\225\260.md" "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/06-ES6\357\274\232\347\256\255\345\244\264\345\207\275\346\225\260.md" index 81ac7f0f..6c6684b1 100644 --- "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/06-ES6\357\274\232\347\256\255\345\244\264\345\207\275\346\225\260.md" +++ "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/06-ES6\357\274\232\347\256\255\345\244\264\345\207\275\346\225\260.md" @@ -1,3 +1,10 @@ +--- +title: 06-ES6:箭头函数 +publish: true +--- + + + ## 前言 ES6 在**函数扩展**方面,新增了很多特性。例如: diff --git "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/07-\345\211\251\344\275\231\345\217\202\346\225\260\345\222\214\346\211\251\345\261\225\350\277\220\347\256\227\347\254\246.md" "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/07-\345\211\251\344\275\231\345\217\202\346\225\260\345\222\214\346\211\251\345\261\225\350\277\220\347\256\227\347\254\246.md" index 1187b1e0..45b58770 100644 --- "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/07-\345\211\251\344\275\231\345\217\202\346\225\260\345\222\214\346\211\251\345\261\225\350\277\220\347\256\227\347\254\246.md" +++ "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/07-\345\211\251\344\275\231\345\217\202\346\225\260\345\222\214\346\211\251\345\261\225\350\277\220\347\256\227\347\254\246.md" @@ -1,3 +1,10 @@ +--- +title: 07-剩余参数和扩展运算符 +publish: true +--- + + + ## 剩余参数 **剩余参数**允许我们将不确定数量的**剩余的元素**放到一个**数组**中。 diff --git "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/08-\345\255\227\347\254\246\344\270\262\343\200\201\346\225\260\347\273\204\343\200\201\345\257\271\350\261\241\347\232\204\346\211\251\345\261\225.md" "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/08-\345\255\227\347\254\246\344\270\262\343\200\201\346\225\260\347\273\204\343\200\201\345\257\271\350\261\241\347\232\204\346\211\251\345\261\225.md" index deca8c70..dc90170f 100644 --- "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/08-\345\255\227\347\254\246\344\270\262\343\200\201\346\225\260\347\273\204\343\200\201\345\257\271\350\261\241\347\232\204\346\211\251\345\261\225.md" +++ "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/08-\345\255\227\347\254\246\344\270\262\343\200\201\346\225\260\347\273\204\343\200\201\345\257\271\350\261\241\347\232\204\346\211\251\345\261\225.md" @@ -1,3 +1,10 @@ +--- +title: 08-字符串、数组、对象的扩展 +publish: true +--- + + + ## 字符串的扩展 > 下面提到的字符串的几个方法,更详细的内容,可以看《04-JavaScript 基础/内置对象 String:字符串的常见方法.md》。 diff --git "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/09-\345\206\205\347\275\256\345\257\271\350\261\241\346\211\251\345\261\225\357\274\232Set\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/09-\345\206\205\347\275\256\345\257\271\350\261\241\346\211\251\345\261\225\357\274\232Set\346\225\260\346\215\256\347\273\223\346\236\204.md" index f29c86ec..61bee39c 100644 --- "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/09-\345\206\205\347\275\256\345\257\271\350\261\241\346\211\251\345\261\225\357\274\232Set\346\225\260\346\215\256\347\273\223\346\236\204.md" +++ "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/09-\345\206\205\347\275\256\345\257\271\350\261\241\346\211\251\345\261\225\357\274\232Set\346\225\260\346\215\256\347\273\223\346\236\204.md" @@ -1,3 +1,10 @@ +--- +title: 09-内置对象扩展:Set数据结构 +publish: true +--- + + + ## Set 数据结构 ### Set 数据结构的介绍 diff --git "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/ES6\357\274\232Symbol.md" "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/ES6\357\274\232Symbol.md" index 2196b01b..5c7b8eac 100644 --- "a/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/ES6\357\274\232Symbol.md" +++ "b/05-JavaScript\345\237\272\347\241\200\357\274\232ES6\350\257\255\346\263\225/ES6\357\274\232Symbol.md" @@ -1,3 +1,7 @@ +--- +publish: false +--- + ## Symbol diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/00-\346\234\215\345\212\241\345\231\250\345\210\206\347\261\273\345\217\212PHP\345\205\245\351\227\250.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/00-\346\234\215\345\212\241\345\231\250\345\210\206\347\261\273\345\217\212PHP\345\205\245\351\227\250.md" index 4f6031ef..d1cb634a 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/00-\346\234\215\345\212\241\345\231\250\345\210\206\347\261\273\345\217\212PHP\345\205\245\351\227\250.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/00-\346\234\215\345\212\241\345\231\250\345\210\206\347\261\273\345\217\212PHP\345\205\245\351\227\250.md" @@ -1,3 +1,12 @@ +--- +title: 00-服务器分类及PHP入门 +publish: true +--- + + + + + ## C/S架构和B/S架构 diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/01-\345\215\225\347\272\277\347\250\213\345\222\214\345\274\202\346\255\245.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/01-\345\215\225\347\272\277\347\250\213\345\222\214\345\274\202\346\255\245.md" index 3282d90a..4cd036c3 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/01-\345\215\225\347\272\277\347\250\213\345\222\214\345\274\202\346\255\245.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/01-\345\215\225\347\272\277\347\250\213\345\222\214\345\274\202\346\255\245.md" @@ -1,3 +1,11 @@ +--- +title: 01-单线程和异步 +publish: true +--- + + + + ## 单线程 JavaScript 语言和执行环境是**单线程**。即同一时间,只能处理一个任务。 diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/02-Ajax\345\205\245\351\227\250\345\222\214\345\217\221\351\200\201http\350\257\267\346\261\202.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/02-Ajax\345\205\245\351\227\250\345\222\214\345\217\221\351\200\201http\350\257\267\346\261\202.md" index c5759093..3f737cc3 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/02-Ajax\345\205\245\351\227\250\345\222\214\345\217\221\351\200\201http\350\257\267\346\261\202.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/02-Ajax\345\205\245\351\227\250\345\222\214\345\217\221\351\200\201http\350\257\267\346\261\202.md" @@ -1,3 +1,11 @@ +--- +title: 02-Ajax入门和发送http请求 +publish: true +--- + + + + ## 同步和异步回顾 ### 同步和异步的简单理解 diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/03-Ajax\344\274\240\350\276\223json\345\222\214XML.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/03-Ajax\344\274\240\350\276\223json\345\222\214XML.md" index 4963dc43..2a22a58c 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/03-Ajax\344\274\240\350\276\223json\345\222\214XML.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/03-Ajax\344\274\240\350\276\223json\345\222\214XML.md" @@ -1,3 +1,11 @@ +--- +title: 03-Ajax传输json和XML +publish: true +--- + + + + ## Ajax 传输 JSON diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/04-\345\220\214\346\272\220\345\222\214\350\267\250\345\237\237.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/04-\345\220\214\346\272\220\345\222\214\350\267\250\345\237\237.md" index bb4baf08..a3551723 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/04-\345\220\214\346\272\220\345\222\214\350\267\250\345\237\237.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/04-\345\220\214\346\272\220\345\222\214\350\267\250\345\237\237.md" @@ -1,3 +1,11 @@ +--- +title: 04-同源和跨域 +publish: true +--- + + + + ## 同源和跨域 diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/05-Promise\345\205\245\351\227\250\350\257\246\350\247\243.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/05-Promise\345\205\245\351\227\250\350\257\246\350\247\243.md" index 929dda74..2c962f05 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/05-Promise\345\205\245\351\227\250\350\257\246\350\247\243.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/05-Promise\345\205\245\351\227\250\350\257\246\350\247\243.md" @@ -1,3 +1,11 @@ +--- +title: 05-Promise入门详解 +publish: true +--- + + + + ## 为什么需要 Promise? 我们在前面的文章《JavaScript 基础:异步编程和 Ajax/单线程和异步》中讲过,Javascript 是⼀⻔单线程语⾔。早期我们解决异步场景时,⼤部分情况都是通过回调函数来进⾏。 diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/06-Promise\347\232\204\351\223\276\345\274\217\350\260\203\347\224\250.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/06-Promise\347\232\204\351\223\276\345\274\217\350\260\203\347\224\250.md" index e9d491fc..69e39801 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/06-Promise\347\232\204\351\223\276\345\274\217\350\260\203\347\224\250.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/06-Promise\347\232\204\351\223\276\345\274\217\350\260\203\347\224\250.md" @@ -1,3 +1,11 @@ +--- +title: 06-Promise的链式调用 +publish: true +--- + + + + ## Promise 的链式调用:处理多次 Ajax 请求【重要】 实际开发中,我们经常需要同时请求多个接口。比如说:在请求完`接口1`的数据`data1`之后,需要根据`data1`的数据,继续请求接口 2,获取`data2`;然后根据`data2`的数据,继续请求接口 3。 diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/07-Promise\347\232\204\351\235\231\346\200\201\346\226\271\346\263\225.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/07-Promise\347\232\204\351\235\231\346\200\201\346\226\271\346\263\225.md" index 93b34411..7e8b8e78 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/07-Promise\347\232\204\351\235\231\346\200\201\346\226\271\346\263\225.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/07-Promise\347\232\204\351\235\231\346\200\201\346\226\271\346\263\225.md" @@ -1,3 +1,11 @@ +--- +title: 07-Promise的静态方法 +publish: true +--- + + + + ## Promise 的常用 API 分类 ### Promise 的实例方法 @@ -227,12 +235,35 @@ imgArr.forEach((item) => { Promise.all(promiseArr).then((res) => { console.log('图片全部上传完成'); console.log('九张图片的url地址,组成的数组:' + res); +}).catch(res=> { + console.log('部分图片上传失败'); }); ``` +上方代码解释: + +1、只有九张图片都上传成功,才会走到 then。 + +2、按时间顺序来看,假设第一张图片上传成功,第二张图片上传失败,那么,最终的表现是: + +- 对于前端来说,九张图都会走到 reject;整体会走到 catch,不会走到 then。 + +- 对于后端来说,第一张图片会上传成功(因为写入DB是不可逆的),第二张图上传失败,剩下的七张图,会正常请求 upload img 接口。 + +3、**特别说明**: + +- 第一张图会成功调 upload 接口,并返回 imgUrl,但不会走到 resolve,因为要等其他八张图的执行结果,再决定是一起走 resolove 还是一起走 reject。 + +- 当执行 Promise.all() / Promise.race() / Promise.any() 的时候,**其实九张图的 upload img 请求都已经发出去了**。对于后端来说,是没有区别的(而且读写DB的操作不可逆),只是在前端的交互表现不同、走到 resolve / reject / then / catch 的时机不同而已。 + + 上面这个例子,在实际的项目开发中,经常遇到,属于高频需求,需要记住并理解。 -当然,实战开发中,在做多张图片上传时,可能是一张一张地单独上传,各自的上传进度相互独立。此时 `Promise.all`便不再适用,这就得具体需求具体分析了。 +4、**思维拓展**: + +- 拓展1:如果你希望九张图同时上传,并且想知道哪些图上传成功、哪些图上传失败,则可以这样做:**无论 upload img 接口请求成功与否,全都执行 reslove**。这样的话,最终一定会走到 then,然后再根据接口返回的结果判断九张图片的上传成功与否。 + +- 拓展2:实战开发中,在做多张图片上传时,可能是一张一张地单独上传,各自的上传操作相互独立。此时 `Promise.all`便不再适用,这就得具体需求具体分析了。 ## Promise.race() @@ -448,6 +479,11 @@ Promise.race([getImg(), timeout()]) 这个思路很巧妙。 +## Promise.any() + + + + ## 总结 Promise 不仅能解决嵌套异步任务的**回调地域**问题,也可做多个异步任务的**并发请求**,还可以进行舒适简洁的状态管理。 diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/08-Async Await\345\207\275\346\225\260\350\257\246\350\247\243.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/08-Async Await\345\207\275\346\225\260\350\257\246\350\247\243.md" index a331f7e6..686d5a78 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/08-Async Await\345\207\275\346\225\260\350\257\246\350\247\243.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/08-Async Await\345\207\275\346\225\260\350\257\246\350\247\243.md" @@ -1,3 +1,11 @@ +--- +title: 08-Async Await函数详解 +publish: true +--- + + + + ## async/await (异步函数)概述 diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/09-\345\256\217\344\273\273\345\212\241\345\222\214\345\276\256\344\273\273\345\212\241.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/09-\345\256\217\344\273\273\345\212\241\345\222\214\345\276\256\344\273\273\345\212\241.md" index 108f6a19..52c8576d 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/09-\345\256\217\344\273\273\345\212\241\345\222\214\345\276\256\344\273\273\345\212\241.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/09-\345\256\217\344\273\273\345\212\241\345\222\214\345\276\256\344\273\273\345\212\241.md" @@ -1,3 +1,12 @@ +--- +title: 09-宏任务和微任务 +publish: true +--- + + + + + ## 准备知识 - 在执行一个 Promise 对象的时候,当走完`resolve();`之后,就会立刻把 `.then()`里面的代码加入到**微任务队列**当中。 diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/\345\207\275\346\225\260\345\260\201\350\243\205-Ajax\345\217\221\351\200\201http\350\257\267\346\261\202\357\274\210get&post\357\274\211.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/\345\207\275\346\225\260\345\260\201\350\243\205-Ajax\345\217\221\351\200\201http\350\257\267\346\261\202\357\274\210get&post\357\274\211.md" index d027261a..3d3a9fc1 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/\345\207\275\346\225\260\345\260\201\350\243\205-Ajax\345\217\221\351\200\201http\350\257\267\346\261\202\357\274\210get&post\357\274\211.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/\345\207\275\346\225\260\345\260\201\350\243\205-Ajax\345\217\221\351\200\201http\350\257\267\346\261\202\357\274\210get&post\357\274\211.md" @@ -1,3 +1,11 @@ +--- +title: 函数封装-Ajax发送http请求(get&post) +publish: false +--- + + + + diff --git "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/\346\250\241\346\235\277\345\274\225\346\223\216.md" "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/\346\250\241\346\235\277\345\274\225\346\223\216.md" index a32ffd4d..d78e39e9 100644 --- "a/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/\346\250\241\346\235\277\345\274\225\346\223\216.md" +++ "b/06-JavaScript\345\274\202\346\255\245\347\274\226\347\250\213\357\274\232Ajax\345\222\214Promise/\346\250\241\346\235\277\345\274\225\346\223\216.md" @@ -1,3 +1,11 @@ +--- +title: 认识Web和Web标准 +publish: false +--- + + + + ## 模版引擎 diff --git "a/07-JavaScript\350\277\233\351\230\266/01-var\343\200\201let\343\200\201const\347\232\204\345\214\272\345\210\253.md" "b/07-JavaScript\350\277\233\351\230\266/01-var\343\200\201let\343\200\201const\347\232\204\345\214\272\345\210\253.md" index 776d06a1..1093776e 100644 --- "a/07-JavaScript\350\277\233\351\230\266/01-var\343\200\201let\343\200\201const\347\232\204\345\214\272\345\210\253.md" +++ "b/07-JavaScript\350\277\233\351\230\266/01-var\343\200\201let\343\200\201const\347\232\204\345\214\272\345\210\253.md" @@ -1,3 +1,13 @@ +--- +title: 01-var、let、const的区别 +publish: true +--- + + + + + + ## var、let、const 的区别 ### 1、var 声明的变量会挂载在 window 对象上,而 let 和 const 声明的变量不会 diff --git "a/07-JavaScript\350\277\233\351\230\266/02-\346\225\260\346\215\256\347\232\204\350\265\213\345\200\274.md" "b/07-JavaScript\350\277\233\351\230\266/02-\346\225\260\346\215\256\347\232\204\350\265\213\345\200\274.md" index c21e2700..adeab3a2 100644 --- "a/07-JavaScript\350\277\233\351\230\266/02-\346\225\260\346\215\256\347\232\204\350\265\213\345\200\274.md" +++ "b/07-JavaScript\350\277\233\351\230\266/02-\346\225\260\346\215\256\347\232\204\350\265\213\345\200\274.md" @@ -1,3 +1,11 @@ +--- +title: 02-数据的赋值 +publish: true +--- + + + + ## 对象赋值 diff --git "a/07-JavaScript\350\277\233\351\230\266/03-\345\210\233\345\273\272\345\257\271\350\261\241\345\222\214\347\273\247\346\211\277.md" "b/07-JavaScript\350\277\233\351\230\266/03-\345\210\233\345\273\272\345\257\271\350\261\241\345\222\214\347\273\247\346\211\277.md" new file mode 100644 index 00000000..39ff6ba9 --- /dev/null +++ "b/07-JavaScript\350\277\233\351\230\266/03-\345\210\233\345\273\272\345\257\271\350\261\241\345\222\214\347\273\247\346\211\277.md" @@ -0,0 +1,237 @@ +--- +title: 03-创建对象和继承 +publish: true +--- + + + + + + + +## 创建对象的几种方式 + +### 通过Object + +```html + + + + + 01_Object构造函数模式 + + + + + + + +``` + + +### 方式二:对象字面量 + +```html + + + + + 02_对象字面量 + + + + + + +``` + + + +### 方式三:工厂模式 + +- 方式:通过工厂函数动态创建对象并返回。 + +返回一个对象的函数,就是**工厂函数**。 + +- 适用场景: 需要创建多个对象。 + +- 问题: 对象没有一个具体的类型,都是Object类型。 + +由于这个问题的存在,工厂模式用得不多。 + +```html + + + + + 03_工厂模式 + + + + + + + +``` + + + +### 方式四:自定义构造函数 + +```html + + + + + 04_自定义构造函数模式 + + + + + + + + +``` + + +方式四引入了继承。 + +## 继承的几种方式 + + +### 通过构造函数继承 + +在子类型构造函数中通用call()调用父类型构造函数 + + +### 原型链继承 + +子类型的原型为父类型的一个实例对象 + + + +### 组合继承 + + + diff --git "a/07-JavaScript\350\277\233\351\230\266/04-\344\275\234\347\224\250\345\237\237\345\222\214\351\227\255\345\214\205.md" "b/07-JavaScript\350\277\233\351\230\266/04-\344\275\234\347\224\250\345\237\237\345\222\214\351\227\255\345\214\205.md" new file mode 100644 index 00000000..f492dca6 --- /dev/null +++ "b/07-JavaScript\350\277\233\351\230\266/04-\344\275\234\347\224\250\345\237\237\345\222\214\351\227\255\345\214\205.md" @@ -0,0 +1,833 @@ +--- +title: 04-作用域和闭包 +publish: true +--- + + + + + + +## 前言 + +面试问题: + +- 说一下对变量提升的理解 + +- 说明this的几种不同的使用场景 + +- 创建10个``标签,点击的时候弹出来对应的序号 + +- 如何理解作用域 + +- 实际开发中闭包的应用 + +涉及到的知识点: + +- 执行上下文 + +- this + +- 作用域 + +- 作用域链 + +- 闭包 + + +## 执行上下文 + +执行上下文主要有两种情况: + +- 全局代码: 一段` + + + + + +``` + +理解: + +- 多个上下级关系的作用域形成的链, 它的方向是从下向上的(从内到外) + +- 查找变量时就是沿着作用域链来查找的 + +查找一个变量的查找规则: + +```javascript + var a = 1 + + function fn1() { + var b = 2 + + function fn2() { + var c = 3 + console.log(c) + console.log(b) + console.log(a) + console.log(d) + } + fn2() + } + fn1() +``` + + +- 在当前作用域下的执行上下文中查找对应的属性, 如果有直接返回, 否则进入2 + +- 在上一级作用域的执行上下文中查找对应的属性, 如果有直接返回, 否则进入3 + +- 再次执行2的相同操作, 直到全局作用域, 如果还找不到就抛出找不到的异常 + + +## 闭包 + +闭包就是能够读取其他函数内部数据(变量/函数)的函数。 + +只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。 + +上面这两句话,是阮一峰的文章里的,你不一定能理解,来看下面的讲解和举例。 + +### 如何产生闭包 + +**当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量或函数时, 就产生了闭包。** + +### 闭包到底是什么? + + +> 使用chrome调试查看 + + +- 理解一: 闭包是嵌套的内部函数(绝大部分人) + +- 理解二: 包含被引用变量 or 函数的对象(极少数人) + +注意: 闭包存在于嵌套的内部函数中。 + + +### 产生闭包的条件 + +- 1.函数嵌套 + +- 2.内部函数引用了外部函数的数据(变量/函数)。 + +来看看条件2: + +```javascript + function fn1() { + function fn2() { + + } + + return fn2; + } + + fn1(); +``` + +上面的代码不会产生闭包,因为内部函数fn2并没有引用外部函数fn1的变量。 + + +PS:还有一个条件是**外部函数被调用,内部函数被声明**。比如: + +```javascript + + function fn1() { + var a = 2 + var b = 'abc' + + function fn2() { //fn2内部函数被提前声明,就会产生闭包(不用调用内部函数) + console.log(a) + } + + } + + fn1(); + + function fn3() { + var a = 3 + var fun4 = function () { //fun4采用的是“函数表达式”创建的函数,此时内部函数的声明并没有提前 + console.log(a) + } + } + + fn3(); + +``` + + + + +## 常见的闭包 + +- 1. 将一个函数作为另一个函数的返回值 + +- 2. 将函数作为实参传递给另一个函数调用。 + +### 闭包1:将一个函数作为另一个函数的返回值 + +```javascript + function fn1() { + var a = 2 + + function fn2() { + a++ + console.log(a) + } + return fn2 + } + + var f = fn1(); //执行外部函数fn1,返回的是内部函数fn2 + f() // 3 //执行fn2 + f() // 4 //再次执行fn2 + +``` + + +当f()第二次执行的时候,a加1了,也就说明了:闭包里的数据没有消失,而是保存在了内存中。如果没有闭包,代码执行完倒数第三行后,变量a就消失了。 + +上面的代码中,虽然调用了内部函数两次,但是,闭包对象只创建了一个。 + +也就是说,要看闭包对象创建了一个,就看:**外部函数执行了几次**(与内部函数执行几次无关)。 + + +### 闭包2. 将函数作为实参传递给另一个函数调用 + + +```javascript + function showDelay(msg, time) { + setTimeout(function() { //这个function是闭包,因为是嵌套的子函数,而且引用了外部函数的变量msg + alert(msg) + }, time) + } + showDelay('atguigu', 2000) +``` + +上面的代码中,闭包是里面的function,因为它是嵌套的子函数,而且引用了外部函数的变量msg。 + + +## 闭包的作用 + +- 作用1. 使用函数内部的变量在函数执行完后, 仍然存活在内存中(延长了局部变量的生命周期) + +- 作用2. 让函数外部可以操作(读写)到函数内部的数据(变量/函数) + +我们让然拿这段代码来分析: + +```javascript + function fn1() { + var a = 2 + + function fn2() { + a++ + console.log(a) + } + return fn2; + } + + var f = fn1(); //执行外部函数fn1,返回的是内部函数fn2 + f() // 3 //执行fn2 + f() // 4 //再次执行fn2 + +``` + +**作用1分析**: + +上方代码中,外部函数fn1执行完毕后,变量a并没有立即消失,而是保存在内存当中。 + + +**作用2分析:** + +函数fn1中的变量a,是在fn1这个函数作用域内,因此外部无法访问。但是通过闭包,外部就可以操作到变量a。 + +达到的效果是:**外界看不到变量a,但可以操作a**。 + +比如上面达到的效果是:我看不到变量a,但是每次执行函数后,让a加1。当然,如果我真想看到a,我可以在fn2中将a返回即可。 + + + +回答几个问题: + +- 问题1. 函数执行完后, 函数内部声明的局部变量是否还存在? + +答案:一般是不存在, 存在于闭包中的变量才可能存在。 + +闭包能够一直存在的根本原因是`f`,因为`f`接收了`fn1()`,这个是闭包,闭包里有a。注意,此时,fn2并不存在了,但是里面的对象(即闭包)依然存在,因为用`f`接收了。 + + +- 问题2. 在函数外部能直接访问函数内部的局部变量吗? + +不能,但我们可以通过闭包让外部操作它。 + + +## 闭包的生命周期 + +1. 产生: 嵌套内部函数fn2被声明时就产生了(不是在调用) + +2. 死亡: 嵌套的内部函数成为垃圾对象时。(比如f = null,就可以让f成为垃圾对象。意思是,此时f不再引用闭包这个对象了) + + + +## 闭包的应用:定义具有特定功能的js模块 + +- 将所有的数据和功能都封装在一个函数内部(私有的),只向外暴露一个包含n个方法的对象或函数。 + +- 模块的使用者, 只需要通过模块暴露的对象调用方法来实现对应的功能。 + +### 方式一 + +(1)myModule.js:(定义一个模块,向外暴露多个函数,供外界调用) + +```javascript +function myModule() { + //私有数据 + var msg = 'Smyhvae Haha' + + //操作私有数据的函数 + function doSomething() { + console.log('doSomething() ' + msg.toUpperCase()); //字符串大写 + } + + function doOtherthing() { + console.log('doOtherthing() ' + msg.toLowerCase()) //字符串小写 + } + + //通过【对象字面量】的形式进行包裹,向外暴露多个函数 + return { + doSomething1: doSomething, + doOtherthing2: doOtherthing + } +} +``` + + +上方代码中,外界可以通过doSomething1和doOtherthing2来操作里面的数据,但不让外界看到。 + +(2)index.html: + +```html + + + + + 05_闭包的应用_自定义JS模块 + + + + + + + +``` + + +### 方式二 + +同样是实现方式一种的功能,这里我们采取另外一种方式。 + +(1)myModule2.js:(是一个立即执行的匿名函数) + +```javascript +(function () { + //私有数据 + var msg = 'Smyhvae Haha' + + //操作私有数据的函数 + function doSomething() { + console.log('doSomething() ' + msg.toUpperCase()) + } + + function doOtherthing() { + console.log('doOtherthing() ' + msg.toLowerCase()) + } + + //外部函数是即使运行的匿名函数,我们可以把两个方法直接传给window对象 + window.myModule = { + doSomething1: doSomething, + doOtherthing2: doOtherthing + } +})() +``` + + +(2)index.html: + +```html + + + + + 05_闭包的应用_自定义JS模块2 + + + + + + + + + + +``` + +上方两个文件中,我们在`myModule2.js`里直接把两个方法直接传递给window对象了。于是,在index.html中引入这个js文件后,会立即执行里面的匿名函数。在index.html中把myModule直接拿来用即可。 + +**总结:** + +当然,方式一和方式二对比后,我们更建议采用方式二,因为很方便。 + +但无论如何,两种方式都采用了闭包。 + + +## 闭包的缺点及解决 + +缺点:函数执行完后, 函数内的局部变量没有释放,占用内存时间会变长,容易造成内存泄露。 + + +解决:能不用闭包就不用,及时释放。比如: + +```javascript + f = null; // 让内部函数成为垃圾对象 -->回收闭包 +``` + +总而言之,你需要它,就是优点;你不需要它,就成了缺点。 + + +## 内存溢出和内存泄露 + +### 内存溢出 + +**内存溢出**:一种程序运行出现的错误。当程序运行**需要的内存**超过了剩余的内存时, 就出抛出内存溢出的错误。 + +代码举例: + +```javascript + var obj = {}; + for (var i = 0; i < 10000; i++) { + obj[i] = new Array(10000000); //把所有的数组内容都放到obj里保存,导致obj占用了很大的内存空间 + console.log("-----"); + } +``` + +### 内存泄漏 + +**内存泄漏**:**占用的内存**没有及时释放。 + +注意,内存泄露的次数积累多了,就容易导致内存溢出。 + +**常见的内存泄露**: + +- 1.意外的全局变量 + +- 2.没有及时清理的计时器或回调函数 + +- 3.闭包 + + +情况1举例: + +```javascript + // 意外的全局变量 + function fn() { + a = new Array(10000000); + console.log(a); + } + + fn(); +``` + +情况2举例: + +```javascript + // 没有及时清理的计时器或回调函数 + var intervalId = setInterval(function () { //启动循环定时器后不清理 + console.log('----') + }, 1000) + + // clearInterval(intervalId); //清理定时器 +``` + +情况3举例: + +```html + +``` + + + + + + + + + + + diff --git "a/07-JavaScript\350\277\233\351\230\266/05-call\343\200\201apply\343\200\201bind\347\232\204\345\214\272\345\210\253.md" "b/07-JavaScript\350\277\233\351\230\266/05-call\343\200\201apply\343\200\201bind\347\232\204\345\214\272\345\210\253.md" new file mode 100644 index 00000000..783c62d1 --- /dev/null +++ "b/07-JavaScript\350\277\233\351\230\266/05-call\343\200\201apply\343\200\201bind\347\232\204\345\214\272\345\210\253.md" @@ -0,0 +1,119 @@ +--- +title: 05-call、apply、bind的区别 +publish: true +--- + + + + + +## call()和apply() + +### 介绍 + +这两个方法都是函数对象的方法,需要通过函数对象来调用。 + +当函数调用call()和apply()时,函数都会立即**执行**。 + +- 都可以用来改变函数的this对象的指向。 + +- 第一个参数都是this要指向的对象(函数执行时,this将指向这个对象),后续参数用来传实参。 + +### 显式绑定this + +JS提供的绝大多数函数以及我们自己创建的所有函数,都可以使用call 和apply方法。 + +它们的第一个参数是一个对象。因为你可以直接指定 this 绑定的对象,因此我们称之为显式绑定。 + +例1: + +```javascript + function foo() { + console.log(this.a); + } + + var obj = { + a: 2 + }; + + // 将 this 指向 obj + foo.apply(obj); //打印结果:2 +``` + +### 第一个参数的传递 + +1、thisObj不传或者为null、undefined时,函数中的this会指向window对象(非严格模式)。 + +2、传递一个别的函数名时,函数中的this将指向这个**函数的引用**。 + +3、传递的值为数字、布尔值、字符串时,this会指向这些基本类型的包装对象Number、Boolean、String。 + +4、传递一个对象时,函数中的this则指向传递的这个对象。 + + +### call()和apply()的区别 + +call()和apply()方法都可以将实参在对象之后依次传递,但是apply()方法需要将实参封装到一个**数组**中统一传递(即使只有实参只有一个,也要放到数组中)。 + +比如针对下面这样的代码: + +```javascript + var persion1 = { + name: "小王", + gender: "男", + age: 24, + say: function (school, grade) { + alert(this.name + " , " + this.gender + " ,今年" + this.age + " ,在" + school + "上" + grade); + } + } + var person2 = { + name: "小红", + gender: "女", + age: 18 + } +``` + +如果是通过call的参数进行传参,是这样的: + +```javascript + persion1.say.call(persion2, "实验小学", "六年级"); +``` + +如果是通过apply的参数进行传参,是这样的: + +```javascript + persion1.say.apply(persion2, ["实验小学", "六年级"]); +``` + +看到区别了吗,call后面的实参与say方法中是一一对应的,而apply传实参时,要封装成一个数组,数组中的元素是和say方法中一一对应的,这就是两者最大的区别。 + +### call()和apply()的作用 + +- 改变this的指向 + +- 实现继承。Father.call(this) + +## bind() + +- 都能改变this的指向 + +- call()/apply()是**立即调用函数** + +- bind()是将函数返回,因此后面还需要加`()`才能调用。 + +bind()传参的方式与call()相同。 + +参考链接: + +- + +- + +- + +- [JS中改变this指向的方法](http://www.xiaoxiaohan.com/js/38.html) + + + + + diff --git "a/07-JavaScript\350\277\233\351\230\266/06-Promise\347\232\204\344\270\200\344\272\233\351\242\230\347\233\256.md" "b/07-JavaScript\350\277\233\351\230\266/06-Promise\347\232\204\344\270\200\344\272\233\351\242\230\347\233\256.md" new file mode 100644 index 00000000..1a1965a6 --- /dev/null +++ "b/07-JavaScript\350\277\233\351\230\266/06-Promise\347\232\204\344\270\200\344\272\233\351\242\230\347\233\256.md" @@ -0,0 +1,132 @@ +--- +title: 06-Promise的一些题目 +publish: true +--- + + + + +## Promise 的执行顺序 + +### 题目 1 + +代码举例: + +```js +const p = new Promise((resolve, reject) => { + console.log(1); +}); + +console.log(2); +``` + +打印结果: + +``` +1 +2 +``` + +我们需要注意的是:Promise 里的代码整体,其实是同步任务,会立即执行。 + +补充:上面的代码中,如果继续写`p.then()`,那么 `then()`里面是不会执行的。因为在定义 promise 的时候需要写 resolve,调用 promise 的时候才会执行 `then()`。 + +基于此,我们再来看下面这段代码: + +```js +const p = new Promise((resolve, reject) => { + console.log(1); + resolve(); +}); + +console.log(2); + +p.then((res) => { + console.log(3); +}); +``` + +打印结果: + +``` +1 +2 +3 +``` + +### 题目 2 + +代码举例: + +```js +// 封装 ajax 请求:传入回调函数 success 和 fail +function ajax(url, success, fail) { + var xmlhttp = new XMLHttpRequest(); + xmlhttp.open('GET', url); + xmlhttp.send(); + xmlhttp.onreadystatechange = function () { + if (xmlhttp.readyState === 4 && xmlhttp.status === 200) { + success(xmlhttp.responseText); + } else { + fail(new Error('接口请求失败')); + } + }; +} + +new Promise((resolve, reject) => { + ajax('a.json', (res) => { + console.log('a接口返回的内容:' + res); + resolve(); + }); +}) + .then((res) => { + console.log('a成功'); + new Promise((resolve, reject) => { + ajax('b.json', (res) => { + console.log('b接口返回的内容:' + res); + resolve(); + }); + }); + }) + .then((res) => { + // 因为上面在b接口的时候,并没有 return,也就是没有返回值。那么,这里的链式操作then,其实是针对一个空的 promise 对象进行then操作 + console.log('b成功'); + }); +``` + +打印结果: + +``` +a接口返回的内容 +a成功 +b成功 +b接口返回的内容 +``` + +### 题目 3 + +举例1: + +```js +new Promise((resolve, reject) => { + resolove(); + console.log('promise1'); // 代码1 +}).then(res => { + console.log('promise then)'; // 代码2:微任务 +}) + +console.log('千古壹号'); // 代码3 +``` + +打印结果: + +``` +promise1 +千古壹号 +promise then +``` + +代码解释:代码1是同步代码,所以最先执行。代码2是**微任务**里面的代码,所以要先等同步任务(代码3)先执行完。 + +当写完`resolove();`之后,就会立刻把 `.then()`里面的代码加入到微任务队列当中。 + diff --git "a/07-JavaScript\350\277\233\351\230\266/07-this.md" "b/07-JavaScript\350\277\233\351\230\266/07-this.md" new file mode 100644 index 00000000..ee12aca1 --- /dev/null +++ "b/07-JavaScript\350\277\233\351\230\266/07-this.md" @@ -0,0 +1,148 @@ +--- +title: 07-this +publish: true +--- + + + + + +## this + +### this的作用 + +- this可以帮我们简化很多代码。比如`xiaoming.name`、`xiaoming.age`可以直接写成`this.name`、`this.age`。 + +- 特别是当我们不知道一个对象是什么,或者这个对象没有名字但又很想调用它的时候,就会使用到this对象。 + +**举例:** + +- 遍历DOM对象,绑定click事件,调用当前点击的对象的id,而不是所有对象的id。 + +代码: + +```html + + + + + Document + + + + +
+
div0
+
div1
+
div2
+
div3
+
div4
+
+ + + + + +``` + + +点击其中的任何一个元素后,`i`的打印结果是5。你可能会觉得很惊讶。我们来解释一下: + +当代码执行完毕后,i已经等于5了。因为一旦运行程序,for循环已经执行完了,此时i等于5。 + +现在,我们尝试在 myDiv[i].onclick事件中写代码,如果打印: + +``` + console.log(i); //打印结果为5 +``` + + +如果打印: + +``` + console.log(myDiv[i].id); +``` + +上方这行代码,打印会报错,因为i=5;如果想打印每个div的id,应该这样写: + +``` + console.log(this.id); +``` + +你看,this的作用,就体现出来了。 + +PS:顺便提醒一下,上面的代码中,如果把`var i`改成`let i`,效果又完全不同了。参考链接:[let和var在for循环中的表现](http://blog.csdn.net/stopllL/article/details/64130664) + +### 全局作用域中的this + +当一段代码在浏览器中执行时,所有的全局变量和对象都是在window对象上定义的。换而言之,所有的全局变量和对象都属于window对象。 + + +## this的定律 + +this关键字永远指向函数(方法)运行时的**所有者**。 + +### 函数赋值给变量时,this指向window + + +比如: + +``` +var foo1 = args.getInfo; +foo1(); + +var foo2 = function(){}; +foo2(); +``` + + +this都是指向window。 + +### 以函数形式调用时,this永远都是window + + +### 以方法的形式调用时,this是调用方法的对象 + + +## 解决闭包中的this指向问题 + + +内部函数是可以访问到外部函数的变量的。 + +方式一:直接通过父函数的名字访问 + +方式二:如果不知道父函数的名字,在父函数里加一句`_this = this`,此时`_this`相当于父函数的名字。 + +### 当this遇到一些特殊的函数时 + + + + + + + + + + + diff --git "a/07-JavaScript\350\277\233\351\230\266/08-JavaScript\345\274\200\345\217\221\347\247\257\347\264\257.md" "b/07-JavaScript\350\277\233\351\230\266/08-JavaScript\345\274\200\345\217\221\347\247\257\347\264\257.md" new file mode 100644 index 00000000..f2d72418 --- /dev/null +++ "b/07-JavaScript\350\277\233\351\230\266/08-JavaScript\345\274\200\345\217\221\347\247\257\347\264\257.md" @@ -0,0 +1,140 @@ +--- +title: 08-JavaScript开发积累 +publish: true +--- + + + + + +### 方法的注释 + +方法写完之后(注意,一定要先写完整),我们在方法的前面输入`/**`,然后回车,会发现,注释的格式会自动补齐。 + +比如: + + +```javascript +/** + * 功能:给定元素查找他的第一个元素子节点,并返回 + * @param ele + * @returns {Element|*|Node} + */ +function getFirstNode(ele){ + var node = ele.firstElementChild || ele.firstChild; + return node; +} +``` + +### 断点调试 + +(1)先让程序运行一遍。 + +(2)f12,弹出代码调试工具 + +(3)打断点: + +![](http://img.smyhvae.com/20180124_2035.png) + +然后刷新页面。 + +(4)一步步调试,每点击一次,执行一步: + +![](http://img.smyhvae.com/20180124_2036.png) + +(5)监视变量: + +当然,也可以添加变量或者表达式到监视窗口。操作如下: + +![](http://img.smyhvae.com/20180124_2037.png) + +上图中,选择变量或表达式,然后右键add to watch. + +然后监视窗口: + +![](http://img.smyhvae.com/20180124_2038.png) + + +### 2019-05-20-给数组、对象赋值 + +**数组赋值的正确写法**: + +```javascript +this.todayList.splice(0, 0, ...dataList); +``` + +**对象赋值的正确写法**: + +```javascript +Object.assign(obj2, obj1); +``` + +上方代码中,是将`obj1` 的值追加到`obj2`中。如果对象里的属性名相同,会被覆盖。 + + +### 2019-11-25-在新的窗口中打开url + +在原来的窗体中跳转到新页面: + +```javascript +window.location.href="要跳转的新页面"; +``` + +在新窗体中打开新页面: + +```javascript +window.open('你所要跳转的新页面'); +``` + + +### 2019-12-10-JavaScript 新特性:Optional Chaining(可选链式调用)语法 + +以往写代码,我们一般都这么写: + +```javascript +if (result && result.user && result.user.name && result.user.name.length) { + console.log('qianguyihao'); +} +``` + +有了 Optinal Chain 语法之后,就简洁很多了,可以这么写: + + +```javascript +if (result?.user?.name?.length) { + console.log('qianguyihao'); +} +``` + + + +参考链接: + +- 了解 JavaScript 新特性:Optional Chaining: + +- 原文链接: https://v8.dev/features/optional-chaining + + + +### 2020-04-28-判断字符串的包含关系 + +```js +var str = 'qiangu2'; +if (str == ('qiangu1' || 'qiangu2')) { + console.log('qianguyihao'); +} +``` + +注意,上面的代码,根本就不会走 console.log 语句,因为if里面的内容是false。 + +如果我们要判断变量 `str` 是否在 `qiangu1、qiangu2`的合集里,我们应该这样写: + +```js +var str = 'qiangu2'; +if (str == 'qiangu1' || str == 'qiangu2') { + console.log('qianguyihao'); +} +``` + + + diff --git "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/01-CSS\345\237\272\347\241\200\347\273\203\344\271\240\357\274\232JD\351\246\226\351\241\265\347\232\204\345\210\266\344\275\234\357\274\210\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\357\274\211.md" "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/01-CSS\345\237\272\347\241\200\347\273\203\344\271\240\357\274\232JD\351\246\226\351\241\265\347\232\204\345\210\266\344\275\234\357\274\210\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\357\274\211.md" index 82480e40..5f79e81e 100644 --- "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/01-CSS\345\237\272\347\241\200\347\273\203\344\271\240\357\274\232JD\351\246\226\351\241\265\347\232\204\345\210\266\344\275\234\357\274\210\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\357\274\211.md" +++ "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/01-CSS\345\237\272\347\241\200\347\273\203\344\271\240\357\274\232JD\351\246\226\351\241\265\347\232\204\345\210\266\344\275\234\357\274\210\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\357\274\211.md" @@ -1,3 +1,11 @@ +--- +title: 01-CSS基础练习:JD首页的制作(顶部和底部) +publish: true +--- + + + + diff --git "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/02-CSS\345\237\272\347\241\200\347\273\203\344\271\240\357\274\232JD\351\246\226\351\241\265\347\232\204\345\210\266\344\275\234\357\274\210\345\277\253\346\215\267\345\257\274\350\210\252\351\203\250\345\210\206\357\274\211.md" "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/02-CSS\345\237\272\347\241\200\347\273\203\344\271\240\357\274\232JD\351\246\226\351\241\265\347\232\204\345\210\266\344\275\234\357\274\210\345\277\253\346\215\267\345\257\274\350\210\252\351\203\250\345\210\206\357\274\211.md" index 837cd26f..03aa6491 100644 --- "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/02-CSS\345\237\272\347\241\200\347\273\203\344\271\240\357\274\232JD\351\246\226\351\241\265\347\232\204\345\210\266\344\275\234\357\274\210\345\277\253\346\215\267\345\257\274\350\210\252\351\203\250\345\210\206\357\274\211.md" +++ "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/02-CSS\345\237\272\347\241\200\347\273\203\344\271\240\357\274\232JD\351\246\226\351\241\265\347\232\204\345\210\266\344\275\234\357\274\210\345\277\253\346\215\267\345\257\274\350\210\252\351\203\250\345\210\206\357\274\211.md" @@ -1,4 +1,12 @@ -02-CSS基础练习:JD首页的制作(快捷导航部分) +--- +title: 02-CSS基础练习:JD首页的制作(快捷导航部分) +publish: true +--- + + + + + 我们在上一篇文章中制作的网页最顶部的导航,是属于网页导航。 diff --git "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/03-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232\345\237\272\347\241\200\347\273\203\344\271\240.md" "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/03-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232\345\237\272\347\241\200\347\273\203\344\271\240.md" index 5a5ab266..9e440fc8 100644 --- "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/03-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232\345\237\272\347\241\200\347\273\203\344\271\240.md" +++ "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/03-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232\345\237\272\347\241\200\347\273\203\344\271\240.md" @@ -1,3 +1,11 @@ +--- +title: 03-DOM操作练习:基础练习 +publish: true +--- + + + + ## DOM操作练习 diff --git "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/04-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232Tab\346\240\217\345\210\207\346\215\242\357\274\210\351\200\232\350\277\207className\350\256\276\347\275\256\346\240\267\345\274\217\357\274\211.md" "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/04-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232Tab\346\240\217\345\210\207\346\215\242\357\274\210\351\200\232\350\277\207className\350\256\276\347\275\256\346\240\267\345\274\217\357\274\211.md" index dcca4320..5ba4794b 100644 --- "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/04-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232Tab\346\240\217\345\210\207\346\215\242\357\274\210\351\200\232\350\277\207className\350\256\276\347\275\256\346\240\267\345\274\217\357\274\211.md" +++ "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/04-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232Tab\346\240\217\345\210\207\346\215\242\357\274\210\351\200\232\350\277\207className\350\256\276\347\275\256\346\240\267\345\274\217\357\274\211.md" @@ -1,7 +1,13 @@ +--- +title: 04-DOM操作练习:Tab栏切换(通过className设置样式) +publish: true +--- + + + + -> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8371782.html),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 -> 以下是正文。 京东网页上,可以看到下面这种tab栏的切换: diff --git "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/05-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232\350\256\277\351\227\256\345\205\263\347\263\273\347\232\204\345\260\201\350\243\205.md" "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/05-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232\350\256\277\351\227\256\345\205\263\347\263\273\347\232\204\345\260\201\350\243\205.md" index 5e4b7c48..b4054339 100644 --- "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/05-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232\350\256\277\351\227\256\345\205\263\347\263\273\347\232\204\345\260\201\350\243\205.md" +++ "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/05-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232\350\256\277\351\227\256\345\205\263\347\263\273\347\232\204\345\260\201\350\243\205.md" @@ -1,3 +1,11 @@ +--- +title: 05-DOM操作练习:访问关系的封装 +publish: true +--- + + + + diff --git "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/07-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232innerHTML\347\232\204\346\226\271\345\274\217\345\210\233\345\273\272\345\205\203\347\264\240.md" "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/07-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232innerHTML\347\232\204\346\226\271\345\274\217\345\210\233\345\273\272\345\205\203\347\264\240.md" index 079cbe22..8dc90448 100644 --- "a/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/07-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232innerHTML\347\232\204\346\226\271\345\274\217\345\210\233\345\273\272\345\205\203\347\264\240.md" +++ "b/08-\345\211\215\347\253\257\345\237\272\346\234\254\345\212\237\357\274\232CSS\345\222\214DOM\347\273\203\344\271\240/07-DOM\346\223\215\344\275\234\347\273\203\344\271\240\357\274\232innerHTML\347\232\204\346\226\271\345\274\217\345\210\233\345\273\272\345\205\203\347\264\240.md" @@ -1,3 +1,11 @@ +--- +title: 07-DOM操作练习:innerHTML的方式创建元素 +publish: true +--- + + + + ## 动态创建DOM元素的三种方式 diff --git "a/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/01-Bootstrap\345\205\245\351\227\250.md" "b/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/01-Bootstrap\345\205\245\351\227\250.md" index 7099e442..ca5de581 100644 --- "a/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/01-Bootstrap\345\205\245\351\227\250.md" +++ "b/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/01-Bootstrap\345\205\245\351\227\250.md" @@ -1,8 +1,13 @@ +--- +title: 01-Bootstrap入门 +publish: true +--- + + + -> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8470657.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 -> 以下是正文。 ## Bootstrap 介绍 diff --git "a/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/02-Bootstrap\344\275\277\347\224\250.md" "b/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/02-Bootstrap\344\275\277\347\224\250.md" index b28b04f6..f383db7f 100644 --- "a/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/02-Bootstrap\344\275\277\347\224\250.md" +++ "b/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/02-Bootstrap\344\275\277\347\224\250.md" @@ -1,3 +1,12 @@ +--- +title: 02-Bootstrap使用 +publish: false +--- + + + + + diff --git "a/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/03-Less\350\257\246\350\247\243.md" "b/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/03-Less\350\257\246\350\247\243.md" index 7101d3bf..f0ee50f7 100644 --- "a/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/03-Less\350\257\246\350\247\243.md" +++ "b/09-\347\247\273\345\212\250Web\345\274\200\345\217\221/03-Less\350\257\246\350\247\243.md" @@ -1,8 +1,12 @@ +--- +title: 03-Less详解 +publish: true +--- + + -> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8476602.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 -> 以下是正文。 ## CSS 预处理器 diff --git "a/10-MySQL\346\225\260\346\215\256\345\272\223/01-\346\225\260\346\215\256\345\272\223\347\232\204\345\237\272\347\241\200\347\237\245\350\257\206.md" "b/10-MySQL\346\225\260\346\215\256\345\272\223/01-\346\225\260\346\215\256\345\272\223\347\232\204\345\237\272\347\241\200\347\237\245\350\257\206.md" new file mode 100644 index 00000000..2e7ba1e1 --- /dev/null +++ "b/10-MySQL\346\225\260\346\215\256\345\272\223/01-\346\225\260\346\215\256\345\272\223\347\232\204\345\237\272\347\241\200\347\237\245\350\257\206.md" @@ -0,0 +1,116 @@ +--- +title: 01-数据库的基础知识 +publish: true +--- + + + + + + + + +## 数据库的概念 + +**数据库**:database(DB),是一种存储数据的仓库。具有如下特性: + +- 数据库是根据数据结构组织、存储和管理数据。 +- 数据库能够长期、高效的管理和存储数据。 +- 数据库的目的就是能够存储(写)和提供(读)数据。 + +## 数据库分类 + +数据库分为两类: + +- **关系型数据库**:把复杂的数据结构归结为简单的二元关系,即二维表格形式(二维表)。注重数据存储的持久性。 + +- **非关系型数据库**:没有具体模型的数据结构。英文简称 NoSQL(Not Only SQL ),意为"不仅仅是SQL"。注重数据读取的效率。 + +我们具体来看看。 + +### 1、关系型数据库 + +**关系型数据库**:把复杂的数据结构归结为简单的二元关系,即二维表格形式(二维表)。 + +关系型数据库有四层结构: + +- 数据库管理系统(DBMS):DataBase Management System。 + +- 数据库(DB):数据存储的管理者。 + +- 数据表(Table):数据关系管理者。 + +- 数据字段(Field):实际数据存储者。 + +常见的关系型数据库产品: + +- 大型:Oracle + +- 中型:MySQL、SQL Server + +- 小型:Sybase、Access + + +### 2、非关系型数据库 + +**非关系型数据库**:没有具体模型的数据结构。英文简称 NoSQL(Not Only SQL ),意为"不仅仅是SQL"。 + +常见的非关系型数据库产品:MongoDB、Redis、Memcached。 + + + +## SQL 的介绍 + +**SQL**:全称 **Structured Query Language**,译为**结构化查询语言**。 + +**SQL**:是一种针对关系型数据库的标准化编程语言,能够实现用户数据库的查询和程序设计。 + +通俗来讲,**SQL 是关系型数据库的操作指令**。 + +根据操作类型不同,SQL 可分为几类: + + +* DQL:Data Query Language,数据查询语言,用于查询和检索数据 +* DML:Data Manipulation Language,数据操作语言,用于数据的写操作(增删改) +* DDL:Data Definition Language,数据定义语言,用于创建数据结构 +* DCL:Data Control Language,数据控制语言,用于用户权限管理 +* TPL:Transaction Process Language,事务处理语言,辅助DML进行事务操作(因此也归属于DML) + + +补充: + +- SQL 虽然是编程语言,但通常只用来进行数据管理,逻辑部分交给其他编程语言。 + +- SQL 是针对关系型数据库的**通用语言**,所有关系型数据库都是基于SQL进行数据操作;而不同的数据库产品,在 SQL 操作指令上略有差异。 + + + +## MySQL 的介绍 + +### MySQL 数据库介绍 + +MySQL 是很有名的 关系型数据库产品,由瑞典MySQL AB 公司开发,现在属于 Oracle 旗下产品。 + +MySQL 在 2008 年被 Sun 公司以10亿美金所收购,而 Sun 公司在2009年被 Oracle 甲骨文公司收购。 + +MySQL 开源免费。 + +### MySQL 访问原理 + +MySQL是一种C/S结构的软件,因此我们需要安装 MySQL 的客户端来访问远程的服务端。也就是说,数据是存放在服务器上的,客户端通过执行 sql 指令来操作服务端的数据。 + +具体步骤是: + +(1)客户端通过 主机(host) + 端口号(port) 服务端。 + +(2)输入 username 和 password 验证身份。 + +(3)客户端和服务端连接成功,通过 sql 指令开始操作数据库。 + + + + + + + + diff --git "a/10-MySQL\346\225\260\346\215\256\345\272\223/02-MySQL\347\232\204\345\256\211\350\243\205\345\222\214Navicat\350\275\257\344\273\266\344\275\277\347\224\250.md" "b/10-MySQL\346\225\260\346\215\256\345\272\223/02-MySQL\347\232\204\345\256\211\350\243\205\345\222\214Navicat\350\275\257\344\273\266\344\275\277\347\224\250.md" new file mode 100644 index 00000000..4b8443ac --- /dev/null +++ "b/10-MySQL\346\225\260\346\215\256\345\272\223/02-MySQL\347\232\204\345\256\211\350\243\205\345\222\214Navicat\350\275\257\344\273\266\344\275\277\347\224\250.md" @@ -0,0 +1,105 @@ +--- +title: 02-MySQL的安装和Navicat软件使用 +publish: true +--- + + + + + +## MySQL 安装 + +### MySQL(Mac版) + +### 步骤1、下载安装包并安装: + +MySQL 下载地址:https://dev.mysql.com/downloads/mysql/ + +![](http://img.smyhvae.com/20200415_1707.png) + + +![](http://img.smyhvae.com/20200415_1708.png) + + +#### 步骤2、配置环境变量 + +打开 `~/.bash_profile` 文件,在文件的末尾,添加如下内容,即可配置环境变量: + +```bash +# mysql +export PATH=${PATH}:/usr/local/mysql/bin +#快速启动、结束MySQL服务, 可以使用alias命令 +alias mysqlstart='sudo /usr/local/mysql/support-files/mysql.server start' +alias mysqlstop='sudo /usr/local/mysql/support-files/mysql.server stop' +``` + +配置好环境变量后,在终端输入 `source ~/.bash_profile` 命令,让配置生效。 + +在终端的任何位置,输入如下命令,即可进入 mysql 命令的执行窗口: + +```sql +mysql -u root -p +``` + +参考链接: + +- [MySQL安装(Mac版)](https://juejin.im/post/5cc2a52ce51d456e7079f27f) + +### 步骤3、继续配置环境变量 + +在 `~/.bash_profile` 中配置好环境变量后,发现每次重启终端后,配置都会失效,需要重新执行 `source ~/.bash_profile` 命令。 + +原因是,zsh加载的是 `~/.zshrc`文件,而 `.zshrc` 文件中并没有定义任务环境变量。 + +解决办法:打开 `~/.zshrc` 文件,在文件的末尾,添加如下内容即可: + +```bash +source ~/.bash_profile +``` + +参考链接: + +## Navicat Premium 软件初体验 + +Navicat Premium 软件是一种数据库管理的GUI软件,采用可视化的方式来查看和操作数据库,非常方便。支持的数据库有: MySQL、MongoDB、SQL Server、SQLite、Oracle 及 PostgreSQL等。 + +安装好 Navicat Premium 软件之后,我们来看看这个软件是怎么用的。 + +### 新建表和数据 + +1、新建连接: + +打开 Navicat Premium 软件,选择菜单栏「文件-新建连接-mysql」,然后选择如下配置,即可在本地新建一个数据库连接: + +![](http://img.smyhvae.com/20200416_1157.png) + + +2、选中连接后,右键新建数据库: + +![](http://img.smyhvae.com/20200416_1159.png) + +![](http://img.smyhvae.com/20200416_1127.png) + + +3、选中数据库之后,新建表 `qiangu_student_table`: + +![](http://img.smyhvae.com/20200416_1138.png) + + +4、在表中添加字段: + +![](http://img.smyhvae.com/20200416_1202.png) + + + +5、字段建好后,开始在表中插入数据: + +![](http://img.smyhvae.com/20200416_1259.png) + + +### 导入外部 sql 文件 + +在 Navicat中,选中当前 database 之后,右键选择“运行sql文件”,即可导入外部sql文件。 + + + diff --git "a/10-MySQL\346\225\260\346\215\256\345\272\223/03-MySQL\347\232\204\345\237\272\346\234\254\346\223\215\344\275\234.md" "b/10-MySQL\346\225\260\346\215\256\345\272\223/03-MySQL\347\232\204\345\237\272\346\234\254\346\223\215\344\275\234.md" new file mode 100644 index 00000000..37fe302a --- /dev/null +++ "b/10-MySQL\346\225\260\346\215\256\345\272\223/03-MySQL\347\232\204\345\237\272\346\234\254\346\223\215\344\275\234.md" @@ -0,0 +1,632 @@ +--- +title: 03-MySQL的基本操作 +publish: true +--- + + + + + + +## SQL 的一些简单语法规则 + +### 结束符 + +SQL 指令需要语句结束符,默认是英文分号`;`。 + +当然,还有另外两个结束符: + +- `\g` 与英文分号`;`等效。 + +- `\G`:将查到的结构旋转90度变成纵向。 + + +### 反引号`` + +SQL语句中如果用到了关键字或者保留字,需要使用反引号``(Tab键上面的符号)来包裹,让系统忽略。 + +## MySQL 数据库的操作分类 + +根据数据库的对象层级,可以将**SQL的基础操作分为四类**: + +- 数据库(DB)操作。 + +- 数据表(Table)操作。 + +- 数据字段(Field)操作。 + +- 数据操作。 + +下面来详细讲一讲。 + +## 一、数据库(DB)的基本操作 + +在终端的任何位置,输入如下命令,即可进入 mysql 命令的执行窗口: + +```sql +mysql -u root -p +``` + +### 1、创建数据库 + +**语法格式**: + +```mysql +create database 数据库名称 [数据库选项]; +``` + +**数据库名称的命名规范**: + +- 由数字、字母和下划线组成。 +- 不区分大小写。 +- 不能以数字开头。 +- 建议使用下划线法创建复杂的数据库名字。比如 `db_qianguyihao`。 + +**举例**: + +创建一个名为 db_qianguyihao1 的数据库: + +```mysql +create database db_qianguyihao1; +``` + + +创建一个指定字符集的数据库: + +```mysql +create database db_qianguyihao2 charset utf8MB4; +``` + +创建一个指定校对集的数据库: + +```mysql +create database db_qianguyihao3 charset utf8MB4 collate utf8mb4_general_ci +``` + + +### 2、查看数据库 + +查看有哪些数据库:(显示所有的数据库列表) + +```mysql +show databases; +``` + +查看 `db_qianguyihao1` 这个数据库的具体创建指令是怎样的: + +```mysql +show create database db_qianguyihao1; +``` + +备注:由于系统会加工,所以看到的结果不一定是真实的创建指令。 + + +### 3、使用指定的数据库 + +使用指定的数据库:(也可以理解成:进入指定的数据库) + +```mysql +# 语法格式 +use database_xxx; + +# 举例 +use db_qianguyihao; +``` + +假设当前服务器连接中有很多个数据库(db_qianguyihao1、db_qianguyihao2),此时,我输入 `use db_qianguyihao2`则代表我想使用 `db_qianguyihao2` 这个数据库。 + + +### 4、修改数据库的参数 + +我们一般很少修改数据库的名称,一般是去修改数据库的一些选项,比如: + +- 修改字符集 + +- 修改校对集 + +**语法格式**: + +```mysql +alter database 数据库名称 [库选项] +``` + +举例1、修改数据库的字符集为gbk: + +```mysql +alter database db_qianguyihao1 charset gbk; +``` + +举例2、修改数据库的校对集: + +```sql +alter database db_qianguyihao2 charset gbk collate gbk_chinese_ci; +``` + +备注:因为校对集是和字符集有关的,所以上方指令是在修改字符集的同时,修改校对集。 + + + +### 5、删除指定的数据库 + +**语法格式**: + +```mysql +drop database 数据库名称; +``` + +备注:删除数据库时,会清空当前数据库里的所有数据表,所以删除数据库的操作一定要谨慎。 + + +## 二、数据表(Table)的基本操作 + +注意,我们最好先通过 `use xxx_database` 命令进入指定的数据库(DB),然后在当前数据库下,进行数据表(Table)的操作。 + +### 1、创建数据表 + +**语法格式**: + +```sql +create table [数据库名].[表名] ( + 字段名1 字段类型, + ... + ... + 字段名2 字段类型 +) 表选项; +``` + +**举例**: + +1、在当前数据库中创建数据表 `table_qiangu1`,并新增**主键** id 字段: + +```sql +CREATE TABLE table_qiangu1 ( + id int NOT NULL AUTO_INCREMENT PRIMARY KEY +); +``` + +2、在当前数据库中创建数据表 `t_student1`,并新增 name、age这连个字段: + +```sql +create table t_student1( + name varchar(255), + age int +); + + +``` + +3、在指定的数据库 `db_2` 中创建数据表 `t_student2`: + + +```sql +create table db_2.t_student2( + name varchar(255), + age int +); +``` + +4、在当前数据库中创建数据表 `t_student3`(含表选项): + +```sql +create table t_student3( + name varchar(255), + age int +)engine Innodb charset utf8MB4; +``` + +举例4中的代码涉及到存储引擎,这里解释一下: + +**存储引擎**是指数据存储和管理的方式,MySQL中提供了多种存储引擎,一般使用默认存储引擎 InnoDB。 + +- InnoDB:默认存储引擎;支持事务处理和外键;数据统一管理。 + +- MyIsam:不支持事务和外键;数据、表结构、索引独立管理;MySQL5.6以后不再维护。 + +6、扩展:如果想创建一个与已有表一样的数据表,MySQL提供了一种便捷的复制模式 + +### 2、复制数据表 + +如果想创建一个与已有表一样的数据表,MySQL提供了一种便捷的**复制**模式。 + +**语法格式**:(复制现有的表 `table_xx1` 到 `table_xx2`) + +```sql +create table table_xx1 like 数据库名.table_xx2; +``` + +注意,这种复制模式,`table_xx2` 只会复制表 `table_xx1` 中的字段,不会复制表`table_xx1`中的数据。 + +**举例**: + + +```sql +# 在当前数据库下,复制现有的表`t_qianguyihao1` 到表 `t_qianguyihao2` +create table t_qianguyihao1 like t_qianguyihao2; + +# 复制现有的表`t_qianguyihao1` 到表 `t_qianguyihao2`,是复制到 `db2`这个数据库中 +create table t_qianguyihao1 like db2.t_qianguyihao2; +``` + + +### 3、显示数据表的名称 + +在当前数据库下,显示所有的数据表: + +```sql +show tables; +``` + +在指定的数据库中,显示所有的数据表: + +```sql +show tables from db_qianguyihao1; +``` + +显示数据表的创建指令:(查看 `t_qianguyihao1` 这个数据表的具体创建指令是怎样的) + +```mysql +show create table t_qianguyihao1; # 备注:由于系统会加工,所以看到的结果不一定是真实的创建指令。 +``` + + + +### 4、查询(查找)数据表的名称 + +> 根据 表名称 查询数据表,也可以理解成:按条件显示部分数据表。 + +根据数据表的**表名称**查找数据表时,需要用到关键词`like`,而且还要涉及到两个符号: + +- `%` 表示匹配任意**多个字符**。 + +- `_` 表示匹配任意**一个字符**(固定位置)。 + +上面这两个模糊查询的符号,大家要牢记。我们来看看具体的例子。 + +语法举例: + +```mysql +show tables like '%like_'; # _表示匹配一个字符(固定位置),%表示匹配N个字符 +``` + +**`%` 符号举例**: + +```sql +# 查询表名称中,包含 “qiangu” 这个关键字的表(“qiangu”这个关键字的前后可能都有内容) +show tables like '%qiangu%'; + +# 查询表名称以“qiangu”开头的表(这个命令应该很实用) +show tables like 'qiangu%'; +``` + +**`_`符号举例**: + +```sql +# 根据 表名称 来查询表,查询条件是:表名称以“qiangu”开头,而且要确保 qiangu 的后面有三个字符(因为我在 qiangu 的后面写了三个下划线)。 +show tables like 'qiangu___'; +``` + + +### 5、desc:查看数据表的表结构 + +查看数据表的表结构,就是**查看这张表中定义了哪些字段**,以及这些字段是如何定义的。通过这种方式,我们可以清晰地了解数据的存储形式。 + +项目开发中,领导在检查我们的工作时,首先看的就是我们的表中定义了哪些字段。所以说,这种方式,还是很实用的。 + +**语法格式**: + +```sql +# 方式1 +desc 表名称; + +# 方式2 +describe 表名称; + +# 方式3 +show columns from 表名称; +``` + +上面的三种方式,效果都一样,三选一即可。 + + +### 6、修改数据表的表名称和表选项 + +**修改数据表的表名称**: + +在当前数据库下,修改数据表的表名称: + +```sql +rename table 原表名 to 新表名; +``` + +指定某个数据库,然后修改数据表的表名称: + + +```sql +rename table 数据库名.原表名 to 数据库名.新表名; +``` + +**修改数据表的表名称**: + +```sql +alter table table1 charset gbk; +``` + +### 7、删除数据表 + +语法格式: + +```sql +drop table 数据表名称; + +``` + + +## 三、字段(Field)的基本操作 + +数据表 table 创建好了之后,我们就可以开始在这张表中新增字段了。 + +### 1、新增字段 + +**语法格式**: + +```sql +alter table 表名 add [column] 字段名 字段类型 [字段属性] [字段位置]; +``` + +注意事项: + +- 新增字段时,必须制指定字段类型。 + +- [column]、 [字段属性]、[字段位置] 这几个都是选填,其他是必填。 + +- 追加字段时,这个字段的顺序默认排在最后。 + +**举例**: + +新增字段 `name`: + +```sql +alter table table_qiangu1 add name varchar(255); + +``` + +新增字段 `age`: + +```sql +alter table table_qiangu1 add age int; +``` + + +### 2、新增字段时,设置字段的位置(顺序) + +在新增字段时,它的顺序是默认放在最后面的,当然,我们也可以人工指定它的顺序。 + +在修改字段的位置时,我们可以用到下面这两个关键字: + +- `first` 放到最前面 + +- `after` 放到某个字段的后面 + +**语法格式**: + +```sql +alter table 表名 add 新字段名 字段类型 字段位置; +``` + + +**举例1**: + +在 `name`字段的后面,新增一个 `sex` 字段: + +```sql +alter table t_qiangu1 add sex varchar(255) default null comment '性别' after name; +``` + +注意,上方举例中,如果是新建 varchar 类型的字段,一定要指定 varchar 的长度(比如255),否则报错。 + +**举例2**: + + +新增一个 `id` 字段,放到最前面: + +```sql +alter table t_qiangu1 add id int first; +``` + + + + +### 3、change:修改现有字段的字段名 + +> 修改现有字段的字段名,是通过 change 关键字,不是通过 modify 关键字(后者会报错,执行失败)。 + +**语法格式**: + +```sql +# 格式1(精简版) +alter table 表名 change 原字段名 新字段名 字段类型; + +# 格式2(完整版) +alter table 表名 change 原字段名 新字段名 字段类型 [字段属性] [位置]; +``` + +注意: + +- 修改字段名时,一定要设置新字段的字段类型。 + +- 虽然 change 关键字也可以修改现有字段的字段属性、字段位置,但我们一般是通过 modify 关键字来做(下面会讲)。 + + +**举例**: + +修改字段名 `sex` 为 `sexy`: + +```sql +alter table t_qiangu2 change sex sexy varchar(255); +``` + +### 4、modify:修改现有字段的的字段类型、字段位置、字段属性 + +**语法格式**: + +```sql +alter table 表名 modify 现有字段的字段名 现有字段的字段类型 [字段属性] [位置]; +``` + +**举例1**、针对现有的字段 `name` 和 `age`,更换这两个字段的顺序: + +```sql +# 注意,这里的 age 后面一定要跟上它的字段类型,否则执行失败 +alter table t_qiangu1 modify age int after name; +``` + +### 修改字段的默认值 + +```sql +# 若本身存在默认值,则先删除 +alter table 表名 alter column 字段名 drop default; + +# 若本身不存在则可以直接设定 +alter table 表名 alter column 字段名 set default 默认值; +``` +### 5、删除字段 + +> 删除字段的同时,会删除字段对应的数据。删除字段的操作不可逆,请谨慎操作。 + +语法格式: + +```sql +alter table 表名 drop 字段名; +``` + +举例:(删除 t_qiangu1 表中的 age 这个字段) + +```sql +alter table t_qiangu1 drop age; +``` + + +## 四、数据的基本操作 + +### 1、新增数据 + +**方式1、全字段插入**: + +语法格式: + +```sql +insert into 表名 values(值1, 值2, ... 最后一个值); +``` + +解释: + +- 值的顺序必须与所有字段的顺序一致。 +- 值的数据类型也必须与字段定义的数据类型一致。 + +举例(给 t_qiangu1 这个表中插入一条完整的数据): + +```sql +insert into t_qiangu1 values(3, 'qianguyihao', 28); +``` + +**方式1、部分字段插入**: + +语法格式: + +```sql +insert into 表名 (字段1, 字段2, 字段3) values(值1, 值2, 值3); +``` + +解释: + +-字段的顺序可以随意,但值的顺序必须要与前面的字段顺序**一一对应**,数据类型也要一致。 + +举例(给 t_qiangu1 这个表中的指定字段插入数据): + +```sql +insert into t_qiangu1 (id, name) values(4, 'xusong'); +``` + +### 2、查询数据 + +> 查询数据的操作,占sql日常操作的95%以上。 + +**语法格式**: + +```sql +select xxx from 表名; +``` + +**举例**: + +查询表中的所有数据: + +```sql +select * from t_qiangu1; +``` + +查询表中 name、age 这两个字段的数据: + +```sql +select name, age from t_qiangu2; +``` + +查询表中 id=2 的数据: + +```sql +select * from t_qiangu3 where id = 2; +``` + +### 3、修改数据 + + +**语法格式**: + +```sql +update 表名 set (字段1 = 新值1, 字段2 = 新值2) [where 条件筛选]; +``` + +**解释**: + +- 我们通常是结合 where 条件语句来修改数据。 + +- **修改数据之前,要先保证表里面有数据**。如果这张表是空表,那么,执行这个命令后,等于没执行。 + + +**举例**: + +将表中,name 这个字段的值全部修改为`千古壹号`: + +```sql +update t_qiangu1 set name = '千古壹号'; +``` + +id = 3 的这条记录中,修改 name 和 age 这两个字段的值: + +```sql +update t_qiangu1 set name = '许嵩', age = '34' where id = 3; +``` + +### 4、删除数据 + +> 删除字段的操作不可逆,请谨慎操作。 + +**语法格式**: + +```sql +delete from 表名 [where 条件]; +``` + +**解释**: + +- 执行删除操作之后,匹配到的**整条记录**,都会删除。 + +- **删除数据之前,要先保证表里面有数据**。如果这张表是空表,那么,执行这个命令后,等于没执行。 + +**举例**: + +删除表中`id = 2`的记录: + +```sql +delete from t_qiangu1 where id = 2; +``` diff --git "a/10-MySQL\346\225\260\346\215\256\345\272\223/04-MySQL\345\255\227\346\256\265\347\232\204\346\225\260\346\215\256\347\261\273\345\236\213.md" "b/10-MySQL\346\225\260\346\215\256\345\272\223/04-MySQL\345\255\227\346\256\265\347\232\204\346\225\260\346\215\256\347\261\273\345\236\213.md" new file mode 100644 index 00000000..540e864f --- /dev/null +++ "b/10-MySQL\346\225\260\346\215\256\345\272\223/04-MySQL\345\255\227\346\256\265\347\232\204\346\225\260\346\215\256\347\261\273\345\236\213.md" @@ -0,0 +1,150 @@ +--- +title: 04-MySQL字段的数据类型 +publish: true +--- + + + + + + +## 前言 + +MySQL 中的字段,主要有四种数据类型: + +- 整型(整数) + +- 小数 + +- 字符串类型 + +- 时间日期类型 + +下面来详细讲一讲。 + +## 整数类型 + +### 整数类型的分类 + +MySQL中,整型有五种: + +* 迷你整型:tinyint,使用**1个字节**存储整数,最多存储256个整数(-128~127)。 + +* 短整型:smallint,使用**2个字节**存储整数。 + +* 中整型:mediumint,使用**3个字节**存储整数。 + +* 标准整型:int,使用**4个字节**存储整数。 + +* 大整型:bigint,使用**8个字节**存储。 + +**强调**: + +(1)如果你不知道用哪一种,或者懒得计算,那就用标准整型 `int`吧,这个用的最多。 + +(2)整型在 MySQL 中默认是有符号的,即有正负;无符号需要使用 `unsigned` 修饰整型,代表正整数。 + +**举例**: + +在指定的表中新增 age 字段,要求 age 是正整数: + +```sql +alter table table_qiangu1 add age int unsigned; +``` + +### 设计思路 + +如果需要新建整型的字段,设计思路如下: + +(1)确定需要存储的数据是整数。 + +(2)预估整数的范围,选择合适的整数类型。 + +(3)确定这个整数是否需要包含负数。 + +### 整数类型的取值范围 + +todo。参考链接: + + +### 整数类型的显示宽度、零填充 + +> 我们在很多设计表中,可能会看到比如 `int(11)`这种数据类型,这里面的 `11`代表的就是`显示宽度`。 + +所谓的**显示宽度**,其实就是显示的时候,看到的最少数字个数。 + +比如 int(2) ,表示不管你的数值是多少,最少可以看到两个数字。假如你存的数值是9,没有满两位,就会在前面补零,显示为`09`;假如你的数值是120,超过了显示宽度,则直接显示原始值,不会做**零填充**。 + +**显示宽度的注意事项**: + +- 显示宽度只适用于 MySQL 的整数类型。 + +- 显示宽度只是指明 MySQL 整数类型最少显示的数字个数(可以通过desc查看表字段显示)。 + +- **显示宽度只是在显示的时候改变数值的样式,不会对原本的值进行更改**。 + +- 显示宽度和数值类型的取值范围无关。例如int(10) 他的取值范围依然是(-2 147 483 648,2 147 483 647)。 + +**零填充的注意事项**: + +- 要想让显示宽度自动进行**零填充**,必须要配合 `ZEROFILL`这个关键字一起使用。 + +- **零填充只能针对正整数**,也就是说,`ZEROFILL` 要求整型为无符号型。 + + + +**举例**: + +1、新建一张表,然后在这张表中新增 num1 字段,要求 num1 显示3位,不够3位的自动进行零填充: + +```sql +# 新建一张表 +CREATE TABLE table_qiangu1 ( + id int NOT NULL AUTO_INCREMENT PRIMARY KEY +); + +# 显示宽度有效(正确写法) +alter table table_qiangu1 add num1 int(3) zerofill; + +# 对比:普通写法,显示宽度无效 +alter table table_qiangu1 add num2 int(3); + +# 对比:普通写法 +alter table table_qiangu1 add num3 int; +``` + +上述命令中,如果把 `zerofill` 这个关键字去掉,是达不到显示宽度的效果的。执行完上述命令后,我们执行 `desc table_qiangu1` 命令,对比一下 num1、num2、num3 的字段结构就知道了: + +![](https://img.smyhvae.com/20200423_1050.png) + +上方截图可以看到,只有 num1 才有显示宽度,它可以进行零填充,num2、num3不行。我们往表中插入整数 `6`,然后看看显示结果,就一目了然: + +![](https://img.smyhvae.com/20200423_1055.png) + + +参考链接:[MySql数据库 数值类型的显示宽度](https://juejin.im/post/5b24a2c251882574d73c6f82) + + +## 小数 + +MySQL 中的小数分为两大类: + + +浮点型的数据分为两种: + +- 单精度:float,使用4个字节存储,精度范围为6-7位有效数字。 + +- 双精度:double,使用8个字节存储,精度范围为14-15位有效数字。 + +注意: + +- 浮点数超过精度范围会自动进行四舍五入。 + +- 精度可以指定整数和小数部分。比如 + + + + + + + diff --git "a/10-MySQL\346\225\260\346\215\256\345\272\223/05-MySQL\346\225\260\346\215\256\345\272\223\347\232\204\345\270\270\347\224\250\345\221\275\344\273\244.md" "b/10-MySQL\346\225\260\346\215\256\345\272\223/05-MySQL\346\225\260\346\215\256\345\272\223\347\232\204\345\270\270\347\224\250\345\221\275\344\273\244.md" new file mode 100644 index 00000000..fb9fc053 --- /dev/null +++ "b/10-MySQL\346\225\260\346\215\256\345\272\223/05-MySQL\346\225\260\346\215\256\345\272\223\347\232\204\345\270\270\347\224\250\345\221\275\344\273\244.md" @@ -0,0 +1,289 @@ +--- +title: 05-MySQL数据库的常用命令 +publish: true +--- + + + + + +## MySQL 的一些简单命令 + +我们可以在 Navicat Premium 软件中,创建数据库和表,然后输入查询命令来查询数据。选择菜单栏「查询->新建查询->输入 sql 命令->运行」即可,效果如下: + +![](https://github.com/qianguyihao/Web/blob/master/img/20200417_1750.png) + +我们还可以直接在终端输入命令行来操作。 + +注意,在 Mac 终端执行 sql 命令时,命令的末尾必须加上`;`(英文格式的分号)。效果如下: + +![](https://github.com/qianguyihao/Web/blob/master/img/20200417_1700.png) + +MySQL 命令行的一些简单命令如下。 + +**以 root 身份进入命令行**: + +``` +mysql -u root -p +``` + +**查看有哪些数据库**: + +```sql +show databases; +``` + +**选择进入指定的数据库**: + +```sql +use xxx_database; + +# 举例 +use qianguyihao_database; +``` + +**在当前数据库中,查看有哪些表**: + +```sql +show tables; +``` + +**在当前数据库中,查询指定表的全部数据**: + +```sql +SELECT * FROM xxx_table; + +# 举例 +SELECT * FROM qianguyihao_student_table +``` + +**删除指定的表**: + +```sql +drop table xxx; + +# 举例 +drop table qianguyihao_student_table; +``` + +**删除指定的数据库**: + +```sql +drop database qianguyihao_student_table; +``` + +**创建一个数据库**: + +```sql +create database qianguyihao_database2; +``` + +## where 条件查询 + +使用 `where` 子句可以对表中的数据进行筛选,结果为 true 的行会出现在查询结果中。 + +语法格式如下: + +```sql +SELECT * FROM 表名 where 条件; +``` + +上面的语法格式中,`条件` 具体要怎么写呢?这个可能有很多种情况。我们继续往下看。 + +### 比较运算符 + +- `=` 等于 +- `>` 大于 +- `>=` 大于等于 +- `<` 小于 +- `<=` 小于等于 +- `!=`:不等于 +- `age > 20`:查询 age 大于 30 的数据 + +**举例**: + +```sql +# 查询 age 大于 20 的数据 +SELECT * FROM qianguyihao_table WHERE age > 20; +``` + +### 逻辑运算符 + +- AND + +- OR + +- NOT + +**举例**: + +```sql +# 查询 age 在20至30之间的数据 +SELECT * FROM qianguyihao_table WHERE age BETWEEN 20 AND 30; + +``` + +### 范围查询 + +- `in` 表示在一个非连续的范围内。 + +- `between ... and ...` 表示在一个连续的范围内 + +举例: + +```sql +# 查询 name 为 千古壹号 或者 许嵩的数据 +SELECT * FROM qianguyihao_table WHERE name IN ['千古壹号', '许嵩']; + +SELECT * FROM qianguyihao_table WHERE age BETWEEN 20 AND 30; +``` + +### 模糊查询 + +- `like` + - `%` 表示任意多个任意字符 + - `_` 表示一个任意字符 + +`%` 符号举例: + +```sql +# 查询标题中包含“前端”这两个字的数据(“前端”这两个字的前后可能都有内容) +select * from qianguyihao_table where `title` like "%前端%"; + +# 查询标题以“前端”开头的数据 +select * from qianguyihao_table where `title` like "前端%"; + +``` + +`_`符号举例: + +```sql +# 查询标题,查询条件是:标题中至少有五个字符,而且,这五个字符中,前两个字符一定是“千古”开头的。 +SELECT * FROM qianguyihao_table WHERE `title` LIKE "千古___"; +``` + +### NULL 的判断 + +- `is null` 判断为空 + +- `is not null` 判断为非空 + +注意,`is null` 和**空字符串**`""` 是有区别的。学过 js 基础之后,你应该知道:空字符串并非 null,只不过是里面的值为空而已;空字符串也是会占有内存空间的。 + +举例: + +```sql +select * from qianguyihao_table where name is not NULL; + +``` + +## join 联表查询 + +### 联表查询命令 + +- `tableA inner join tableB`:表 A 与表 B 匹配的行会出现在结果中。 + +- `tableA left join tableB`:表 A 与表 B 匹配的行会出现在结果中。表 A 中独有的数据,对应表 B 中用 null 填充。 + +- `tableA right join tableB`:表 A 与表 B 匹配的行会出现在结果中。表 B 中独有的数据,对应表 A 中用 null 填充。 + +光是这样看,不好理解,我们来举个例子。 + +### 举例 + +现在有下面这两张表:作者表 author、图书表 book。 + +**表 1**、作者表 author: + +| id | authorId | authorName | +| :-- | :------- | :--------- | +| 1 | 11 | 王小波 | +| 2 | 12 | 吴军 | +| 3 | 88 | 千古壹号 | + +**表 2**、图书表 book: + +| id | bookId | bookName | authorId | +| :-- | :----- | :--------- | -------- | +| 1 | 201 | 黄金时代 | 11 | +| 2 | 202 | 白银时代 | 11 | +| 3 | 203 | 青铜时代 | 11 | +| 4 | 204 | 浪潮之巅 | 12 | +| 5 | 205 | 硅谷之谜 | 12 | +| 6 | 206 | 数学之美 | 12 | +| 7 | 777 | 设计心理学 | 99 | + +注意,表2中的每本图书都有对应的 authorId,这个 authorId 就是对应表1中的 authorId。**通过 authorId 把两张表关联起来**。 + +通过联表查询上面的两张表,我们来对比一下查询结果。 + +**情况 0**:(inner join) + +```sql +SELECT * FROM author INNER JOIN book; +``` + +查询结果: + + +![](https://github.com/qianguyihao/Web/blob/master/img/20200418_2300.png) + + +上面这种查询,没有意义,因为没有加任何查询条件。 + +**情况 1**:(inner join) + +```sql +SELECT * FROM author INNER JOIN book ON author.authorId = book.authorId; +``` + +查询结果: + +![](https://github.com/qianguyihao/Web/blob/master/img/20200418_2305.png) + + +上面这行命令,跟下面这行命令等价: + +```sql +SELECT * FROM author, book WHERE author.authorId = book.authorId; +``` + +**情况 2**:(left join) + +```sql +SELECT * FROM author LEFT JOIN book ON author.authorId = book.authorId; +``` + +查询结果: + +![](https://github.com/qianguyihao/Web/blob/master/img/20200418_2310.png) + +**情况 3**:(right join) + +```sql +SELECT * FROM author RIGHT JOIN book ON author.authorId = book.authorId; +``` + +查询结果: + +![](https://github.com/qianguyihao/Web/blob/master/img/20200418_2315.png) + +### 参考链接 + +- [Mysql 联表查询](https://blog.csdn.net/qmhball/article/details/8000003) + + +## 自关联查询 + +涉及到层级关系时可以用自关联查询。 + + +## 子查询 + +当一个查询结果是另一个查询的条件时,这个查询称之为子查询。 + + + + + + diff --git "a/10-MySQL\346\225\260\346\215\256\345\272\223/MySQL\350\256\276\350\256\241\344\270\211\345\244\247\350\214\203\345\274\217.md" "b/10-MySQL\346\225\260\346\215\256\345\272\223/MySQL\350\256\276\350\256\241\344\270\211\345\244\247\350\214\203\345\274\217.md" new file mode 100644 index 00000000..fe631ccf --- /dev/null +++ "b/10-MySQL\346\225\260\346\215\256\345\272\223/MySQL\350\256\276\350\256\241\344\270\211\345\244\247\350\214\203\345\274\217.md" @@ -0,0 +1,47 @@ +--- +title: 01-Bootstrap入门 +publish: false +--- + + + + + + +## 前言 + +范式即规范。MySQL 范式的作用是: + +- 让我们建的表更佳简洁和高效。 + +- 让功能独立化,避免耦合。 + +## MySQL 设计三大范式 + +### 第一范式(1NF):原子性 + +表的每一列具有原子性,不可再分。 + +### 第二范式:唯一性 + +第二范式是建立在第一范式基础上的;外要求所有非主键字段必须完全依赖主键,而不是部分依赖。 + + +### 第三范式 + +第三范式是建立在第二范式基础上的;且要求没有传递依赖。 + + +## 参考链接 + +- [MySql--数据库设计三范式](https://www.jianshu.com/p/3e97c2a1687b) + + + + + + + + + + diff --git "a/10-MySQL\346\225\260\346\215\256\345\272\223/\344\272\213\345\212\241.md" "b/10-MySQL\346\225\260\346\215\256\345\272\223/\344\272\213\345\212\241.md" new file mode 100644 index 00000000..7554981e --- /dev/null +++ "b/10-MySQL\346\225\260\346\215\256\345\272\223/\344\272\213\345\212\241.md" @@ -0,0 +1,20 @@ +--- +title: 01-Bootstrap入门 +publish: false +--- + + + + + + +## 事务语句 + +- 开启:begin + +- 提交:commit + +- 回滚:rollback + + + diff --git "a/10-Node.js\345\222\214\346\225\260\346\215\256\345\272\223/MySQL\346\225\260\346\215\256\345\272\223/\344\272\213\345\212\241.md" "b/10-Node.js\345\222\214\346\225\260\346\215\256\345\272\223/MySQL\346\225\260\346\215\256\345\272\223/\344\272\213\345\212\241.md" deleted file mode 100644 index 9c884a80..00000000 --- "a/10-Node.js\345\222\214\346\225\260\346\215\256\345\272\223/MySQL\346\225\260\346\215\256\345\272\223/\344\272\213\345\212\241.md" +++ /dev/null @@ -1,11 +0,0 @@ - -## 事务语句 - -- 开启:begin - -- 提交:commit - -- 回滚:rollback - - - diff --git "a/11-Node.js/01-Node.js\344\273\213\347\273\215.md" "b/11-Node.js/01-Node.js\344\273\213\347\273\215.md" new file mode 100644 index 00000000..283f3bc8 --- /dev/null +++ "b/11-Node.js/01-Node.js\344\273\213\347\273\215.md" @@ -0,0 +1,257 @@ +--- +title: 01-Node.js介绍 +publish: true +--- + + + + +## todo + +- rpc 和 Node.js 的关系 + +- [《吊打面试官》系列 Node.js 全栈秒杀系统](https://mp.weixin.qq.com/s/uWeAsJ-P253je15A49uKIQ) + +## 前言 + +Node 的重要性已经不言而喻,很多互联网公司都已经有大量的高性能系统运行在 Node 之上。Node 凭借其单线程、异步等举措实现了极高的性能基准。此外,目前最为流行的 Web 开发模式是前后端分离的形式,即前端开发者与后端开发者在自己喜欢的 IDE 上独立进行开发,然后通过 HTTP 或是 RPC 等方式实现数据与流程的交互。这种开发模式在 Node 的强大功能的引领下变得越来越高效,也越来越受到各个互联网公司的青睐。 + +### 前端同学为什么要学习后端/后端同学为什么要学习前端 + +- 了解前后端交互流程。 + +- 前端同学能够和后台开发的程序员更佳紧密地结合、更顺畅地沟通。 + +- 当网站的业务逻辑需要前置时,前端人员需要学习一些后台开发的技术,以完成相应的任务;;反过来也一样。 + +- 拓宽知识视野和技术栈,能够站在全局的角度审视整个项目。 + +### 前端同学为什么要学 Node.js + +1、Node.js 使用 JavaScript 语言开发服务器端应用,**便于前端同学上手**(一些公司甚至要求前端工程师掌握 Node.js 开发)。 + +2、实现了前后端的语法统一,**有利于和前端代码整合**,甚至共用部分代码。 + +比如说,针对接口返回的各种字段,前后端都必须要做校验。此时,如果用 Node.js 来做后台开发的话,前后端可以共用校验的代码。 + +3、Node.js 性能高、生态系统活跃,提供了大量的开源库。 + +4、Jeff Atwood 在 2007 年提出了著名的 Atwood 定律:**任何能够用 JavaScript 实现的应用系统,最终都必将用 JavaScript 实现**。 Jeff Atwood 是谁不重要(他是 Stack Overflow 网站的联合创始人),重要的是这条定律。 + +### 后端同学为什么要学 Node.js + +因为前端同学在学 Node.js。 + +## 什么是 Node.js + +### 官方定义 + +[Node.js](https://nodejs.org/zh-cn/) 是一个基于 **Chrome V8 引擎**的 JavaScript 运行环境。Node.js 使用了一个**事件驱动**、**非阻塞式 I/O**的模型,使其轻量又高效。Node.js 的包管理工具 npm 是全球最大的开源库生态系统。 + +Node.js 不是一门语言,也不是 JavaScript 的框架,也不是像Nginx一样的Web服务器 ,**Node.js 是 JavaScript 在服务器端的运行环境(平台)**。 + + +### Node.js 的组成 + +在 Node.js 里运行 JavaScript,跟在 Chrome 里运行 JavaScript 有什么不同? + +二者采用的是同样的 JS 引擎。在 Node.js 里写 JS,和在前端写 JS,几乎没有不同。在写法上的区别在于:Node.js 没有浏览器、页面标签相关的 API,但是新增了一些 Node.js 相关的 API。通俗来说,对于开发者而言,在前端写 JS 是用于控制浏览器;而 Node.js 环境写 JS 可以控制整个计算机。 + +我们知道,JavaScript 的组成分为三个部分: + +- ECMAScript + +- DOM:标签元素相关的API + +- BOM:浏览器相关的API + +ECMAScript 是 JS 的语法;DOM 和 BOM 浏览器端为 JS 提供的 API。 + +而 Node.js 的组成分为: + +- **ECMAScript**。ECMAScript 的所有语法在 Node 环境中都可以使用。 + +- **Node 环境**提供的一些**附加 API**(包括文件、网络等相关的 API)。 + +如下图所示: + +![](http://img.smyhvae.com/20200409_1545.png) + +### 补充 + +与 PHP、JSP、Python、Perl、Ruby 的“既是语言,也是平台”不同,Node.js 的使用 JavaScript 进行编程,运行在 Chrome 的 V8 引擎上。 + +与 PHP、JSP 等相比(PHP、JSP、.net 都需要运行在服务器程序上,Apache、Nginx、Tomcat、IIS。 +),Node.js 跳过了 Apache、Naginx、IIS 等 HTTP 服务器,它自己不用建设在任何服务器软件之上。Node.js 的许多设计理念与经典架构(LAMP = Linux + Apache + MySQL + PHP)有着很大的不同,可以提供强大的伸缩能力。Node.js 没有 web 容器。 + +JS 语言非常灵活,使得它在严谨性方面不如 Java 等传统的静态语言。JS 是一门动态语言,而且融合了面向对象和函数式编程这两种编程范式。 + +随着 ES6、ES7 等 JS 语法规范的出现,以及浏览器对这些规范的支持,使得我们可以用更为现代化的 JS 语言特性,来编写现代化的应用。 + +## Node.js 的架构和依赖 + +Node.js 的架构如下: + +![](http://img.smyhvae.com/20180301_1540.png) + +Node.js 内部采用 Google Chrome 的 V8 引擎,作为 JavaScript 语言解释器;同时结合自行开发的 libuv 库,**扩展了 JS 在后端的能力(比如 I/O 操作、文件读写、数据库操作等)**。使得 JS 既可以在前端进行 DOM 操作(浏览器前端),又可以在后端调用操作系统资源,是目前最简单的全栈式语言。 + +其次,Node 生态系统活跃,提供了大量的开源库,使得 JavaScript 语言能与操作系统进行更多的交互。 + +### Node.js 运行环境的核心:V8 引擎 和 libuv 库 + +Node.js 是 JavaScript 在服务器端的运行环境,在这个意义上,Node.js 的地位其实就是 JavaScript 在服务器端的虚拟机,类似于 Java 语言中的 Java 虚拟机。 + +- [V8 引擎](https://v8.dev/) :编译和执行 JS 代码、管理内存、垃圾回收。V8 给 JS 提供了运行环境,可以说是 JS 的虚拟机。V8 引擎本身是用 C++ 写的。 + +- [libuv](https://zh.wikipedia.org/wiki/Libuv): libuv 是一个专注于异步 I/O 的跨平台类库,目前主要在 Node.js 上使用。它是 Node.js 最初的作者 Ryan Dahl 为 Node.js 写的底层类库,也可以称之为虚拟机。libuv 本身是用 C 写的。 + +### Java 虚拟机和 V8 引擎,是由同一人开发 + +Chrome 浏览器成功的背后,离不开 JS 的 V8 引擎。作为虚拟机,V8 的性能表现优异,它的开发者是 Lars Bak。在 Lars 的工作履历里,绝大部分都是与虚拟机相关的工作。在开发 V8 之前,他曾经在 Sun 公司工作,担任 HotSpot 团队的技术领导,主要致力于开发高性能的 Java 虚拟机。在这之前,他也曾为 Self、Smalltalk 语言开发过高性能虚拟机。这些无与伦比的经历让 V8 一出世就超越了当时所有的 JS 虚拟机。 + +![](http://img.smyhvae.com/20200617_1120.png) + +V8 的性能优势使得用 JavaScript 写高性能后台服务程序成为可能。在这样的契机下,Ryan Dahl 选择了 JavaScript,选择了 V8,在事件驱动、非阻塞 I/O 模型的设计下实现了 Node。 + +### V8 的内存限制 + +在一般的后端开发语言中,在基本的内存使用上没有什么限制,然而在 Node 中通过 JavaScript 使用内存时就会发现只能使用部分内存(64 位系统下约为 1.4GB,32 位系统下约为 0.7GB)。在这样的限制下,将会导致 Node 无法直接操作大内存对象。 + +造成这个问题的主要原因在于 Node 基于 V8 构建,所以在 Node 中使用的 JavaScript 对象基本上都是通过 V8 自己的方式来进行分配和管理的。V8 的这套内存管理机制在浏览器的应用场景下使用起来绰绰有余,足以胜任前端页面中的所有需求。但在 Node 中,这却限制了开发者随心所欲使用大内存的想法。 + +## Node 的发展历史 + +- 2008 年左右,随着 Ajax 的逐渐普及,Web 开发逐渐走向复杂化,系统化; + +- Node.js 诞生于 2009 年,由 Joyent 的员工 Ryan Dahl 开发而成。2009 年 5 月,Ryan Dahl 在 GitHub 中开源了 Node 的最初版本,同年 11 月,在 JSConf 大会上展示了 Node 项目; + +- 2010 年 1 月,NPM 包管理工具诞生,使得程序员能够更方便地发布和分享 Node.js 的第三方库。 + +- Node.js 最初只支持 Linux 和 Mac OS 操作系统。2011 年 7 月,微软参与合作,Node.js 终于支持了 Windows 平台。PS:不过,node 的生产环境基本是在 Linux 下。 + +- 目前官网最新版本已经更新到 14.x.x 版本,最新稳定的是 12.18.0。 + +据 Node.js 创始人 Ryan Dahl 回忆,他最初希望采用 Ruby,但是 Ruby 的虚拟机效率不行。 + +注意:是 Node 选择了 JavaScript,不是 JavaScript 发展出来了一个 Node。 + +## Node.js 的应用 + +Node.js 拥有强大的开发者社区,现在已经发展出比较成熟的技术体系,以及庞大的生态。它被广泛地应用在 Web 服务、开发工作流、客户端应用等诸多领域。其中,在 **Web 服务**领域,业界对 Node.js 的接受程度最高。 + +### 1、BFF 中间层 + +BFF,即 Backend For Frontend(服务于前端的后端)。玉伯在《[从前端技术进化到体验科技](https://mp.weixin.qq.com/s/IYddaaw2ps1wR2VT1dZWPg)》这篇文章中点出了 BFF 层的概念: + +> BFF 模式下,整体分工很清晰,**后端通过 Java/C++ 等语言负责服务实现,理想情况下给前端提供的是基于领域模型的 RPC 接口,前端则在 BFF 层直接调用服务端 RPC 接口拿到数据**,按需加工消费数据,并实现人机交互。基于 BFF 模式的研发,很适合拥有前端技术背景的全栈型工程师。这种模式的好处很明显,后端可以专注于业务领域,更多从领域模型的视角去思考问题,页面视角的数据则交给前端型全栈工程师去搞定。**领域模型与页面数据是两种思维模式,通过 BFF 可以很好地解耦开,让彼此更专业高效**。 + +在 Web 服务里,搭建一个中间层,前端访问中间层的接口,中间层再访问后台的 Java/C++ 服务。这类服务的特点是不需要太强的服务器运算能力,但对程序的灵活性有较高的要求。这两个特点,正好和 Node.js 的优势相吻合。Node.js 非常适合用来做 BFF 层,优势如下: + +- 对于前端来说:让前端**有能力自由组装后台数据**,这样可以减少大量的业务沟通成本,加快业务的迭代速度;并且,前端同学能够**自主决定**与后台的通讯方式。 + +- 对于后台和运维来说,好处是:安全性(不会把主服务器暴露在外面)、降低主服务器的复杂度等。 + +### 2、服务端渲染 + +**客户端渲染**(CSR / Client side render):前端通过一大堆接口请求数据,然后通过 JS 动态处理和生成页面结构和展示。优点是**前后端分离**、减小服务器压力、局部刷新。缺点是不利于 SEO(如果你的页面然后通过 Ajax 异步获取内容,抓取工具并不会等待异步完成后再行抓取页面内容)、首屏渲染慢。 + +**服务端渲染**(SSR / Server Side Render):服务器返回的不是接口数据,而是一整个页面(或整个楼层)的 HTML 字符串,浏览器直接显示即可。也就是说,在服务器端直接就渲染好了,然后一次性打包返回给前端。优点是**有利于 SEO、首屏渲染很快**。 + +**总结: 搜索引擎优化 + 首屏速度优化 = 服务端渲染**。 + +备注:这里的「服务端渲染」只是让 Node.js 做中间层,不会替代后端的,后台同学请放心。 + +参考链接: + +- [Vue 服务端渲染的概念](https://ssr.vuejs.org/zh/) + +- + +- + +- [方应杭](https://www.zhihu.com/question/59578433/answer/326694511) + +历史回顾: + +(1)一开始,页面很简单,html 是后端渲染的(比如PHP、ASP、JSP等方式)。后端发现页面中的 js 好麻烦(虽然简单,但是坑多),于是让公司招聘专门写 js 的人,简称「前端切图仔」。 + +(2)随着 Node.js 和前端 MVC 的兴起,以及前端越来越复杂,慢慢演变成了「前后端分离」。 + +(3)前端的 SPA 应用流行之后,发现 SEO 问题很大,而且首屏渲染速度很慢,但是自己选的路再难走也要走下去,于是用 Node.js 在服务端渲染被看成是一条出路。 + +(4)以前在一起的时候,是后端做部分前端的工作;现在在一起的时候,是前端做部分后端的工作。 + +### 3、做小型服务、小型网站的后端(基于 Express、Koa 框架) + +现在很多公司的后台管理系统,都是用 Node.js 来开发接口,毕竟,后台管理系统对性能和并发的要求不是太高。有了 Node.js 之后,通过 JS 直接操作 DB,做增删改查,生成接口,极大降低了前端同学的学习门槛。 + +当然,有时候做 Node.js 开发,是因为:后台人力不够,所以把后台开发的一部分工作量,转移给前端同学。 + +### 4、做项目构建工具 + +前端正在广泛使用的构建工具 gulp、Webpack,就是基于 Node.js 来实现的。 + +### 5、 做 PC 端的软件(基于 Electron 框架) + +Electron 框架就是基于 Node.js 的。也可以说:Electron 是 Node.js 在PC客户端的技术。 + +有一点你可能会感到惊讶:程序员们都在用的代码编辑器 VS Code 软件, 就是用 JS 语言实现的。 + +还有一个例子是:电子游戏直播网站 [Twitch](https://www.twitch.tv/),号称是国外游戏直播的鼻祖,它在 PC 端的客户端软件,就是用 Electron 框架的。你会发现,Twitch 的网站视觉,和 PC 端的视觉,几乎是一样的。如果两端都采用 JS 语言,就可以极大的复用现有的工程。 + +### 知名度较高的 Node.js 开源项目 + +![](http://img.smyhvae.com/20180301_2009.png) + +- express:Node.js 中著名的 web 服务框架。 + +- Koa:下一代的 Node.js 的 Web 服务框架。所谓的“下一代”是相对于 Express 而言的。 + +- [Egg](https://eggjs.org/zh-cn/):2016 年,阿里巴巴研发了知名的 Egg.js 开源项目,号称企业级 Web 服务框架。Egg.js 是基于 Koa 开发的。 + +* mocha:是现在最流行的 JavaScript 测试框架,在浏览器和 Node 环境都可以使用。 + +* PM2:node 多进程管理。 + +* jade:非常优秀的模板引擎,不仅限于 js 语言。 + +* CoffeeScript:用简洁的方式展示 JavaScript 优秀的部分。 + +* Atom:编辑器。 + +* VS Code:最酷炫的编辑器。 + +* socket.io:实时通信框架。 + +### 总结 + +或许,能用 Node.js 做的后台应用,Java/C++ 也能做;但是 Node.js 可以让我们多一种选择。 + +短期来看,Node.js 很难像 Java/C++ 那样,成为后台的主力开发语言。这并非是因为 Node.js 的性能问题,主要是因为,Node.js 还比较年轻,经验积累太少,框架的支持度不够。搞企业级服务,Node.js 敌不过 Java/C++,所以目前只能搞「轻量级」;但未来可期。 + +限制语言能力的不是语言本身,而是生态。 + +## 最后一段:前端同学会 Node.js 就真的全栈了吗? + +一个人的精力是有限的,既擅长前端、又精通后端的人,毕竟是极少数。 + +林肯说过:“你可以在所有的时间欺骗一部分人,也可以在一段时间欺骗所有的人,但你不可能在所有的时间欺骗所有的人”。 + +同样的,我也说过:“你可以在这一段时间擅长前端技术,也可以在另一段时间擅长后台技术,但你不可能在**同一段时间**同时擅长前端和后台,更不可能在**所有的时间**同时擅长前端和后台。” + +所谓的全栈,只是一个伪命题。个人不一定需要全栈,企业和项目也不强制要求全栈,分工协作,才最高效。 + +对于个人而言,虽然全栈很难,但是 Node.js 的出现,**让 JS 语言实现了前后端语法的统一,让 JS 语言的技术栈更佳全面**。 + +涉及到后台开发相关的技术,无论如何,也绕不开**框架设计、开发调试、数据库操作、高并发处理、大规模存储、性能优化、容灾方案、RPC 调用、进程管理、操作系统调度、网络安全、系统运维、日常维护、甚至是 Linux 内核、驱动开发**等过硬的知识技能和经验积累。等你亲身经历过这些,才算明白:语言只是一种工具。 + +## 我的公众号 + +想学习**更多技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 + +扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: + +![](https://img.smyhvae.com/20200102.png) + +## \ No newline at end of file diff --git "a/11-Node.js/02-Node.js\347\232\204\347\211\271\347\202\271.md" "b/11-Node.js/02-Node.js\347\232\204\347\211\271\347\202\271.md" new file mode 100644 index 00000000..6f45abbb --- /dev/null +++ "b/11-Node.js/02-Node.js\347\232\204\347\211\271\347\202\271.md" @@ -0,0 +1,35 @@ +--- +title: 02-Node.js的特点 +publish: true +--- + + + + + +## Node.js 的特点 + +- 异步、非阻塞 IO 模型 + +- 事件循环 + +- 单线程 + +- 总结:轻量和高效 + +Node.js 的性能和效率非常高。 + +传统的 Java 语言是一个请求开启一个线程,当请求处理完毕后就关闭这个线程。而 Node.js 则完全没有采用这种模型,它本质上就是一个单线程。 + +你可能会疑问:一个线程如何服务于大量的请求、如何处理高并发的呢?这是因为,Node.js 采用的是异步的、非阻塞的模型。 + +这里所谓的“单线程”,指的是 Node 的主线程只有一个。为了确保主线程不被阻塞,主线程是用于接收客户端请求。但不会处理具体的任务。而 Node 的背后还有一个线程池,线程池会处理长时间运行的任务(比如 IO 操作、网络操作)。线程池里的任务是通过队列和事件循环的机制来执行。 + + +## 使用 Node.js 时的劣势 + +- 程序运行不稳定,可能会出现服务不可用的情况 + +- 程序运行效率较低,每秒的请求数维持在一个较低的水平 + +- 前端同学对服务器端的技术不太熟悉。 diff --git "a/11-Node.js/03-Node.js\345\274\200\345\217\221\347\216\257\345\242\203\345\256\211\350\243\205.md" "b/11-Node.js/03-Node.js\345\274\200\345\217\221\347\216\257\345\242\203\345\256\211\350\243\205.md" new file mode 100644 index 00000000..b9ddfb51 --- /dev/null +++ "b/11-Node.js/03-Node.js\345\274\200\345\217\221\347\216\257\345\242\203\345\256\211\350\243\205.md" @@ -0,0 +1,625 @@ +--- +title: 03-Node.js开发环境安装 +publish: true +--- + + + + + +## Node.js 运行环境配置:通过 Node.js 安装包(不推荐) + +去 Node.js 的[官网](https://nodejs.org/en/)下载安装包: + +![](http://img.smyhvae.com/20180301_1505.png) + +我们也可以在 里下载历史版本。 + +![](http://img.smyhvae.com/20180301_1507.png) + +注意,我们以一定要用偶数版(V4、V6 等),不要用奇数版(比如 V5),因为奇数版不稳定。 + +后续如果需要安装其他版本,可以这样做:重新下载最新的安装包,覆盖安装即可。 + +但我们并不推荐直接采用 Node.js.msi(windows)或者 Node.js.pkg(Mac) 安装包进行安装,因为会产生如下问题。 + +**通过 Node.js 安装包产生的问题**: + +- 安装新版本时,需要覆盖就版本;而且以前版本安装的很多全局工具包,需要重新安装。 + +- 无法回滚到之前的旧版本。 + +- 无法在多个版本之间切换(很多时候,不同的项目需要使用特定版本。或者,我想临时尝鲜一下新版本的特性) + +因此,我们暂时先不用安装 Node.js,稍后用 NVM 的方式来安装 Node.js。通过 NVM 的方式,可以让多个版本的 Node.js 共存,并灵活切换。 + +### Node.js 版本常识 + +- 偶数版本为稳定版(0.6.x ,0.8.x ,8.10.x) + +- 奇数版本为非稳定版(0.7.x ,0.9.x ,9.11.x) + +- LTS(Long Term Support) + +参考链接:[node.js 中 LTS 和 Current 的区别](https://blog.csdn.net/u012532033/article/details/73332099) + +## Node.js 运行环境安装:通过 NVM(推荐) + +**[NVM](https://github.com/nvm-sh/nvm)**:node.js version manager,用来管理 node 的版本。 + +**我们可以先安装 NVM,然后通过 NVM 安装 Node.js**。这是官方推荐的做法。 + +Windows 和 Mac 下安装的 Node.js 的步骤如下。 + +### Windows 系统安装 Node.js + +**1、安装 NVM**: + +(1)我们去 下载 NVM 的安装包: + +![](http://img.smyhvae.com/20180301_1603.png) + +下载下来后,直接解压到 `D:\web`目录下: + +![](http://img.smyhvae.com/20180301_1610.png) + +(2)在上面的目录中,新建一个`settings.txt`文件,里面的内容填充如下: + +```bash +root: D:\web\nvm +path: D:\web\nodejs +arch: 64 +proxy +``` + +上方内容的解释: + +- root 配置为:当前 nvm.exe 所在的目录 + +- path 配置为:node 快捷方式所在的目录 + +- arch 配置为:当前操作系统的位数(32/64) + +- proxy 不用配置 + +(3)配置环境变量: + +- `NVM_HOME` = `D:\web\nvm`(当前 nvm.exe 所在目录) + +- `NVM_SYMLINK` = `D:\web\nodejs` (node 快捷方式所在的目录) + +- PATH += `;%NVM_HOME%;%NVM_SYMLINK%` + +配置成功后,重启资源管理器。 + +**2、验证:**(在 cmd 命令行中输入命令) + +(1)输入`nvm`命令查看环境变量是否配置成功: + +![](http://img.smyhvae.com/20180301_1645.png) + +(2)输入 `nvm ls`,查看已安装的所有 node 版本。 + +(3)输入 `nvm -v`,查看 已安装的 nvm 版本。 + +(4)输入 `node -v`,查看正在使用的 node 版本。 + + +如果 Node 安装失败,可以参考上面这个链接。 + +**3、安装指定版本的 Node.js**: + +```bash +nvm install 版本号 + +# 举例 +nvm install 8.10.0 +``` + +输入 `node -v`,查看当前使用的 node 版本。 + +关于 NVM 的常用命令,详见下一段。 + +补充: + +如果 Node 安装失败,可以在上方的 `settings.txt`文件中,新增如下两行,修改镜像源: + +``` +node_mirror: https://npm.taobao.org/mirrors/node/ +npm_mirror: https://npm.taobao.org/mirrors/npm/ +``` + +- 参考链接:[安装 npm,nvm,node](https://segmentfault.com/a/1190000011114680) + + +### Mac 系统安装 Node.js + +**1、安装 NVM**: + +(1)打开 终端.app,输入: + +```bash +curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash +``` + +安装成功的界面: + +![](http://img.smyhvae.com/20180302_2126.png) + +完成后,nvm 就被安装在了`~/.nvm`下。 + +如果发现安装失败: + +![](http://img.smyhvae.com/20180302_2111.png) + +原因:Xcode 软件进行过更新。 + +解决办法:打开 Xcode 软件,同意相关内容即可。 + +(2)配置环境变量: + +编辑器打开`~/.bash_profile`文件,如果不会就输入`open ~/.bash_profile`。 + +(补充:如果你的 Mac 电脑里找不到`~/.bash_profile`文件,那就找找有没有`~/.profile`文件,或者`~/.bashrc`文件,或者`~/.zshrc`文件。如果还是没有,那你就手动创建一个`~/.bash_profile`文件)。 + +在最后一行输入: + +```bash +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm +``` + +如果你发现文件中已经存在了上面这行代码,就不用往里面加了。这一步的作用是每次新打开一个 bash,nvm 都会被自动添加到环境变量中。 + +最后,输入 `source ~/.bash_profile`重启环境变量的配置。 + +PS:NVM 现在已经不支持 Homebrew 的方式来安装了。 + +参考链接: + +**2、验证:**(在 终端命令行中输入命令) + +(1)输入 `nvm` 命令查看环境变量是否配置成功: + +(2)输入 `nvm ls`,查看已安装的所有 node 版本。 + +(3)输入 `nvm -v`,查看 已安装的 nvm 版本。 + +(4)输入 `node -v`,查看正在使用的 node 版本。 + +**3、安装指定版本的 Node.js**: + +和 Windows 下一样,也是执行如下命令: + +```bash +nvm install 版本号 + +# 举例 +nvm install 8.10.0 +``` + +网速有点慢,要稍等。 + +![](http://img.smyhvae.com/20180302_2148.png) + +输入 `node -v`,查看当前使用的 node 版本。 + +安装好 `Node` 之后,`npm` 也会自动安装的,输入 `npm -v`,查看 npm 的版本。 + +关于 NVM 的常用命令,详见下一段。 + +## NVM 的常用命令 + +> 注意,这一段说的是 NVM 的常用命令,不是 Node 的常用命令。 + +查看当前使用的 nvm 版本: + +```bash +nvm --version +``` + +查看本地安装的所有的 Node.js 版本: + +```bash +# 方式1 +nvm ls + +# 方式2 +nvm list +``` + +**安装指定版本的 Node.js:** + +```bash +nvm install 版本号 + +# 举例 +nvm install 8.10.0 +``` + +卸载指定版本 Node.js: + +```bash +nvm uninstall 版本号 +``` + +**切换使用指定版本的 node**: + +```bash +nvm use 版本号 +``` + +**设置node的默认版本**: + +```bash +nvm alias default 版本号 +``` + + +**查看全局npm包的安装路径**: + +``` +npm root -g +``` + + +查看远程服务器端的所有 Node 版本: + +```bash +nvm ls-remote +``` + +执行上面的命令后,在列出的版本清单中,凡是用 `Latest LTS`标注的版本,则表明是**长期维护**的版本。我们在安装时,建议安装这些版本。当然,我们也可以在网址 查看 LTS 的历史版本。 + +## Node.js 的常用命令 + +查看 node 的版本: + +```bash +$ node -v +``` + +执行脚本字符串: + +```bash +$ node -e 'console.log("Hello World")' +``` + +运行脚本文件: + +```bash +$ node index.js + +$ node path/index.js + +$ node path/index +``` + +查看帮助: + +```bash +$ node --help + +``` + +**进入 REPL 环境:** + +```bash +$ node +``` + +REPL 的全称:Read、Eval、 Print、Loop。类似于浏览器的控制台。 + +![](http://img.smyhvae.com/20180301_1900.png) + +如果要退出 REPL 环境,可以输入`.exit` 或 `process.exit()`。 + +在 VS Code 里,我们可以在菜单栏选择“帮助->切换开发人员工具”,打开 console 控制台。 + +## 包和 NPM + +### 什么是包 + +由于 Node 是一套轻内核的平台,虽然提供了一系列的内置模块,但是不足以满足开发者的需求,于是乎出现了包(package)的概念: +与核心模块类似,就是将一些预先设计好的功能或者说 API 封装到一个文件夹,提供给开发者使用。 + +Node 本身并没有太多的功能性 API,所以市面上涌现出大量的第三方人员开发出来的 Package。 + +### 包的加载机制 + +如果 Node 中自带的包和第三方的包名冲突了,该怎么处理呢?原则是: + +- 先在系统核心(优先级最高)的模块中找; + +- 然后到当前项目中 node_modules 目录中找。 + +比如说: + +```javascript +requiere(`fs`); +``` + +那加载的肯定是系统的包。所以,我们尽量不要创建一些和现有的包重名的包。 + +### NPM 的概念 + +**NPM**:Node Package Manager。官方链接: + +Node.js 发展到现在,已经形成了一个非常庞大的生态圈。包的生态圈一旦繁荣起来,就必须有工具去来管理这些包。NPM 应运而生。 + +举个例子,当我们在使用 Java 语言做开发时,需要用到 JDK 提供的内置库,以及第三方库。同样,在使用 JS 做开发时,我们可以使用 NPM 包管理器,方便地使用成熟的、优秀的第三方框架,融合到我们自己的项目中,极大地加速日常开发的构建过程。 + +随着时间的发展,NPM 出现了两层概念: + +- 一层含义是 Node 的开放式模块登记和管理系统,亦可以说是一个生态圈,一个社区。 + +- 另一层含义是 Node 默认的模块管理器,是一个命令行下的软件,用来安装和管理 Node 模块。 + +### NPM 的安装(不需要单独安装) + +NPM 不需要单独安装。默认在安装 Node 的时候,会连带一起安装 NPM: + +![](http://img.smyhvae.com/20180302_1105.png) + +NVM、Node、NPM 安装之后,目录分布如下: + +![](http://img.smyhvae.com/20180302_1134.png) + +![](http://img.smyhvae.com/20180302_1137.png) + +![](http://img.smyhvae.com/20180302_1138.png) + +输入 `npm -v`,查看 npm 的版本: + +![](http://img.smyhvae.com/20180302_1139.png) + +如果上方命令无效,可能是之前的 node 并没有完全安装成功。解决办法: + +另外,Node 附带的 NPM 可能不是最新版本,可以用下面的命令,更新到最新版本: + +```bash +$ npm install npm -g +``` + +### 配置 NPM 的全局目录(暂略) + +NPM 默认安装到当前正在使用 Node 版本所在目录下。我们建议重新配置 NPM 的全局目录。 + +输入`npm config ls`,查看: + +![](http://img.smyhvae.com/20180302_1210.png) + +## NPM 的常用命令 + +查看 npm 当前版本: + +```bash +npm -v +``` + +更新 npm: + +```bash +npm install npm@latest -g + +``` + +项目初始化:(执行完成后,会生成`package.json`文件) + +```bash +npm init + +# 快速跳过问答式界面,选择默认配置 +npm init --yes +``` + +只在当前工程下安装指定的包: + +```bash +npm install [package] +``` + +在全局安装指定的包: + +``` +npm install -g [package] +``` + +安装的包只用于开发环境,不用于生产环境:(会出现在 package.json 文件中的 devDependencies 属性中) + +```bash +npm install [package] --save-dev + +# 或者 +npm install [package] -D +``` + +安装的包需要发布到生产环境:(会出现在 package.json 文件中的 dependencies 属性中) + +```bash +npm install [package] --save + +# 或者 +npm install [package] -S +``` + +查看当前目录下已安装的 node 包: + +```bash +npm list +``` + +查看全局已经安装的 node 包: + +```bash +npm list -g +``` + +查看 npm 帮助命令: + +```bash +npm --help +``` + +查看指定命令的帮助: + +```bash +npm [指定命令] --help +``` + +更新指定的包: + +```bash +npm update [package] +``` + +卸载指定的包: + +```bash +npm uninstall [package] +``` + +查看配置信息: + +```bash +npm config list +``` + +查看本地安装的指定包的信息,没有则显示 empty: + +```bash +npm ls [package] +``` + +查看全局安装的指定包的信息,没有则显示 empty: + +```bash +npm ls [package] -g +``` + +查看远程 npm 上指定包的所有版本信息: + +```bash +npm info [package] +``` + +查看当前包的安装路径: + +```bash +npm root +``` + +查看全局包的安装路径: + +```bash +npm root -g +``` + +## 配置 npm 镜像源 + +由于 npm 默认的下载地址在国外(npmjs.com),有时候会被墙,导致无法下载或者下载很慢。因此,我们可以尝试切换成,从其他的镜像源下载 npm 包。 + +切换镜像源,有下面这几种方式: + +- 方式 1:临时切换镜像源。 + +- 方式 2:切换镜像源 + +- 方式 3:通过 NRM 切换镜像源(最为推荐的方式)。 + +- 方式 4:cnpm。 + +下面来分别讲一下。 + +### 方式 1:临时切换镜像源 + +安装指定包的时候,通过追加 `--registry`参数即可。格式如下: + +```bash +# 格式 +npm install [package] --registry [https://xxx] + +# 举例:在下载安装 express 这个包的时候,临时指定镜像源为 https://registry.npm.taobao.org +npm install express --registry https://registry.npm.taobao.org +``` + +### 方式 2:切换镜像源 + +```bash +npm config set registry https://registry.npm.taobao.org +``` + +执行上述命令后,以后下载所有 npm 包的时候,都会改为使用淘宝的镜像源。 + +### 方式 3:通过 NRM 切换镜像源(推荐) + +**NRM**:Node Registry Manager。作用是:**切换和管理 npm 包的镜像源**。 + +- 项目地址: + +- GitHub 地址: + +**安装 NRM**: + +```bash + npm install -g nrm +``` + +![](http://img.smyhvae.com/20180302_1208.png) + +**NRM 的常用命令:** + +```bash +# 显示全部的镜像 +nrm ls + +# 使用淘宝的镜像 +nrm use taobao +``` + +效果如下: + +![](http://img.smyhvae.com/20180302_1215.png) + +推荐的国内加速镜像淘宝: + +## 方式 4:安装 cnpm + +- 项目地址: + +安装`cnpm`替换 npm(npm 由于源服务器在国外,下载包的速度较慢,cnpm 会使用国内镜像): + +```bash +npm install -g cnpm --registry=https://registry.npm.taobao.org +``` + +![](http://img.smyhvae.com/20180302_2204.png) + +以后我们就可以通过 cnpm 命令去安装一个包。举例如下: + +```bash +# 安装 vue 这个包 +cnpm install vue +``` + +这里的单词 `install` 可以简写成 `i`。 + +## Node.js 的简单使用 + +我们可以输入`node`命令,然后在里面写 js 的代码。 + +或者,也可以 通过 node 运行 指定的 js 文件。比如,编写好一个 js 文件`01.js`,然后在命令行输入: + +```bash + node 01.js +``` + +就可以执行这个 js 程序,直接在命令行查看运行结果。 + +## 我的公众号 + +想学习**更多技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 + +扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: + +![](https://img.smyhvae.com/20200102.png) diff --git "a/11-Node.js/04-Node.js\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\357\274\232CommonJS.md" "b/11-Node.js/04-Node.js\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\357\274\232CommonJS.md" new file mode 100644 index 00000000..5303d8da --- /dev/null +++ "b/11-Node.js/04-Node.js\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\357\274\232CommonJS.md" @@ -0,0 +1,709 @@ +--- +title: 04-Node.js模块化规范:CommonJS +publish: true +--- + + + + + + +## 前言 + +网站越来越复杂,js代码、js文件也越来越多,会遇到**一些问题**: + +- 文件依赖 + +- 全局污染、命名冲突 + +程序模块化包括: + +- 日期模块 + +- 数学计算模块 + +- 日志模块 + +- 登陆认证模块 + +- 报表展示模块等。 + +所有这些模块共同组成了程序软件系统。 + +一次编写,多次使用,才是提高效率的核心。 + + + + +## 模块化的理解 + +### 什么是模块化 + + +**概念**:将一个复杂的程序依据一定的规则(规范)封装成几个块(文件),并组合在一起。 + +模块的内部数据、实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信。 + +最早的时候,我们会把所有的代码都写在一个js文件里,那么,耦合性会很高(关联性强),不利于维护;而且会造成全局污染,很容易命名冲突。 + +### 模块化的好处 + +- 避免命名冲突,减少命名空间污染 + +- 降低耦合性;更好地分离、按需加载 + +- **高复用性**:代码方便重用,别人开发的模块直接拿过来就可以使用,不需要重复开发类似的功能。 + +- **高可维护性**:软件的声明周期中最长的阶段其实并不是开发阶段,而是维护阶段,需求变更比较频繁。使用模块化的开发,方式更容易维护。 + +- 部署方便 + + + + +## 模块化规范 + +### 模块化规范的引入 + +假设我们引入模块化,首先可能会想到的思路是:在一个文件中引入多个js文件。如下: + +```html + + + + + + + +``` + +但是这样做会带来很多问题: + +- 请求过多:引入十个js文件,就有十次http请求。 + +- 依赖模糊:不同的js文件可能会相互依赖,如果改其中的一个文件,另外一个文件可能会报错。 + +以上两点,最终导致:**难以维护**。 + +于是,这就引入了模块化规范。 + + +### 模块化的概念解读 + +模块化起源于 Node.js。Node.js 中把很多 js 打包成 package,需要的时候直接通过 require 的方式进行调用(CommonJS),这就是模块化的方式。 + +那如何把这种模块化思维应用到前端来呢?这就产生了两种伟大的 js:RequireJS 和 SeaJS。 + + +### 模块化规范 + +服务器端规范: + +- [**CommonJS规范**](http://www.commonjs.org/):是 Node.js 使用的模块化规范。 + +CommonJS 就是一套约定标准,不是技术。用于约定我们的代码应该是怎样的一种结构。 + + +浏览器端规范: + +- [**AMD规范**](https://github.com/amdjs/amdjs-api):是 **[RequireJS](http://requirejs.org/)** 在推广过程中对模块化定义的规范化产出。 + +``` +- 异步加载模块; + +- 依赖前置、提前执行:require([`foo`,`bar`],function(foo,bar){}); //也就是说把所有的包都 require 成功,再继续执行代码。 + +- define 定义模块:define([`require`,`foo`],function(){return}); +``` + +- **[CMD规范]()**:是 **[SeaJS](http://seajs.org/)** 在推广过程中对模块化定义的规范化产出。淘宝团队开发。 + +``` + + 同步加载模块; + + 依赖就近,延迟执行:require(./a) 直接引入。或者Require.async 异步引入。 //依赖就近:执行到这一部分的时候,再去加载对应的文件。 + + define 定义模块, export 导出:define(function(require, export, module){}); +``` + + +PS:面试时,经常会问AMD 和 CMD 的区别。 + + +另外,还有ES6规范:import & export。 + +这篇文章,我们来讲一下`CommonJS`,它是 Node.js 使用的模块化规范。 + +## CommonJS 的基本语法 + +### CommonJS 的介绍 + + +[CommonJS](http://www.commonjs.org/):是 Node.js 使用的模块化规范。也就是说,Node.js 就是基于 CommonJS 这种模块化规范来编写的。 + +CommonJS 规范规定:每个模块内部,module 变量代表当前模块。这个变量是一个对象,它的 exports 属性(即 module.exports)是对外的接口对象。加载某个模块,其实是加载该模块的 module.exports 对象。 + +在 CommonJS 中,每个文件都可以当作一个模块: + +- 在服务器端:模块的加载是运行时同步加载的。 + +- 在浏览器端: 模块需要提前编译打包处理。首先,既然同步的,很容易引起阻塞;其次,浏览器不认识`require`语法,因此,需要提前编译打包。 + +### 模块的暴露和引入 + +Node.js 中只有模块级作用域,两个模块之间的变量、方法,默认是互不冲突,互不影响,这样就导致一个问题:模块 A 要怎样使用模块B中的变量&方法呢?这就需要通过 `exports` 关键字来实现。 + +Node.js中,每个模块都有一个 exports 接口对象,我们可以把公共的变量、方法挂载到这个接口对象中,其他的模块才可以使用。 + +接下来详细讲一讲模块的暴露、模块的引入。 + + +### 暴露模块的方式一: exports + +`exports`对象用来导出当前模块的公共方法或属性。别的模块通过 require 函数调用当前模块时,得到的就是当前模块的 exports 对象。 + +**语法格式**: + +```js +// 相当于是:给 exports 对象添加属性 +exports.xxx = value +``` + +这个 value 可以是任意的数据类型。 + +**注意**:暴露的关键词是`exports`,不是`export`。其实,这里的 exports 类似于 ES6 中的 export 的用法,都是用来导出一个指定名字的对象。 + + + +**代码举例**: + +```js +const name = 'qianguyihao'; + +const foo = function (value) { + return value * 2; +}; + +exports.name = name; +exports.foo = foo; +``` + + + +### 暴露模块的方式二: module.exports + +`module.exports`用来导出一个默认对象,没有指定对象名。 + +语法格式: + +```javascript +// 方式一:导出整个 exports 对象 +module.exports = value; + +// 方式二:给 exports 对象添加属性 +module.exports.xxx = value; +``` + +这个 value 可以是任意的数据类型。 + +代码举例: + +```js +// 方式1 +module.exports = { + name: '我是 module1', + foo(){ + console.log(this.name); + } +} + +// 我们不能再继续写 module.exports = value2。因为重新赋值,会把 exports 对象 之前的赋值覆盖掉。 + +// 方式2 +const age = 28; +module.exports.age = age; + +``` + +`module.exports` 还可以修改模块的原始导出对象。比如当前模块原本导出的是一个对象,我们可以通过 module.exports 修改为导出一个函数。如下: + +```js +module.exports = function () { + console.log('hello world') +} +``` + +### exports 和 module.exports 的区别 + + + +最重要的区别: + +- 使用exports时,只能单个设置属性 `exports.a = a;` + +- 使用module.exports时,既单个设置属性 `module.exports.a`,也可以整个赋值 `module.exports = obj`。 + +其他要点: + +- Node中每个模块的最后,都会执行 `return: module.exports`。 + +- Node中每个模块都会把 `module.exports`指向的对象赋值给一个变量 `exports`,也就是说 `exports = module.exports`。 + +- `module.exports = XXX`,表示当前模块导出一个单一成员,结果就是XXX。 + +- 如果需要导出多个成员,则必须使用 `exports.add = XXX; exports.foo = XXX`。或者使用 `module.exports.add = XXX; module.export.foo = XXX`。 + +### 问题: 暴露的模块到底是谁? + +**答案**:暴露的本质是`exports`对象。【重要】 + +比如,方式一的 `exports.a = a` 可以理解成是,**给 exports 对象添加属性**。方式二的 `module.exports = a`可以理解成是给整个 exports 对象赋值。方式二的 `module.exports.c = c`可以理解成是给 exports 对象添加属性。 + +Node.js 中每个模块都有一个 module 对象,module 对象中的有一个 exports 属性称之为**接口对象**。我们需要把模块之间公共的方法或属性挂载在这个接口对象中,方便其他的模块使用。 + + +### 引入模块的方式:require + +require函数用来在一个模块中引入另外一个模块。传入模块名,返回模块导出对象。 + +**语法格式**: + +```js +const module1 = require('模块名'); +``` + +解释: + +- 内置模块:require的是**包名**。 + +- 下载的第三方模块:require的是**包名**。 + +- 自定义模块:require的是**文件路径**。文件路径既可以用绝对路径,也可以用相对路径。后缀名`.js`可以省略。 + + +**代码举例**: + +```js +const module1 = require('./main.js'); + +const module2 = require('./main'); + +const module3 = require('Demo/src/main.js'); +``` + +**require()函数的两个作用**: + +- 执行导入的模块中的代码。 + +- 返回导入模块中的接口对象。 + + +### 主模块 + +主模块是整个程序执行的入口,可以调度其他模块。 + +```bash +# 运行main.js启动程序。此时,main.js就是主模块 +$ node main.js +``` + +### 模块的初始化 + +一个模块中的 JS 代码仅在模块**第一次被使用时**执行一次,并且在使用的过程中进行初始化,然后会被缓存起来,便于后续继续使用。 + +代码举例: + +(1)calModule.js: + +```js +var a = 1; +​ +function add () { + return ++a; +} +​ +exports.add = add; + +``` + +(2)main.js:(在 main.js 中引入 hello.js 模块) + +```js +var addModule1 = require('./calModule') +var addModule2 = require('./calModule') +​ +console.log(addModule1.add()); +console.log(addModule2.add()); +``` + +在命令行执行 `node main.js` 运行程序,打印结果: + +```bash +2 +3 +``` + +从打印结果中可以看出,`calModule.js`这个模块虽然被引用了两次,但只初始化了一次。 + + +## CommonJS 在服务器端的实现举例 + + +### 1、初始化项目 + +在工程文件中新建如下目录和文件: + +``` +modules + | module1.js + | module2.js + | module3.js + +app.js +``` + +然后在根目录下新建如下命令: + +``` + npm init +``` + + +然后根据提示,依次输入如下内容: + +- **包名**:可以自己起包名,也可以用默认的包名。注意,包名里不能有中文,不能有大写。 + +- **版本**:可以用默认的版本 1.0.0,也可以自己修改包名。 + +其他的参数,一路回车即可。效果如下: + +![](http://img.smyhvae.com/20180410_1425.png) + +于是,根目录下会自动生成`package.json`这个文件。点进去看一下: + +```json +{ + "name": "commonjs_node", + "version": "1.0.0", + "description": "", + "main": "app.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "smyhvae", + "license": "ISC" +} + +``` + + +### 2、导入第三方包 + +`uniq`这个第三方包的作用是保证唯一性(我们拿它来举例)。我们在当前工程目录下,输入如下命令进行安装: + +``` + npm install uniq +``` + +安装成功后,根目录下会自动生成相应的文件: + +![](http://img.smyhvae.com/20180410_1450.png) + + +需要说明的是,我的node版本是 v8.10.0(v8以上),对应的 npm 版本是 v5.6.0,版本比较高,因此,当我输入完`npm install uniq`之后,`package.json`中就会自动添加`uniq`包的依赖: + +![](http://img.smyhvae.com/20180410_1855.png) + + +如果有些童鞋的npm版本较低,就需要手动去添加依赖;另一种方式是,可以使用`npm install uniq --save`命令,这个多出来的`--save`就可以自动添加依赖。 + + +我们去[官网](https://www.npmjs.com/package/uniq)看一下`uniq`的用法: + +```javascript + let uniq = require('uniq'); + + let arr = [1, 1, 2, 2, 3, 5]; + uniq(arr); + console.log(arr); //输出结果:[ 1, 2, 3, 5 ] + +``` + +可以看出,这个包可以起到数组去重的作用。 + +### 3、自定义模块 + +(1)module1.js: + +```javascript +//暴露方式一:module.exports = value + +//暴露一个对象出去 +module.exports = { + name: '我是 module1', + foo(){ + console.log(this.name); + } +} + +//我们不能再继续写 module.exports = xxx。因为重新赋值,会把之前的赋值覆盖掉。 + +``` + +(2)module2.js: + +```javascript +//暴露方式一:module.exports = value + +//暴露一个函数出去 +module.exports = function(){ + console.log('我是 module2'); +} +``` + +注意,此时暴露出去的 exports 对象 等价于整个函数。 + +(3)module3.js: + +```javascript +//暴露方式二:exports.xxx = value + +//可以往 export 对象中不断地添加属性,进行暴露 + +exports.foo1 = function(){ + console.log('module3 中的 foo1 方法'); +} + +exports.foo2 = function(){ + console.log('module3 中的 foo2 方法'); +} + +exports.arr = [1,1,2,2,3,5,11]; + +``` + +(4)app.js:(将其他模块汇集到主模块) + +```javascript +//将其他模块汇集到主模块 + +let uniq = require('uniq'); //引入时,第三方模块要放在自定义模块的上面 + +let module1 = require('./modules/module1'); +let module2 = require('./modules/module2'); +let module3 = require('./modules/module3'); + +//调用module1对象的方法 +module1.foo(); + +//调用module2的函数 +module2(); //注意,在定义时,module2对象等价于整个函数function。所以,module2()的意思是,直接调用了函数。 + +//调用module3中的属性 +module3.foo1(); +module3.foo2(); + +uniq(module3.arr); //将module3中的数组进行去重操作 +console.log(module3.arr); //打印数组去重后的结果 +``` + +这样的话,我们的代码就写完了。 + +我们在命令行中输入`node app.js`,就可以把代码跑起来了。打印结果如下: + +```bash +我是 module1 +我是 module2 +module3 中的 foo1 方法 +module3 中的 foo2 方法 +[ 1, 11, 2, 3, 5 ] + +``` + + +## CommonJS 基于浏览器端的实现举例 + + +### 1、初始化项目 + +在工程文件中新建如下目录和文件: + +``` +js + dist //打包生成文件的目录 + src //源码所在的目录 + | module1.js + | module2.js + | module3.js + | app.js //应用主源文件 +index.html //因为CommonJS是基于浏览器端,js文件要跑在浏览器的页面上,所以要有这个html页面 +``` + +然后在根目录下新建如下命令: + +``` + npm init +``` + + +然后根据提示,依次输入如下内容: + +- **包名**:可以自己起包名,也可以用默认的包名。注意,包名里不能有中文,不能有大写。 + +- **版本**:可以用默认的版本 1.0.0,也可以自己修改包名。 + +其他的参数,一路回车即可。 + +于是,根目录下会自动生成`package.json`这个文件。点进去看一下: + +```json +{ + "name": "commonjs_browser", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} + + +``` + + +### 2、下载第三方包:Browserify + +这里需要用到[Browserify](http://browserify.org/)这个工具进行编译打包。Browserify 称为 CommonJS 的浏览器端的打包工具。 + +输入如下命令进行安装:(两个命令都要输入) + + +```javascript + npm install browserify -g //全局 + npm install browserify --save-dev //局部。 +``` + +上面的代码中,`-dev`表示开发依赖。这里解释一下相关概念: + +- 开发依赖:当前这个包,只在开发环境下使用。 + +- 运行依赖:当前这个包,是在生产环境下使用。 + + +### 3、自定义模块 & 代码运行 + +(1)module1.js: + +```javascript +//暴露方式一:module.exports = value + +//暴露一个对象出去 +module.exports = { + name: '我是 module1', + foo(){ + console.log(this.name); + } +} + +//我们不能再继续写 module.exports = xxx。因为重新赋值,会把之前的赋值覆盖掉。 + +``` + +(2)module2.js: + +```javascript +//暴露方式一:module.exports = value + +//暴露一个函数出去 +module.exports = function(){ + console.log('我是 module2'); +} +``` + +注意,此时暴露出去的 exports 对象 等价于整个函数。 + +(3)module3.js: + +```javascript +//暴露方式二:exports.xxx = value + +//可以往export对象中不断地添加属性,进行暴露 + +exports.foo1 = function(){ + console.log('module3 中的 foo1 方法'); +} + +exports.foo2 = function(){ + console.log('module3 中的 foo2 方法'); +} +``` + +(4)app.js:(将其他模块汇集到主模块) + +```javascript +let module1 = require('./module1'); // ./ 指的是当前路径 +let module2 = require('./module2'); +let module3 = require('./module3'); + +module1.foo(); +module2(); +module3.foo1(); +module3.foo2(); +``` + +引入的路径解释: + +- `./`是相对路径,指的是当前路径(app.js的当前路径是src) + + +到此,我们的主要代码就写完了。 + +但是,如果我们直接在index.html中,像下面这样写,是不行的:(因为浏览器不认识 require 关键字) + +```html + + + + + + + Document + + + + + + +``` + +为了能够让index.html引入app.js,我们需要输入如下命令: + +打包处理js: + +``` + browserify js/src/app.js -o js/dist/bundle.js +``` + +然后在index.html中引入打包后的文件: + +```html + +``` + + + + + + + + + + + + + + + diff --git "a/11-Node.js/05-Node.js\345\206\205\347\275\256\346\250\241\345\235\227\357\274\232fs\346\226\207\344\273\266\346\250\241\345\235\227.md" "b/11-Node.js/05-Node.js\345\206\205\347\275\256\346\250\241\345\235\227\357\274\232fs\346\226\207\344\273\266\346\250\241\345\235\227.md" new file mode 100644 index 00000000..68e38a18 --- /dev/null +++ "b/11-Node.js/05-Node.js\345\206\205\347\275\256\346\250\241\345\235\227\357\274\232fs\346\226\207\344\273\266\346\250\241\345\235\227.md" @@ -0,0 +1,398 @@ +--- +title: 05-Node.js内置模块:fs文件模块 +publish: true +--- + + + + + + +## Node.js 的官方API文档 + + +- Node.js 的API文档(英文): + +- Node.js 的API文档(中文): + +关于 Node.js 的内置模块和常见API,可以看官方文档。 + + +查阅文档时,稳定指数如下: + +- 红色:废弃。 + +- 橙色:实验。表示当前版本可用,其他版本不确定。也许不向下兼容,建议不要在生产环境中使用该特性。 + +- 绿色:稳定。与 npm 生态系统的兼容性是最高的优先级。 + + +## Node.js 中模块的分类 + + +Node.js 应用由模块组成,采用 CommonJS 模块规范。Node.js中的模块分为三种: + +- 内置模块 + +- 第三方模块 + +- 自定义模块 + +下面简单介绍一下。 + +### 1、内置模块 + +```js +const process = require('process'); +const path = require('path'); + +console.log(process.version); +console.log(path.resolve('../')); +``` + +require方法用于加载模块。 + +常见的内置模块包括: + +- FS:文件系统模块 + +- path:路径模块 + +- OS:操作系统相关 + +- net:网络相关 + +- http + +- ... + +你可能会有疑问:Node.js 这么牛吗?还能直接和操作系统做交互? + +带着这个疑问,我们不妨简单看看 Node.js 的源码,以 os 模块举例: + +- 打开os模块的源码:,翻到最底部,找到 `cpus`这个方法 + +- 进而找到 `getCPUs()` + +- internalBinding('os'):通过 internalBinding 可以调用系统底层的方法。internalBinding 主要是 JS 虚拟机在做的事情。 + +- `internalBinding('os')` 的实现,在 里,里面都是 C++ 的代码。比如有一个`getCPUs`方法。 + +现在你知道了,JS本身是没有能力获取底层系统资源的,这一切都是 JS虚拟机在和底层做交互,然后通过 JS 的表现形式,暴露给应用层。 + +另外,还有很多库,是直接使用C/++编写的,通过编译之后,再提供给 JS 应用层调用,或者直接提供给 Node.js层使用。 + +**所有的编程语言底层都会回归C/C++**,甚至是汇编语言。 + + +### 2、require 加载第三方包的机制 + +```js +const express = require('express'); +``` + +require 加载第三方包的机制: + +(1)第三方包安装好后,这个包一般会存放在当前项目的 node_modules 文件夹中。我们找到这个包的 package.json 文件,并且找到里面的main属性对应的入口模块,这个入口模块就是这个包的入口文件。 + +(2)如果第三方包中没有找到package.json文件,或者package.json文件中没有main属性,则默认加载第三方包中的index.js文件。 + +(3)如果在 node_modules 文件夹中没有找到这个包,或者以上所有情况都没有找到,则会向上一级父级目录下查找node_modules文件夹,查找规则如上一致。 + +(4)如果一直找到该模块的磁盘根路径都没有找到,则会报错:can not find module xxx。 + +### 3、自定义模块(module): + +每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。 + +举例: + +``` +var example = require('./example.js'); +console.log(example.x); // 5 +console.log(example.addX(1)); // 6 +``` + +## 读取文件 + +今天这篇文章,重点讲一下 Node 内置模块中的 **fs(文件处理模块)**。 + +在使用文件模块之前,记得先导入: + +```js +// 导入文件模块 +const fs = require('fs'); +``` + +fs 的英文全称是 File System。fs 模块提供了很多 api 方法,我们首先应该学习的方法是**文件读取**。 + +Node中文件读取的方式主要有以下几种。 + + +### 异步读取文件 fs.readFile() + + + +语法格式: + +```js +fs.readFile(file[, options], callback(error, data)) +``` + +代码举例: + +```javascript +const fs = require('fs'); + +fs.readFile('hello.txt', 'utf8', (err, data) => { + if (err) { + // 失败 + console.log(err) + } else { + // 成功 + console.log('异步读取数据:' + data2) + } +}); +``` + + +如果需要嵌套读取多个文件,可以用 promise 或者 async ... await 进行封装。代码举例如下。 + +### promise 封装 fs.readFile() + +```js +const fs = require('fs'); + +function fsRead(path) { + return new Promise((resolve, reject) => { + fs.readFile(path, { flag: 'r', encoding: "utf-8" }, (err, data) => { + if (err) { + //失败执行的内容 + reject(err) + } else { + //成功执行的内容 + resolve(data) + } + }) + }) +} + +var promise1 = fsRead('hello1.txt') +promise1.then(res1 => { + console.log(res1); + return fsRead('hello2.txt'); +}).then(res2 => { + console.log(res2); + return fsRead('hello3.txt'); +}).then(res3 => { + console.log(res); +}) + +``` + +### async ... await 封装 fs.readFile() + +这个写法更为简洁,推荐。 + +```js +var fs = require('fs'); + +function fsRead(path) { + return new Promise((resolve, reject) => { + fs.readFile(path, { flag: 'r', encoding: "utf-8" }, (err, data) => { + if (err) { + //失败执行的内容 + reject(err) + } else { + //成功执行的内容 + resolve(data) + } + }) + }) +} + +async function ReadList() { + var res1 = await fsRead('hello1.txt'); + var res2 = await fsRead('hello2.txt'); + var res3 = await fsRead('hello3.txt'); +} + +// 执行方法 +ReadList(); + +``` + + +### 同步读取文件 fs.readFileSync() + +语法格式: + +```js +fs.readFileSync(file[, options]) +``` + +代码举例: + +```javascript +const fs = require('fs'); + +try { + const data = fs.readFileSync('hello.txt', 'utf8'); + console.log(data); +} catch(e) { + // 文件不存在,或者权限错误 + throw e; +} +``` + +### Node.js 中的同步和异步的区别 + +fs模块对文件的几乎所有操作都有同步和异步两种形式。例如:readFile() 和 readFileSync()。 + +区别: + +- 同步调用会阻塞代码的执行,异步则不会。 + +- 异步调用会将 读取任务 下达到任务队列,直到任务执行完成才会回调。 + +- 异常处理方面:同步必须使用 try catch 方式,异步可以通过回调函数的第一个参数。【重要】 + +## 写入文件 + +语法格式: + +```js +fs.write(fd, string[, position[, encoding]], callback) + +``` + +async ... await 封装: + +```js +let fs = require('fs') + +function writeFs(path, content) { + return new Promise(function (resolve, reject) { + fs.writeFile(path, content, { flag: "a", encoding: "utf-8" }, function (err) { + if (err) { + //console.log("写入内容出错") + reject(err) + } else { + resolve(err) + //console.log("写入内容成功") + } + }) + }) +} + + +async function writeList() { + await writeFs('1.html', "

qianguyihao

"); + await writeFs('2.html', "

hello world

"); + await writeFs('3.html', "

永不止步

"); +} + +writeList() +``` + +## 删除文件 + +语法格式: + +```js +fs.unlink(path, callback) +``` + +参数说明: + +- path:文件路径。 +- callback:回调函数。 + + +代码举例: + +```js +fs.unlink('path/file.txt', (err) => { + if (err) throw err; + console.log('文件删除成功'); +}); + +``` + +备注:`fs.unlink()` 不能用于删除目录。 如果要删除目录,可以使用 `fs.rmdir()`。 + + +## Buffer + +通过 Buffer 开辟的内存空间,都是连续的内存空间,所以效率比较高。 + +代码举例1: + +```js + +// 将字符串转成 buffer 对象 +const str = 'qianguyihao'; +let buffer = Buffer.from(str); + +console.log(buffer); // 输出16进制编码 +console.log(buffer.toString()); // 输出字符串:qianguyihao +``` + +代码举例2: + +```js +// 从内存中开辟一个新的缓冲区 +let buffer = Buffer.alloc(20); +buffer[0] = 'a'; + +console.log(buffer); + +``` + + +## 读取目录 + + +语法格式: + +```js +fs.mkdir(path[, options], callback) +``` + +参数说明: + +- path:文件路径。 + +- options参数可以是: + - recursive:是否以递归的方式创建目录,默认为 false。 + - mode:设置目录权限,默认为 0777。 + + +代码举例: + +```js +var fs = require("fs"); +​ +console.log("查看 /tmp 目录"); +fs.readdir("/tmp/",function(err, files){ + if (err) { + return console.error(err); + } + files.forEach( function (file){ + console.log( file ); + }); +}); + +``` + + +其他的还有:(暂略) + +- 删除目录 + +- 输入输出 + + + + + diff --git "a/11-Node.js/06-Node.js\345\206\205\347\275\256\346\250\241\345\235\227\357\274\232path\350\267\257\345\276\204\346\250\241\345\235\227.md" "b/11-Node.js/06-Node.js\345\206\205\347\275\256\346\250\241\345\235\227\357\274\232path\350\267\257\345\276\204\346\250\241\345\235\227.md" new file mode 100644 index 00000000..c8516c56 --- /dev/null +++ "b/11-Node.js/06-Node.js\345\206\205\347\275\256\346\250\241\345\235\227\357\274\232path\350\267\257\345\276\204\346\250\241\345\235\227.md" @@ -0,0 +1,150 @@ +--- +title: 06-Node.js内置模块:path路径模块 +publish: true +--- + + + + + + +## path 路径模块 + +Node.js 通过`path`这个内置模块,提供了一些路径操作的API,具体可以参考官方的api文档。这里列举一些常用的API。 + +### path.extname() 获取文件/路径的扩展名 + +语法格式: + +```js + path.extname(myPath); +``` + +代码解释: + +- 获取 `myPath` 这个文件或者路径的扩展名。 + +- `myPath` 这个参数要求是字符串。如果 `myPath` 不是字符串,则抛出 TypeError。 + +代码举例: + +```js +const path = require('path'); + +path.extname('hello.txt'); // 返回 '.txt' + +path.extname('www.qianguyihao.com'); // 返回 '.com' + +path.extname('index.coffee.md'); // 返回 '.md' + +path.extname('index.'); // 返回 '.' + +path.extname('index'); // 返回 '' + +path.extname('.index'); // 返回 '' + +path.extname('.index.md'); // 返回 '.md' + +``` + +### path.resolve() 生成完成的绝对路径 + +语法格式: + +```js +path.resolve([...myPaths]) +``` + +解释: + +- 将路径或路径片段的序列解析为绝对路径。 + +- 返回的路径是**从右往左**处理,后面的每个 myPath 被依次解析,直到构造出一个完整的绝对路径。 + +代码举例: + +```js +const path = require('path'); + +let arr1 = ['/foo1/foo2', 'qianguyihao', 'foo3']; +let result1 = path.resolve(...arr1); +console.log(result1); // 打印结果:/foo1/foo2/qianguyihao/foo3 + +let arr2 = ['/foo1/foo2', '/qianguyihao', 'foo3']; +let result2 = path.resolve(...arr2); +console.log(result2); // 打印结果:/qianguyihao/foo3 +``` + +### 几个常见路径 + +- `__dirname`:这是一个常量,表示:当前执行文件所在**完整目录**。 + +- `__filename`:这是一个常量。表示:当前执行文件的**完整目录 + 文件名**。 + +- `process.cwd`:获取当前执行 Node命令 时的目录名。 + + +代码举例: + +```js +console.log(__dirname); + +console.log(__filename); + +console.log(process.cwd()); +``` + +运行结果: + +```bash +$ node app.js + +/Users/smyhvae/qianguyihao +/Users/smyhvae/qianguyihao/app.js +/Users/smyhvae/qianguyihao +``` + +### path.join() 将多个路径进行拼接 + +如果是我们手动拼接路径,容易出错。这个时候,可以利用 path.join() 方法将路径进行拼接。 + +语法格式: + +```js +path.join([...paths]); + +``` + +解释:使用平台特定的分隔符作为定界符将所有给定的 path 片段连接在一起,然后规范化生成的路径。 + +代码举例: + +```js +const path = require('path'); + +const result1 = path.join(__dirname, './app.js'); +console.log(result1); // 返回:/Users/smyhvae/qianguyihao/app.js + +const result2 = path.join('/foo1', 'foo2', './foo3'); +console.log(result2); // 返回:/foo1/foo2/foo3 + +const result3 = path.join('/foo1', 'foo2', '/foo3'); +console.log(result3); // 返回:/foo1/foo2/foo3 +``` + +## OS 系统模块 + + +- os.networkInterfaces() 查看网络地址 + + +## 我的公众号 + +想学习**更多技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 + +扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: + +![](https://img.smyhvae.com/20200102.png) + + + diff --git "a/11-Node.js/07-Node.js\346\223\215\344\275\234MySQL\346\225\260\346\215\256\345\272\223.md" "b/11-Node.js/07-Node.js\346\223\215\344\275\234MySQL\346\225\260\346\215\256\345\272\223.md" new file mode 100644 index 00000000..a894f7af --- /dev/null +++ "b/11-Node.js/07-Node.js\346\223\215\344\275\234MySQL\346\225\260\346\215\256\345\272\223.md" @@ -0,0 +1,335 @@ +--- +title: 07-Node.js操作MySQL数据库 +publish: true +--- + + + + + +## Node.js 连接 MySQL + +(1)安装 mysql 包: + +```bash +$ npm install mysql +``` + +(2)引入 mysql 包: + +```js +const mysql = require("mysql"); +``` + +(3)建立连接: + +```js +let mysql = require("mysql"); +let options = { + host: "localhost", + //port:"3306", //可选,默认3306 + user: "root", + password: 'xxx', // 这里改成你自己的数据库连接密码 + database: "qiangu_database", +}; +//创建与数据库进行连接的连接对象 +let connection = mysql.createConnection(options); + +//建立连接 +connection.connect((err) => { + if (err) { + // 数据库连接成功 + console.log(err); + } else { + // 数据库连接失败 + console.log("数据库连接成功"); + } +}); +``` + +正常来说,运行程序后,应该会提示`数据库连接成功`。 + +如果在运行时提示错误`Client does not support authentication protocol requested by server`,解决办法如下:(在终端进入 sql 之后,输入如下命令) + +```sql +# 注意,这里的 'root' 请填你的user账号, 'localhost' 请填 你的 host, 'password' 请填你的密码 +ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'; + +# 然后执行如下命令 +flush privileges; +``` + +## Node.js 增删改查 MySQL + +针对下面这张表: + +![](https://github.com/qianguyihao/Web/blob/master/img/20200418_1728.png) + + +通过 Node.js可以对其进行一些增删改查操作。代码举例如下。 + +### 1、查询表 + +```js +let mysql = require('mysql'); +let options = { + host: 'localhost', + //port:"3306",//可选,默认3306 + user: 'root', + password: 'xxx', // 这里改成你自己的数据库密码 + database: 'qiangu_database' +} +//创建与数据库进行连接的连接对象 +let connection = mysql.createConnection(options); + +//建立连接 +connection.connect((err) => { + if (err) { + // 数据库连接成功 + console.log(err) + } else { + // 数据库连接失败 + console.log('数据库连接成功') + } +}); + + +// 1、查询表 +let strSql1 = 'select * from qiangu_student_table'; +connection.query(strSql1, (err, result, fields) => { + if (err) { + // 表查询失败 + console.log(err); + } else { + // 表查询成功 + console.log('qiangu_student_table 表查询结果:' + JSON.stringify(result)); + console.log('fields:' + JSON.stringify(fields)); + } +}) + +``` + +打印结果如下: + +```bash +qiangu_student_table 表查询结果: +[{"id":1,"name":"千古壹号","age":28},{"id":2,"name":"许嵩","age":34},{"id":3,"name":"邓紫棋","age":28}] + +fields:[ + {"catalog":"def","db":"qiangu_database","table":"qiangu_student_table","orgTable":"qiangu_student_table","name":"id","orgName":"id","charsetNr":63,"length":11,"type":3,"flags":0,"decimals":0,"zeroFill":false,"protocol41":true}, + {"catalog":"def","db":"qiangu_database","table":"qiangu_student_table","orgTable":"qiangu_student_table","name":"name","orgName":"name","charsetNr":33,"length":765,"type":253,"flags":0,"decimals":0,"zeroFill":false,"protocol41":true}, + {"catalog":"def","db":"qiangu_database","table":"qiangu_student_table","orgTable":"qiangu_student_table","name":"age","orgName":"age","charsetNr":63,"length":11,"type":3,"flags":0,"decimals":0,"zeroFill":false,"protocol41":true} +] +``` + +### 删除表 + +```js +// 2、删除表 +let strSql2 = 'drop table test2_table'; +connection.query(strSql2, (err, result) => { + if (err) { + // 表删除失败 + console.log(err); + } else { + // 表删除成功 + console.log('表删除成功:' + result); + } +}); +``` + +打印结果: + +```bash +表删除成功: +OkPacket { + fieldCount: 0, + affectedRows: 0, + insertId: 0, + serverStatus: 2, + warningCount: 0, + message: '', + protocol41: true, + changedRows: 0 +} +``` + +### 删除数据库 + +将上方的sql语句换一下即可: + +```sql +let strSql3 = 'drop database qiangu_database'; + +``` + + +### 2、新建数据库 + +```js +let mysql = require('mysql'); +let options = { + host: 'localhost', + //port:"3306",//可选,默认3306 + user: 'root', + password: 'smyhvae001', + // database: 'qiangu_database' // 注意,因为代码里是创建新的数据库,所以这里不需要填其他的数据库名 +} +//创建与数据库进行连接的连接对象 +let connection = mysql.createConnection(options); + +//建立连接 +connection.connect((err) => { + if (err) { + // 数据库连接成功 + console.log(err); + } else { + // 数据库连接失败 + console.log('数据库连接成功') + } +}); + +// 创建新的数据库 +const strSql4 = 'create database qiangu_database3'; +connection.query(strSql4, (err, result) => { + if (err) { + console.log(err); + } else { + console.log('新建数据库成功:' + JSON.stringify(result)); + } + +}); + + +``` + +打印结果: + +```bash +数据库连接成功 +新建数据库成功:{ + "fieldCount":0,"affectedRows":1,"insertId":0,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0 +} + +``` + + + +### 3、新建表 + +新建表的sql语句举例: + +```sql +CREATE TABLE `qiangu_table5` ( + `id` int NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `age` int DEFAULT NULL, + PRIMARY KEY (`id`) +); +``` + +如果是在 js 代码中执行上面这样命令的话,要记得把 sql 语句存放在字符串里的同一行。 + +代码举例如下: + +```js +let mysql = require('mysql'); +let options = { + host: 'localhost', + //port:"3306",//可选,默认3306 + user: 'root', + password: 'smyhvae001', + database: 'qiangu_database' +} +//创建与数据库进行连接的连接对象 +let connection = mysql.createConnection(options); + +//建立连接 +connection.connect((err) => { + if (err) { + // 数据库连接成功 + console.log(err); + } else { + // 数据库连接失败 + console.log('数据库连接成功') + } +}); + + +// 新建表 +// 注意,在 js 代码中,sql 语句要存放在字符串里的同一行。 +const strSql5 = 'CREATE TABLE `qianguyihao_table5` (`id` int NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`age` int DEFAULT NULL,PRIMARY KEY (`id`));'; + +connection.query(strSql5, (err, result) => { + if (err) { + // 新建表失败 + console.log(err); + } else { + // 新建表成功 + console.log('qianguyihao 新建表成功:' + JSON.stringify(result)); + } +}) + +``` + +打印结果: + +```bash +数据库连接成功 +qianguyihao 新建表成功: +{ + "fieldCount":0,"affectedRows":0,"insertId":0,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0 +} +``` + + +### 在指定的表中插入数据 + +在指定的表中插入数据: + +```js +// 在指定的表中插入数据 +const strSql6 = "insert into qianguyihao_table5 (name, age) values ('千古壹号', '28')"; + +connection.query(strSql6, (err, result) => { + if (err) { + // 插入数据失败 + console.log(err); + } else { + // 在指定的表中插入数据成功 + console.log('qianguyihao 在指定的表中插入数据成功:' + JSON.stringify(result)); + } +}); + +``` + +打印结果: + +```bash +qianguyihao 在指定的表中插入数据成功: +{ + "fieldCount":0,"affectedRows":1,"insertId":1,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0 +} +``` + +如果插入的数据是变量(比如是用户提交上来的数据),那么,sql 语句可以这样写: + +```js +// 在指定的表中插入数据(数据作为变量) +const strSql7 = "insert into qianguyihao_table5 (name, age) values (?, ?)"; + +connection.query(strSql7, ['许嵩', '34'], (err, result) => { + if (err) { + // 插入数据失败 + console.log(err); + } else { + // 在指定的表中插入数据成功 + console.log('qiangauyihao 在指定的表中插入数据成功:' + JSON.stringify(result)); + } +}); + +``` + + + + diff --git a/11-Node.js/CommonJS.md b/11-Node.js/CommonJS.md new file mode 100644 index 00000000..f09b7af6 --- /dev/null +++ b/11-Node.js/CommonJS.md @@ -0,0 +1,122 @@ +--- +title: 01-数据库的基础知识 +publish: false +--- + + + + + + + +## 全局对象 + +### global + +类似于客户端 JavaScript 运行环境中的 window。 + + +## process + +用于获取当前的 Node 进程信息,一般用于获取环境变量之类的信息。 + +### console + +Node 中内置的 console 模块,提供操作控制台的输入输出功能,常见使用方式与客户端类似。 + +## 全局函数 + +- setInterval(callback, millisecond) + +- clearInterval(timer) + +- setTimeout(callback, millisecond) + +- clearTimeout(timer) + +- Buffer:Class + - 用于操作二进制数据 + - 以后介绍 + + +## Node 调试 + +### 最简单的调试 + +最方便也是最简单的调试:console.log() + + +### Node 原生的调试 + +网址: + +### 第三方模块提供的调试工具 + +``` +$ npm install node-inspector –g //方式一 + + +$ npm install devtool -g //方式二 +``` + +### 开发工具的调试 + +- Visual Studio Code + +- WebStorm + +## 模块化结构 + +Node 实现 CommonJS 规范,所以可以使用模块化的方式组织代码结构。 + +- Node 采用的模块化结构是按照 CommonJS 规范。 + +- 模块与文件是一一对应关系,即加载一个模块,实际上就是加载对应的一个模块文件。 + +### CommonJS 规范 + +CommonJS 就是一套约定标准,不是技术。用于约定我们的代码应该是怎样的一种结构。 + +参考链接: + +- + +### 常用内置模块 + +- `path`:处理文件路径。 + +- `fs`:操作(CRUD)文件系统。 + +- `child_process`:新建子进程。 + +- `util`:提供一系列实用小工具。 + +- `http`:提供 HTTP 服务器功能。 + +- `url`:用于解析 URL。 + +- `querystring`:解析 URL 中的查询字符串。 + +- `crypto`:提供加密和解密功能。 + + +总结:更多内容可以参考 api文档: + + +## 文件系统操作 + +### 相关模块 + +- fs:基础的文件操作 API + +- path:提供和路径相关的操作 API + +- readline:用于读取大文本文件,一行一行读 + +- fs-extra(第三方): + + + + + + diff --git a/11-Node.js/ES6.md b/11-Node.js/ES6.md new file mode 100644 index 00000000..aca50e30 --- /dev/null +++ b/11-Node.js/ES6.md @@ -0,0 +1,161 @@ +--- +title: 01-数据库的基础知识 +publish: false +--- + + + + + + +## 前言 + +ECMAScript 是 JS 的语言标准。而 ES6 是新的 JS 语法标准。 + + +### 发展历史 + +20180303_1633.png + +- 2015年6月,ES6正式发布。 + + +### ES6 的其他优势 + +- 使用 babel 语法转换器,支持低端浏览器 + +- 流行的库基本都是基于 ES6 构建。 React 默认使用 ES6 新源发开发。 + + +## ES6 的常用语法 + +### ES6语法概览 + +- 块级作用域、字符串 + +- 对象扩展、解构 + +- 类、模块化等。 + + +### 作用域:let 和 const + +- 用 `let`定义变量 ,替代 var + +- 用const 定义常量(定义后,不可修改) + +- 作用域和 {} + + +举例: + +```javascript + let a1 = 'haha'; + + const name = `smyhvae`; +``` + + +### 模板字符串 + +我们以前让字符串进行拼接的时候,是这样做的:(传统写法的字符串拼接) + +```javascript + var name = 'smyhvae'; + var age = '26'; + console.log('name:'+name+',age:'+age); //传统写法 +``` + + +这种写法,比较繁琐,而且容易出错。 + +现在有了 ES6 语法,字符串拼接可以这样写: + +```javascript + var name = 'smyhvae'; + var age = '26'; + + console.log('name:'+name+',age:'+age); //传统写法 + + console.log(`name:${name},age:${age}`); //ES6 写法 + +``` + +注意,上方代码中,倒数第二行用的是单引号,最后一行用的是反引号(在tab键的上方)。 + + +### 函数扩展 + +ES6 中函数的用法: + +- 参数默认值 + +- 箭头函数 + +- 展开运算符 + + + +定义和调用函数:(传统写法) + +```javascript + function fn1(name) { + console.log(name); + } + + fn1('smyhvae'); +``` + + +定义和调用函数:(ES6写法) + +```javascript + var fn2 = (name)=>{ + console.log(name); + } + + fn2('smyhvae'); +``` + + +上面两端代码,执行的结果是一样的。 + +当然,也可以给上面这个函数的参数加一个默认值: + +```javascript + var fn2 = (name='enen')=>{ + console.log(name); + } + + fn2(); //参数用默认值 enen + fn2('smyhvae'); +``` + + + +比如说,1秒后执行一段代码,可以用箭头函数: + +```javascript + setTimeout(()=>{ + console.log('something'); + },1000); +``` + +如果函数体只有一条 return 语句,那么大括号可以省略: + +```javascript + const myDouble = x=>x*2; + console.log(myDouble(5)); //打印结果为10 + +``` + + +箭头函数的好处: + +- 简写代码 + +- 保持 this 的作用域 + + + +## \ No newline at end of file diff --git "a/11-Node.js/JavaScript\346\250\241\345\235\227\345\214\226\357\274\232AMD.md" "b/11-Node.js/JavaScript\346\250\241\345\235\227\345\214\226\357\274\232AMD.md" new file mode 100644 index 00000000..5e9a2920 --- /dev/null +++ "b/11-Node.js/JavaScript\346\250\241\345\235\227\345\214\226\357\274\232AMD.md" @@ -0,0 +1,212 @@ +--- +title: JavaScript模块化:AMD +publish: true +--- + + + + + + +## AMD的基本语法 + +### AMD的概念 + +**AMD**(Asynchronous Module Definition):异步模块定义。AMD专门用于浏览器端,模块的加载是异步的。 + +[**AMD规范**](https://github.com/amdjs/amdjs-api):是 **[RequireJS](http://requirejs.org/)** 在推广过程中对模块化定义的规范化产出。 + +RequireJS:一个基于AMD规范实现的模块化开发解决方案。 + + +### 暴露模块的方式 + +**定义没有依赖的模块**:(参数只有一个 function) + +```javascript +define(function () { + + return 模块 + +}) +``` + + +**定义有依赖的模块**:(参数有两个:模块名、function) + +```javascript +//定义有依赖的模块:第一个参数为数组 +define(['module1', 'module2'], function (m1, m2) { + + return 模块 + +}) +``` + +代码解释: + +- 第一个参数必须是数组,里面存放的是,需要依赖的其他的模块。 + +- 第二个参数是function,里面带了形参 m1 和 m2,分别代表了 module1 和 module2。这个形参的作用是,前面依赖的模块一旦声明了,就可以一一对应地注入到 function中去,从而在 function 内部使用依赖的模块。这种方式称之为**显式声明依赖注入**。 + +### 引入模块的方式 + +在主模块中引入其他的模块: + + +```javascript +//在主模块中引入其他的模块 +require(['module1', 'module2'], function (m1, m2) { + + 使用m1 / m2 + +}) +``` + +### RequireJS:是AMD的实现 + +- + +- + +## RequireJS的使用举例(自定义模块) + +### 1、创建项目结构 + +在工程文件中新建如下目录: + + + ``` +js + | libs + + | modules + | alerter.js + | dataService.js + | main.js + +index.html + ``` + +所有的代码写完之后,项目结构如下: + +![](http://img.smyhvae.com/20180411_1331.png) + + +### 2、下载require.js,并导入 + +- 官网: + +- GitHub: + +在官网下载`require.js`文件: + +![](http://img.smyhvae.com/20180411_1127.png) + +然后将`require.js`文件拷贝到项目的`js/libs/`目录中。 + +这样的话,就导入成功了。 + +### 3、自定义模块 + +(1)dataService.js: + +```javascript +//定义没有依赖的模块 +define(function () { + let name = '我是 dataService.js中的内容'; + function getName() { + return name; + } + + //暴露模块 + return { getName }; +}); +``` + + +这模块没有依赖。 + +(2)alerter.js: + +```javascript +//定义有依赖的模块 +define(['myDataService'], function (dataService) { + let msg = '我是 aleter.js中的内容'; + function showMsg() { + console.log(dataService.getName()); //调用了 myDataService 模块中的内容 + console.log(msg); + } + + //暴露模块 + return { showMsg }; + +}); +``` + +这个模块,依赖了`myDataService`这个模块,模块名是我自己起的。稍后,我们会在main.js中做映射,将`myDataService`这个名字和`dataService.js`文件关联起来。 + +(3)main.js: + +> 这个是主模块。 + +```javascript +requirejs.config({ + //baseUrl: 'js/', //基本路径 + paths: { //配置路径 + myDataService: './modules/dataService', + myAlerter: './modules/alerter' + } +}); + +requirejs(['myAlerter'], function (alerter) { + alerter.showMsg(); +})(); +``` + +这个模块,依赖了`myAlerter`这个模块,模块名是我自己起的。并且,我们在文件的上方做了映射,将`myAlerter`这个名字和`alerter.js`文件关联了起来。 + + +我们来讲一下最上方的几行代码(即`requirejs.config`里的内容)的意思: + +- 我们可以看到,文件(3)依赖了文件(2),文件(2)依赖了文件(1)。 + +- `paths`里做的就是映射:将键`myDataService`和文件`dataService.js`进行关联,将键`myAlerter`和文件`alerter.js`进行关联。 + +另外,再讲一下注释里的`baseUrl`的用法:如果没有这个注释,那么`paths`里的路径,是从**当前这个文件**(main.js)的角度出发的;如果加了一行`baseUrl`,表明它是 paths 里所有路径的最开头的部分,`baseUrl`的路径是从**项目的根目录**的角度出发的。 + +(4)index.html: + +这个是入口文件。 + + +```html + + + + + + + Document + + + + + + +``` + +注意,上面的代码中,我们直接通过`src`属性引入`requre.js `文件,一旦这个文件发挥作用了,会去找`data-main`属性里的指向,它正好指向的是主模块。 + +有了上面这种引入的方式,我们就不用再老土地引入多个` + + + + + +``` + +打印结果: + +![](http://img.smyhvae.com/20180412_1955.png) + + + + + + +## others + + +### SeaJS 的介绍 + +SeaJS:一个基于CMD规范实现的模块化开发解决方案。 + +作者:Alibaba 玉伯。 + +官网: + +GitHub: + +现在官网变成了: + +特性: + +- 简单友好的模块定义规范。 + +- 自然直观的代码组织方式。 + +![](http://img.smyhvae.com/20180303_2107.png) + +### RequireJS(AMD)、SeaJS(CDM)、CommonJS、ES6 的对比 + +1、RequireJS 和 AMD: + +![](http://img.smyhvae.com/20180303_1653.png) + +异步模块定义,特点是依赖前置。 + +2、SeaJS 和 CMD: + + +同步模块定义。 + +```javascript + // 所有模块都通过 define 来定义 + define(function(require, exports, module) { + + //通过 require 引入依赖 + + var $ require(`jquery`); + + var Spinning = require(`./spinning`); + }) +``` + +3、CommonJS: + +![](http://img.smyhvae.com/20180303_1701.png) + +以上三个都是 ES5里面的规范。 + +4、ES6: + +ES6的特性:export/import + +![](http://img.smyhvae.com/20180303_1704.png) + + diff --git "a/11-Node.js/JavaScript\346\250\241\345\235\227\345\214\226\357\274\232ES6.md" "b/11-Node.js/JavaScript\346\250\241\345\235\227\345\214\226\357\274\232ES6.md" new file mode 100644 index 00000000..c1069744 --- /dev/null +++ "b/11-Node.js/JavaScript\346\250\241\345\235\227\345\214\226\357\274\232ES6.md" @@ -0,0 +1,326 @@ +--- +title: JavaScript模块化:ES6 +publish: true +--- + + + + + +## 模块化开发的引入 + +### JS开发的弊端 + +JS 在使用时存在两大问题,而 Node.js 可以很好地避免这两个问题: + +- 文件依赖。比如 a 文件依赖 b 文件,b 文件依赖 c 文件。而 Node.js 中的文件依赖,不需要人工维护和人为分析。 + +- 命名冲突。js 的各个文件是相互开放的,容易导致命名冲突。而 Node.js 是属于半封闭的状态,可以指定哪些内容是开放的,哪些内容是封闭的。 + +Node.js 在解决这两个问题时,用到的就是模块化开发。 + +### 软件开发中的模块化开发 + +一个功能就是一个模块,多个模块可以组成完整的应用,抽离一个模块不会影响其他功能的运行。 + +效果如下: + +![](http://img.smyhvae.com/20200409_1934.png) + +### Node.js 中的模块化开发 + +Node.js 规定,一个 JS 文件就是一个模块,模块内部定义的变量和函数默认情况下在外部无法访问。 + +模块内部可以使用 `exports` 对象进行成员导出, 使用 `require` 方法导入其他模块。效果如下: + +![](http://img.smyhvae.com/20200409_1932.png) + +## ES6模块化的基本语法 + +### ES6模块化的说明 + +**依赖模块需要编译打包处理**。原因如下: + +- (1)有些浏览器不支持 ES6 的语法,写完 ES6 的代码后,需要通过`Babel`将 ES6 转化为 ES5。 + +- (2)生成了ES5之后,里面仍然有`require`语法,而浏览器并不认识`require`这个关键字。此时,可以用 `Browserify`编译打包 js,进行再次转换。 + +推荐学习链接: + +- + + +### 基本语法: + + +**导出模块**: + +``` + export +``` + + +**引入模块**: + +``` + import xxx from '路径' +``` + + +## ES6模块化的使用举例(自定义模块) + +### 1、初始化项目 + +(1)在工程文件中新建如下目录: + + +``` +js + | src + | module1.js + | module2.js + | module3.js + | main.js + + +index.html +``` + +(2)在工程的根目录下,新建文件`package.json`,内容如下: + +```json +{ + "name": "es6-babel-browserify", + "version": "1.0.0" +} +``` + +### 2、环境配置:安装babel 和 browserify等 + +(1)安装babel 和 browserify: + +```bash + npm install babel-cli -g + + npm install babel-preset-es2015 --save-dev + + npm install browserify -g +``` + + +安装 babel 的详细解释,可以参考本人的另外一篇文章:[ES6的介绍和环境配置](https://github.com/smyhvae/Web/blob/master/10-ES6/03-ES6%E7%9A%84%E4%BB%8B%E7%BB%8D%E5%92%8C%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE.md) + +(2)新建.babelrc: + +在根目录下新建文件`.babelrc`,输入如下内容: + +``` +{ + "presets":[ + "es2015" + ], + "plugins":[] +} +``` + +### 3、编写代码 + + +(1)module1.js: + +```javascript +//暴露模块:采用分别暴露的方式 + +export function foo1() { + console.log('我是 module1 中的 foo1'); +} + +export function foo2() { + console.log('我是 module2 中的 foo2'); +} + +export let arr = [1, 2, 3, 4, 5]; +``` + + + +(2)module2.js: + +```javascript +//暴露模块:采用统一暴露的方式 + +function fn1() { + console.log('我是 module2 中的 fn1'); +} + +function fn2() { + console.log('我是 module2 中的 fn2'); +} + +//统一暴露 +export { fn1, fn2 }; +``` + + +(3)module3.js: + + + +```javascript +//暴露模块:采用默认暴露的方式。 +//默认暴露的方式可以暴露任意数据类型,暴露的是什么数据,接收到的就是什么数据 + +//语法格式:export default value; +export default () => { + console.log('我是 module3 中 default 方式暴露的函数'); +}; +``` + + +这里,我们采取了一种新的暴露方式(默认暴露),在暴露时,加上了`default`这个关键字。代码里暴露了一个箭头函数,稍后,我们注意在main.js里是怎么引入module3.js的。 + +注意,我们只能写一次 default,也就是说,只能进行一次默认暴露。 + +(4)module4.js:(default方式暴露多个属性) + +```javascript +//暴露模块:采用默认暴露的方式。 +//默认暴露的方式可以暴露任意数据类型,暴露的是什么数据,接收到的就是什么数据 + +//语法格式:export default value; +export default { + name: '我是 module4 中 default 方式暴露的属性 name', + foo() { + console.log('我是 module4 中 default 方式暴露的函数 foo'); + } +} +``` + +这里,我们依旧采取了默认暴露的方式,只能写一次 default。代码里暴露了一个对象(对象里存放了一个属性、一个方法)。稍后,我们注意在main.js里是怎么引入module4.js的。 + +如果我想暴露多个属性、多个对象怎呢?很简单,把你想要暴露的所有内容,都放在default里,包成一个对象。你看module4.js就是如此, 同时暴露了多个属性&方法。 + +(5)main.js: + +这个是主模块。现在,我们来看一下,它如何引入上面的四个模块。 + + +```javascript + +//主模块。引入其他的模块 + +import { foo1, foo2 } from './module1'; //采用解构赋值的形式进行导入。注意,括号里的对象名,要和 module1 中的对象名一致。 +import { fn1, fn2 } from './module2'; //采用解构赋值的形式进行导入。注意,括号里的对象名,要和 module2 中的对象名一致。 +import myModule3 from './module3'; //module3 模块是采用 default 方式进行暴露的,myModule3 这个名字是我随便起的 +import myModule4 from './module4'; //module4 模块是采用 default 方式进行暴露的,myModule4 这个名字是我随便起的 + +//调用module1、module2中的内容 +foo1(); +foo2(); +fn1(); +fn2(); + +//调用module3中的内容 +myModule3(); + +//调用module4中的内容 +console.log(myModule4.name); //module4中的属性 +myModule4.foo(); //module4中的方法 +``` + +我们可以看出:(具体请看注释,非常重要) + +- module1和module2是采用**常规暴露**的形式,在引入它们时,模块名要一致。而且,要求用**对象解构赋值**的形式,而不是用 `import myModule from ...`这种形式(否则会报错 undefined)。 + +- module2和module3是采用**默认暴露**的形式,在引入它们时,模块名随便起。 + +(6)index.html: + +在这里引入main.js即可。 + +```html + + + + + + + + Document + + + + + + + + +``` + + +### 4、编译转换 + +如果我们不进行转换,而是直接在 index.html 中加载 js/src/main.js,是会报错的: + + +接下来,我们就进行转换。 + +(1)利用 babel 将 ES6 转换为 ES5: + +``` +babel src -d build //build目录会自动生成 +``` + +上方命令的意思是,将`src`目录下的所有ES6文件转化为ES5文件,并放在`build`目录下(`build`目录会被自动创建)。 + +转化成ES5之后,我们发现,如果直接在 index.html 中加载`build`目录下的ES5文件,也是会报错的,因为浏览器不认识`main.js`里的`require`关键字: + +![](http://img.smyhvae.com/20180414_1410.png) + + +于是,我们还要进行一次转换。 + +(2)利用`Browserify`编译打包 `build`目录下的 ES5 文件: + +```bash +browserify build/main.js -o dist/main.js //dist目录需要手动创建 +``` + +dist/main.js就是我们需要引入到 index.html 里的文件。 + +以后,我们每次修改完ES6的代码,就要执行上面的两个命令,重新生成新的js文件。 + + +运行效果: + +![](http://img.smyhvae.com/20180414_1615.png) + + +工程文件: + +- [2018-04-13-ES6Demo.rar](https://download.csdn.net/download/smyhvae/10348940) + + +## ES6模块化的使用举例(引入第三方模块) + +下载 jQuery 包: + +``` +npm install jquery@1 //下载jQuery 1.X 的版本里最新的 +``` + +在main.js 中引入上面的 jQuery: + +``` +import $ from 'jQuery'; +``` + + +然后我们就可以通过`$`这个符号去写jQuery的代码了。 + + + + + + + diff --git a/11-Node.js/KOA2.md b/11-Node.js/KOA2.md new file mode 100644 index 00000000..e2d6f5cb --- /dev/null +++ b/11-Node.js/KOA2.md @@ -0,0 +1,13 @@ +--- +title: 01-数据库的基础知识 +publish: false +--- + + + + + +## KOA2 简介 + +KOA已经发展到了第二个版本,简称 KOA2。突出的特点是插件和中间件, + diff --git "a/11-Node.js/Node.js\344\273\243\347\240\201\344\270\276\344\276\213.md" "b/11-Node.js/Node.js\344\273\243\347\240\201\344\270\276\344\276\213.md" new file mode 100644 index 00000000..4dac89a5 --- /dev/null +++ "b/11-Node.js/Node.js\344\273\243\347\240\201\344\270\276\344\276\213.md" @@ -0,0 +1,88 @@ +--- +title: 01-数据库的基础知识 +publish: false +--- + + + + + + + +## 在 Node.js 上建一个 http 服务器 + + +(1)新建一个文件 `server01.js`,然后在里面输入如下代码: + +```javascript + +const http = require('http'); //引入 node.js里面的一个http包。因为引入之后,我们不会去修改它,所以用常量来表示 + + +// 创建一台服务器 +var server = http.createServer(function (){ //当有人来访问这台服务器时,就会执行 function 回调函数 + console.log('有人来访问我了'); +}); + +server.listen(8080); //要让服务器设置为监听状态,端口设置为8080 + +``` + +注意看注释。 + +我们把上面这个 js 文件跑起来,然后在浏览器端输入`http://localhost:8080/`,每请求一次,服务器的控制台就会打印 `有人来访问我了`。 + + +(2)write()函数和 end()函数: + +将上面的代码修改如下: + +server02.js: + +```javascript +const http = require('http'); + + +// 创建一台服务器 +var server = http.createServer(function (request, response) { //当有人来访问这个服务器时,就会执行function 这个回调函数 + console.log('有人来访问我了'); + + response.write('smyhvae'); //向浏览器输出内容 + response.end(); //结束了,浏览器你走吧。 + +}); + +server.listen(8080); + + +``` + +function 回调函数里可以设置两个参数:request 和 response。`response.write()`表示向浏览器输出一些内容。 + +将上面的 js 代码跑起来,产生的问题是,无论我们在浏览器端输入`http://localhost:8080/1.html`,还是输入`http://localhost:8080/2.jpg`,浏览器上显示的都是`smyhvae`。 + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/11-Node.js/WebSocket.md b/11-Node.js/WebSocket.md new file mode 100644 index 00000000..02b0a61b --- /dev/null +++ b/11-Node.js/WebSocket.md @@ -0,0 +1,77 @@ +--- +title: 01-数据库的基础知识 +publish: false +--- + + + + + + + +## WebSocket 的引入 + +### 背景分析 + +HTTP协议是无状态的,服务器只会响应来自客户端的请求,但是它与客户端之间不具备持续连接。 + + +当用户在浏览器上进行操作时,可以请求服务器上的api;但是反过来却不可能:服务器端发生了一个事件,无法将这个事件的信息**实时主动**地通知客户端。只有在客户端查询服务器当前状态时,所发生事件的信息才会从服务器传递到客户端。 + + +那怎么去实时地知道服务器的状态呢?方法有两个: + +(1)**轮询**:客户端每隔很短的时间,都会对服务器发出请求,查看是否有新的消息,只要轮询速度足够快,例如1秒,就能给人造成交互是实时进行的印象。这种做法是无奈之举,实际上对服务器、客户端双方都造成了大量的性能浪费。 + + +(2)**长连接**:客户端只请求一次,但是服务器会将连接保持,不会返回结果。当服务器有了新数据时,实时地发给客户端,而一直保持挂起状态。这种做法的也造成了大量的性能浪费。 + +### WebSocket 协议 + +最新的 HTML5协议,制定了 WebSocket 协议标准,允许客户端和服务器端以**全双工**的方式进行通信。 + +WebSocket 的原理非常简单:利用HTTP请求产生握手,HTTP头部含有 WebSocket 协议的请求,**握手之后,二者转用TCP协议进行交流*(QQ的协议)。 + +WebSocket协议需要浏览器和服务器都支持才可以使用: + + +- 支持WebSocket协议的浏览器有:Chrome 4、火狐4、IE10、Safari5 + +- 支持WebSocket协议的服务器有:Node 0、Apach7.0.2、Nginx1.3 + + +### http 长连接和 websocket 的长连接区别 + +HTTP1.1通过使用Connection:keep-alive进行长连接,HTTP 1.1默认进行持久连接。在一次 TCP 连接中可以完成多个 HTTP 请求,但是对每个请求仍然要单独发 header,Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。 + +websocket是一个真正的全双工。长连接第一次tcp链路建立之后,后续数据可以双方都进行发送,**不需要发送请求头**。 + +keep-alive双方并没有建立正真的连接会话,服务端可以在任何一次请求完成后关闭。WebSocket 它本身就规定了是正真的、双工的长连接,两边都必须要维持住连接的状态。 + +### Socket.IO 的引入 + +Node.js上需要写一些程序,来处理TCP请求。 + +Node.js从诞生之日起,就支持 WebSocket 协议。不过,从底层一步一步搭建一个Socket服务器很费劲(想象一下Node写一个静态文件服务都那么费劲)。所以,有大神帮我们写了一个库 Socket.IO。 + +Socket.IO 是业界良心,新手福音。它屏蔽了所有底层细节,让顶层调用非常简单。并且还为不支持 WebSocket 协议的浏览器,提供了长轮询的透明模拟机制。 + +Node的单线程、非阻塞I/O、事件驱动机制,使它非常适合Socket服务器。 + +### Socket.IO 的安装 + +Socket.IO 的官网是: + +安装方式: + +``` + npm install socket.io +``` + + + + + + + + diff --git "a/11-Node.js/\344\272\213\344\273\266\351\251\261\345\212\250\345\222\214\351\235\236\351\230\273\345\241\236\346\234\272\345\210\266.md" "b/11-Node.js/\344\272\213\344\273\266\351\251\261\345\212\250\345\222\214\351\235\236\351\230\273\345\241\236\346\234\272\345\210\266.md" new file mode 100644 index 00000000..fc03c10d --- /dev/null +++ "b/11-Node.js/\344\272\213\344\273\266\351\251\261\345\212\250\345\222\214\351\235\236\351\230\273\345\241\236\346\234\272\345\210\266.md" @@ -0,0 +1,146 @@ +--- +title: 01-数据库的基础知识 +publish: false +--- + + + + + + +## 异步编程 + +### 异步操作 + +- Node 采用 Chrome V8 引擎处理 JavaScript 脚本。V8 最大特点就是**单线程运行**,一次只能运行一个任务。 + +- Node 大量采用异步操作(asynchronous operation),即任务不是马上执行,而是插在任务队列的尾部,等到前面的任务运行完后再执行。 + +- 提高代码的响应能力。 + + +异步IO也叫非阻塞IO。例如读文件,传统的语言,基本都是读取完毕才能进行下一步操作。非阻塞就是Node的callback,不会影响下一步操作,等到文件读取完毕,回调函数自动被执行,而不是在等待。 + +### 异步操作回调 + +由于系统永远不知道用户什么时候会输入内容,所以代码不能永远停在一个地方。 + +Node 中的操作方式就是以异步回调的方式解决无状态的问题。 + + +### 回调函数的设计:错误优先 + +异步操作中,无法通过 try catch 捕获异常。 + +这是因为回调函数主要用于异步操作,当回调函数运行时,前期的操作早结束了,错误的执行栈早就不存在了,传统的错误捕捉机制try…catch对于异步操作行不通,所以只能把错误交给回调函数处理。 + +**统一约定:** + +回调函数的第一个参数默认接收错误信息,第二个参数才是真正的回调数据(便于外界获取调用的错误情况): + +``` +foo1('赵小黑', 19, function(error, data) { + if(error) throw error; + console.log(data); +}); +``` + + +### 异步回调的问题 + +相比较于传统的代码: + +- 异步事件驱动的代码 + +- 不容易阅读 + +- 不容易调试 + +- 不容易维护 + +另外还有个问题是**回调地狱:** + +```javascript +do1(function() { + do2(function() { + do3(function() { + do4(function() { + do5(function() { + do6() + }); + }); + }); + }); +}); + +``` + + +## 进程和线程 + +### 进程(进行中的程序) + +- 每一个 **正在运行** 的应用程序都称之为进程。 + +- 每一个应用程序运行都至少有一个进程。 + +- 进程是用来给应用程序提供一个运行的环境。 + +- 进程是操作系统为应用程序分配资源的一个单位。 + + +### 线程 + +- 用来执行应用程序中的代码 + +- 在一个进程内部,可以有很多的线程 + +- 在一个线程内部,同时只可以干一件事 + +- 传统的开发方式大部分都是 I/O 阻塞的,所以需要多线程来更好的利用硬件资源。 + +线程并不是越多越好。 + +### 多线程的弊端 + +缺点一: + + - 创建线程耗费。 + - 线程数量有限。 + - CPU 在不同线程之间转换,有个上下文转换,这个转换非常耗时。 + +所谓的多线程其实都是假的,对于单核CPU而言,它们无非是在抢占 CPU 资源。线程和线程之间需要**切换和调度**,这是很耗费资源的。 + +缺点二: + +- 线程之间共享某些数据,同步某个状态都很麻烦。 + +就算 CPU 是多核的,现在的问题是,线程与线程之间如果要共享数据,该怎么办?比如 A 线程要访问 B 线程的变量。 + + + +## 事件驱动和非阻塞机制 + + +参考链接: + + +总结: + +- Node 中将所有的阻塞操作交给了内部线程池实现。 + +- Node 主线程本身,主要就是不断的**往返调度**。 + + +### 平台实现差异 + + +由于 Windows 和 *nix 平台(其他平台)的差异,Node 提供了 libuv 作为抽象封装层,保证上层的 Node 与下层的自定义线程池及 IOCP 之间各自独立。 + +如下图所示: + +![](http://img.smyhvae.com/20180301_2252.png) + + + + diff --git "a/11-Vue\345\237\272\347\241\200/Vue-router\350\267\257\347\224\261.md" "b/11-Vue\345\237\272\347\241\200/Vue-router\350\267\257\347\224\261.md" deleted file mode 100644 index 72738c5e..00000000 --- "a/11-Vue\345\237\272\347\241\200/Vue-router\350\267\257\347\224\261.md" +++ /dev/null @@ -1,6 +0,0 @@ - - -## 前言 - -路由:就是SPA(单页应用)的**路径管理器**。 - diff --git "a/12-Vue\345\237\272\347\241\200/01-Vue\347\232\204\344\273\213\347\273\215\345\222\214vue-cli.md" "b/12-Vue\345\237\272\347\241\200/01-Vue\347\232\204\344\273\213\347\273\215\345\222\214vue-cli.md" new file mode 100644 index 00000000..6a70d221 --- /dev/null +++ "b/12-Vue\345\237\272\347\241\200/01-Vue\347\232\204\344\273\213\347\273\215\345\222\214vue-cli.md" @@ -0,0 +1,354 @@ +--- +title: 01-Vue的介绍和vue-cli +publish: true +--- + + + + + + + +## MVVM模式 + +![](http://img.smyhvae.com/20180420_2150.png) + +- Model:负责数据存储 + +- View:负责页面展示 + +- View Model:负责业务逻辑处理(比如Ajax请求等),对数据进行加工后交给视图展示 + +## 关于框架 + +### 为什么要学习流行框架 + +**1、企业为了提高开发效率**:在企业中,时间就是效率,效率就是金钱;企业中,使用框架,能够提高开发的效率。 + +**提高开发效率的发展历程**: + +原生JS -> Jquery之类的类库 -> 前端模板引擎 -> Angular.js / Vue.js(能够帮助我们减少不必要的DOM操作;提高渲染效率;双向数据绑定的概念) + +2、在Vue中,一个核心的概念就是:数据驱动,避免手动操作DOM元素。这样的话,可以让前端程序员可以更多的时间去关注数据的业务逻辑,而不是关心 DOM 是如何渲染的了。 + +### 框架和库的区别 + +**框架**: + +框架是一套完整的解决方案。 + +对项目的**侵入性**较大,项目如果需要更换框架,则需要重新架构整个项目。但是优点也很明显:功能完善、提供了一整套的解决方案。 + +**库(插件)**: + +只是提供某一个小功能。 + +对项目的侵入性较小,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求。 + +举例: + +- 从Jquery 切换到 Zepto + +- 从 EJS 切换到 art-template + +## 前端的各种框架 + + +### Vue 和 React 的相同点 + +- 利用虚拟DOM实现快速渲染 + +- 轻量级 + +- 响应式组件 + +- 支持服务器端渲染 + +- 易于集成路由工具、打包工具以及状态管理工具 + +PS:Vue 在国内很受欢迎;React 在国内和国外都很受欢迎,适合做大型网站。 + +### 什么是虚拟 DOM + +传统的web开发,是利用 jQuery操作DOM,这是非常耗资源的。 + +我们可以在 JS 的内存里构建类似于DOM的对象,去拼装数据,拼装完整后,把数据整体解析,一次性插入到html里去。这就形成了虚拟 DOM。 + +Vue1.0没有虚拟DOM,Vue2.0改成了基于虚拟DOM。 + +### 前端框架回顾 + +![](http://img.smyhvae.com/20180302_1645.png) + +![](http://img.smyhvae.com/20180302_1651.png) + +![](http://img.smyhvae.com/20180302_1652.png) + +Vue框架中,没有控制器。 + +## Vue 框架 + +### 发展历史 + +- 2013年底作为尤雨溪个人实验项目开始开发 + +- 2014年2月公开发布。 + +- 2014年11月发布0.11版本 + +- 2016年10月发布2.0版本。 + +### 相关网址 + +- [中文官网](https://cn.vuejs.org/) + +- [vuejs官方论坛](https://forum.vuejs.org/) + +- GitHub地址: + + +- Vue1.0 在线文档: + +- Vue2.x 在线文档: + +- Vue1下载地址: + +- Vue2下载地址: + +![](http://img.smyhvae.com/20180302_1658.png) + +上方截图的时间:2018-03-02。 + +### 介绍 + + Vue 本身并不是一个框架,Vue结合周边生态构成一个灵活的、渐进式的框架。 + + Vue 以及大型 Vue 项目所需的周边技术,构成了生态。 + +渐进式框架图: + +![](http://img.smyhvae.com/20180302_1701.png) + +### Vue框架的特点 + +- 模板渲染:基于 html 的模板语法,学习成本低。 + +- 响应式的更新机制:数据改变之后,视图会自动刷新。【重要】 + +- 渐进式框架 + +- 组件化/模块化 + +- 轻量:开启 gzip压缩后,可以达到 20kb 大小。(React 达到 35kb,AngularJS 达到60kb)。 + +## Vue 的环境搭建 + +> 我们首先要安装好 NVM、Node.js环境,然后再来做下面的操作。 + +### 常见的插件 + +- Webpack:代码模块化构建打包工具。 + +- Gulp:基于流的自动化构建工具。 + +- Babel:使用最新的 规范来编写 js。 + +- Vue:构建数据驱动的Web界面的渐进式框架 + +- Express:基于 Node.js 平台,快速、开放、极简的 Web 开发框架。 + +以上这些包,都可以通过 NPM 这个包管理工具来安装。 + +### 引用 Vue.js 文件 + +1、**方式一**:(CDN的方式进行引用) + +```html + + + + + Title + + + + + + + +``` + +2、方式二:(下载 vue.js 文件) + +去网站 下载 vue.js 文件,直接放到工程文件里,然后引用。 + +3、方式三:(NPM的方式安装vue) + +```bash +# 最新稳定版 +$ npm install vue +``` + +如果网络不稳定,可以采用下面的方式安装: + +``` +$ cnpm i vue --save +``` + +然后在代码中通过下面这种方式进行引用: + +```javascript + import Vue from 'vue' +``` + +## 利用 vue-cli 新建一个空的项目 + +Vue 提供一个官方命令行工具,可用于快速搭建大型单页应用。该工具为现代化的前端开发工作流提供了开箱即用的构建配置。只需几分钟即可创建并启动一个带热重载、保存时静态检查以及可用于生产环境的构建配置的项目。 + +### 官方代码参考 + +``` + npm install -g @vue/cli + + vue create my-app + + cd my-app + + npm run serve +``` + +我们根据上方的参考代码,来看看“利用 vue-cli 新建一个空的项目”的步骤。 + +### 安装 vue-cli(命令行工具) + +安装命令如下: + +```bash +# 全局安装 vue-cli +$ npm install -g @vue/cli +``` + +### 初始化一个 simple 项目 + +(1)首先执行: + +``` + vue create my-app +``` + +输入上方命令后,会弹出一个选项: + +![](http://img.smyhvae.com/20190624_163626.png) + +如果是初学者,直接选`default`就行。之后会自动生成一个空的初始化项目,包含了项目目录、以及项目依赖的脚本。 + +这个空项目的工程文件如下:(请务必仔细研究这个项目的写法和目录结构) + +- [2019-06-21-vue-my-app.zip](https://download.csdn.net/download/smyhvae/11256220) + +我们可以看到这个项目的结构: + +![](http://img.smyhvae.com/20190624_160726.png) + +- src:项目源码 + +- .babelrc:ES6编译插件的配置 + +- index.html:单页面的入口 + +上方截图中,`npm install `指的是下载各种依赖包,`npm run dev`指的是打开发包,`npm run build`指的是打生产包。 + +(2)本地运行项目: + +``` + cd my-app + + npm run serve +``` + +浏览器输入`http://localhost:8080/`,就可以让这个空的项目在本地跑起来: + +![](http://img.smyhvae.com/20190624_160229.png) + +备注:我们在 GitHub上下载的任何Vue有关的项目,第一步都是要首先执行 npm install,安装依赖的 mode_modules,然后再运行。我们发给同事的工程文件,建议不要包含 `node_modules`。 + +### 构建一个 非 simple 项目 + +构建一个空的项目,首先执行: + +``` +$ vue create vuedemo2 +``` + +![](http://img.smyhvae.com/20190624_163726.png) + +上图中,选择 `Manually select features`,然后根据提示依次输入: + +![](http://img.smyhvae.com/20190624_164305.png) + +- project name:**要求小写**。 + +- description:默认即可。 + +- vue-router:需要。 + +- ESlint:语法检查,初学者可以暂时不需要。 + +- 单元测试:暂时也不需要。 + +- e2e test:不需要。 + +选择 eslint 的配置: + +![](http://img.smyhvae.com/20190624_165001.png) + +然后让这个空的项目就可以在浏览器上跑起来。 + +## vue 项目结构分析 + +![](http://img.smyhvae.com/20180501_2100.png) + +- buid:打包配置的文件夹 + +- config:webpack对应的配置 + +- src:开发项目的源码 + - App.vue:入口组件。`.vue`文件都是组件。 + - main.js:项目入口文件。 + +- static:存放静态资源 + +- `.babelrc`:解析ES6的配置文件 + +- `.editorcofnig`:编辑器的配置 + +- `.postcssrc.js`:html添加前缀的配置 + +- `index.html`:单页面的入口。通过 webpack打包后,会把 src 源码进行编译,插入到这个 html 里面来。 + +- `package.json`:项目的基础配置,包含版本号、脚本命令、项目依赖库、开发依赖库、引擎等。 + +### 图片的base64编码 + +默认是10k以下,建议都通过 base64编码。在配置文件`webpack.base.conf.js`中进行修改: + +``` + { + test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, + loader: 'url-loader', + options: { + limit: 10000, + name: utils.assetsPath('img/[name].[hash:7].[ext]') + } +``` + + +## 我的公众号 + +想学习**更多技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 + +扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: + +![](http://img.smyhvae.com/20160401_01.jpg) + + diff --git "a/12-Vue\345\237\272\347\241\200/02-Vue\347\232\204\347\263\273\347\273\237\346\214\207\344\273\244.md" "b/12-Vue\345\237\272\347\241\200/02-Vue\347\232\204\347\263\273\347\273\237\346\214\207\344\273\244.md" new file mode 100644 index 00000000..c3e5c039 --- /dev/null +++ "b/12-Vue\345\237\272\347\241\200/02-Vue\347\232\204\347\263\273\347\273\237\346\214\207\344\273\244.md" @@ -0,0 +1,669 @@ +--- +title: 02-Vue的系统指令 +publish: true +--- + + + + + + + +> 本文最初发表于[博客园](),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 + +> 以下是正文。 + + +## 本文主要内容 + +- 插值表达式 {{}} + +- v-cloak + +- v-text + +- v-html + +- v-bind + +- v-on + +- 举例:文字滚动显示(跑马灯效果) + +- v-on的事件修饰符 + + + +## Vue初体验 + +新建一个空的项目,引入`vue.js`文件。写如下代码: + +```html + + + + + Title + + + + + +
+ {{name}} +
+ + + + +``` + + +显示效果: + +![](http://img.smyhvae.com/20180313_0955.png) + +如果我们在控制台输入`myVue.$data.name = 'haha'`,页面会**自动更新**name的值。意思是,当我们直接修改data数据,页面会自动更新,而不用去操作DOM。 + + +下面来讲一下Vue的各种系统指令。 + + +## 插值表达式 {{}} + +数据绑定最常见的形式就是使用 “Mustache” 语法(双大括号)的文本插值。例如: + +```html +Message: {{ msg }} +``` + +Mustache 标签将会被替代为对应数据对象上 msg 属性(msg定义在data对象中)的值。 +无论何时,绑定的数据对象上 msg 属性发生了改变,插值处的内容都会**自动更新**。 + +`{{}}`对JavaScript 表达式支持,例如: + +```javascript +{{ number + 1 }} + +{{ ok ? 'YES' : 'NO' }} + +{{ name == 'smyhvae' ? 'true' : 'false' }} + +{{ message.split('').reverse().join('') }} +``` + + +但是有个限制就是,每个绑定都**只能包含单个表达式**,如下表达式无效: + +```html + +{{ var a = 1 }} + + +{{ if (ok) { return message } }} +``` + + +代码举例: + +```html + + + + + + + + Document + + + +
+ content:{{name}} +
+ + + + + + +``` + +运行结果: + + +![](http://img.smyhvae.com/20180506_2240.png) + + +## v-cloak + +`v-cloak`:保持和元素实例的关联,直到结束编译后自动消失。 + +v-cloak指令和CSS 规则一起用的时候,能够**解决差值表达式闪烁的问题**(即:可以隐藏未编译的标签直到实例准备完毕)。 + +就拿上一段代码来举例,比如说,`{{name}}`这个内容,**在网速很慢的情况下,一开始会直接显示`{{name}}`这个内容**,等网络加载完成了,才会显示`smyhvae`。那这个**闪烁的问题**该怎么解决呢? + +解决办法是:通过`v-cloak`隐藏`{{name}}`这个内容,当加载完毕后,再显示出来。 + +```html + + + + + + Document + + + + +
+ + {{name}} + +
+ + + + + + + +``` + + +## v-text + +v-text可以将一个变量的值渲染到指定的元素中。例如: + +```html + + + + + + Title + + + + + +
+ +
+ + + + + +``` + +结果: + + +![](http://img.smyhvae.com/20180313_1645.png) + +### 差值表达式和 v-text 的区别 + +```html + + content:{{name}} + + + /span> +``` + +**区别1**: v-text 没有闪烁的问题,因为它是放在属性里的。 + +**区别2** :插值表达式只会替换自己的这个占位符,并不会把整个元素的内容清空。v-text 会**覆盖**元素中原本的内容。 + +为了解释区别2,我们来用代码举例: + +```html + +

content:++++++{{name}}------

+ + +

------++++++

+``` + +上方代码的演示结果: + +![](http://img.smyhvae.com/20180506_2320.png) + +其实,第二行代码中,只要浏览器中还没有解析到`v-text="name"`的时候,会显示`------++++++`;当解析到`v-text="name"`的时候,name的值会直接替换`------++++++`。 + + +## v-html + + +`v-text`是纯文本,而`v-html`会被解析成html元素。 + +注意:使用v-html渲染数据可能会非常危险,因为它很容易导致 XSS(跨站脚本) 攻击,使用的时候请谨慎,能够使用{{}}或者v-text实现的不要使用v-html。 + +代码举例: + +```html + + + + + + + + Document + + + +
+

{{msg}}

+

+

+ +
+ + + + + + +``` + +运行结果: + +![](http://img.smyhvae.com/20180506_2330.png) + + +## v-bind:属性绑定机制 + +`v-bind`:用于绑定**属性**。 + +比如说: + +```html + + +
+``` + + +上方代码中,给属性加了 v-bind 之后,属性值里的整体内容是**表达式**,属性值里的`imageSrc`和`size`是Vue实例里面的**变量**。 + +也就是说, v-bind的属性值里,可以写合法的 js 表达式。 + +上面两行代码也可以简写成: + +```html + + +
+``` + +**举例:** + +```html + + + + + + Title + + + + +
+ + + + + + 超链接 + +
+ + + + + + + +``` + +上面的代码中,我们给`value`这个属性绑定了值,此时这个值是一个变量。 + +效果: + +![](http://img.smyhvae.com/20180313_1745.png) + + + +## v-on:事件绑定机制 + +### `v-on:click`:点击事件 + +```html + + + + + + Title + + + + + + +
+ + {{name}} + +
+ + + + + + + +``` + + +上方代码中,我们给button按钮绑定了点击事件。注意,这个button标签要写在div区域里(否则点击事件不生效),因为下方的View module接管的是div区域。 + +### `v-on`的简写形式 + +例如: + +```html + +``` + +可以简写成: + +```html + +``` + + +### v-on的常用事件 + +v-on 提供了click 事件,也提供了一些其他的事件。 + + +- v-on:click + +- v-on:keydown + +- v-on:keyup + +- v-on:mousedown + +- v-on:mouseover + +- v-on:submit + +- .... + +## 举例:文字滚动显示(跑马灯效果) + +我们利用上面几段所学的内容,做个跑马灯的小例子。要实现的效果是:类似于LED屏幕上,滚动显示的文字。 + +**文字滚动显示的思路**: + +(1)每次点击按钮后,拿到 msg 字符串,然后调用字符串的`substring`来进行字符串的截取操作,把第一个字符截取出来,放到最后一个位置即可。这就实现了滚动的效果。 +(2)为了实现文字**自动连续滚动**的效果,需要把步骤(1)中点击按钮的操作,放到**定时器**中去。 + +我们先来看一下 点击事件里的代码改怎么写。 + +**步骤 1**:每次点击按钮,字符串就滚动一次。代码如下: + +```javascript + startMethod: function () { + // 获取 msg 的第一个字符 + var start = this.msg.substring(0, 1); + // 获取 后面的所有字符 + var end = this.msg.substring(1); + // 重新拼接得到新的字符串,并赋值给 this.msg + this.msg = end + start; + } +``` + +**步骤2**:给上面的操作添加定时器。代码如下: + +```javascript + startMethod: function () { + var _this = this; + //添加定时器:点击按钮后,让字符串连续滚动 + setInterval(function () { + // 获取 msg 的第一个字符 + var start = _this.msg.substring(0, 1); + // 获取 后面的所有字符 + var end = _this.msg.substring(1); + // 重新拼接得到新的字符串,并赋值给 this.msg + // 注意: VM实例,会监听自己身上 data 中所有数据的改变,只要数据一发生变化,就会自动把 最新的数据,从data 上同步到页面中去 + _this.msg = end + start; + console.log(_this.msg); + }, 400); + } +``` + +上面的代码中,我们发现,如果在定时器中直接使用this,这个this指向的是window。为了解决这个问题,我们是通过`_this`来解决了这个问题。 + +另外,我们还可以利用箭头函数来解决this指向的问题,因为箭头函数总的this指向,会继承外层函数的this指向。如下。 + +**步骤2的改进版**:用箭头函数来改进定时器,解决this指向的问题。代码如下: + +```javascript + startMethod: function () { + //添加定时器:点击按钮后,让字符串连续滚动 + setInterval(() => { + // 获取 msg 的第一个字符 + var start = this.msg.substring(0, 1); + // 获取 后面的所有字符 + var end = this.msg.substring(1); + // 重新拼接得到新的字符串,并赋值给 this.msg + // 注意: VM实例,会监听自己身上 data 中所有数据的改变,只要数据一发生变化,就会自动把 最新的数据,从data 上同步到页面中去 + this.msg = end + start; + console.log(_this.msg); + }, 400); + } +``` + + +**步骤3**:停止定时器。如下: + +我们还需要加一个按钮,点击按钮后,停止文字滚动。也就是停止定时器。 + +提示:我们最好把定时器的id放在全局的位置(放到data里),这样的话,开启定时器的方法和停止定时器的方法,都可以同时访问到这个定时器。 + +代码如下: + +```javascript + data: { + msg: '生命壹号,永不止步~~~', + intervalId: null + }, + methods: { + startMethod: function () { + //添加定时器:点击按钮后,让字符串连续滚动 + this.intervalId = setInterval(() => { //【注意】这个定时器的this,一定不要忘记了 + // 获取 msg 的第一个字符 + var start = this.msg.substring(0, 1); + // 获取 后面的所有字符 + var end = this.msg.substring(1); + // 重新拼接得到新的字符串,并赋值给 this.msg + // 注意: VM实例,会监听自己身上 data 中所有数据的改变,只要数据一发生变化,就会自动把 最新的数据,从data 上同步到页面中去 + this.msg = end + start; + console.log(_this.msg); + }, 400); + }, + + stopMethod: function () { + //停止定时器:点击按钮后,停止字符串的滚动 + clearInterval(this.intervalId); + } + } +``` + + +**【重要】步骤4**:一开始的时候,还需要判断是否已经存在定时器。如下: + +步骤3中的代码,虽然做了停止定时器的操作,但是有个问题:在连续多次点击“启动定时器”按钮的情况下,此时再点击“停止定时器”的按钮,是没有反应的。因此,我们需要改进的地方是: + +- **在开启定时器之前,先做一个判断**:如果定时器不为 null,就不继续往下执行了(即不再开启新的定时器),防止开启了多个定时器。 + +- **停止定时器的时候,虽然定时器停止了,但定时器并不为 null**。因此,最后我们还需要手动将定时器设置为null。这样,才能恢复到最初始的状态。 + +**完整版代码**: + +针对上面的四个步骤,为了实现这个案例,完整版代码如下: + +```html + + + + + + + + Document + + + +
+

{{msg}}

+ + + +
+ + + + + + +``` + + +**上方代码的总结**: + +- 在Vue的实例中,如果想要获取data里的属性、methods里面的方法,都要通过`this`来访问。这里的**this指向的是Vue的实例对象**。 + +- VM实例,会监听自己身上 data 中所有数据的改变,只要数据一发生变化,就会自动把最新的数据,从 data 上同步到页面中去。这样做 的好处是:**程序员只需要关心数据,不需要考虑如何重新渲染DOM页面;减少DOM操作**。 + +- 在调用定时器 id 的时候,代码是`this.intervalId`,这个`this`一定不要漏掉了。 + + +## 我的公众号 + +想学习**更多技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 + +扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: + +![](http://img.smyhvae.com/2016040102.jpg) + diff --git "a/12-Vue\345\237\272\347\241\200/03-v-on\347\232\204\344\272\213\344\273\266\344\277\256\351\245\260\347\254\246.md" "b/12-Vue\345\237\272\347\241\200/03-v-on\347\232\204\344\272\213\344\273\266\344\277\256\351\245\260\347\254\246.md" new file mode 100644 index 00000000..9dc65c32 --- /dev/null +++ "b/12-Vue\345\237\272\347\241\200/03-v-on\347\232\204\344\272\213\344\273\266\344\277\256\351\245\260\347\254\246.md" @@ -0,0 +1,273 @@ +--- +title: 03-v-on的事件修饰符 +publish: true +--- + + + + + + + +## v-on的事件修饰符 + +### v-on的常见事件修饰符 + +`v-on` 提供了很多事件修饰符来辅助实现一些功能。事件修饰符有如下: + +- `.stop` 阻止冒泡。本质是调用 event.stopPropagation()。 + +- `.prevent` 阻止默认事件(默认行为)。本质是调用 event.preventDefault()。 + +- `.capture` 添加事件监听器时,使用捕获的方式(也就是说,事件采用捕获的方式,而不是采用冒泡的方式)。 + +- `.self` 只有当事件在该元素本身(比如不是子元素)触发时,才会触发回调。 + +- `.once` 事件只触发一次。 + +- `.{keyCode | keyAlias}` 只当事件是从侦听器绑定的元素本身触发时,才触发回调。 + +- `.native` 监听组件根元素的原生事件。 + +PS:一个事件,允许同时使用多个事件修饰符。 + +写法示范: + +```html + + + + + + + + + + + + + + + + +
+ + + +``` + + +### `.stop`的举例 + +我们来看下面这个例子: + +```html + + + + + + + + Document + + + + + +
+
+
+
+
+
+ + + + + +``` + +上方代码中,存在冒泡的现象,父标签中包含了一个子标签。当点击子标签时,父标签也会被触发。打印顺序是: + +``` + child 被点击了 + father 被点击了 +``` + +那么问题来了,如果我不想让子标签的点击事件冒泡到父亲,该怎么做呢?办法是:给子标签加一个**事件修饰符**`.stop`,阻止冒泡。代码如下: + +```html +
+``` + +阻止冒泡后,当点击子标签时,打印结果是: + +``` + child 被点击了 +``` + +PS:我发现一个有意思的现象。上方的这行代码中,如果把`.stop`改为`:stop`,造成的现象是,父标签被触发了,而子标签没有被触发。 + +### `.capture`举例 + +`.capture`:触发事件时,采用捕获的形式,而不是冒泡的形式。 + +还是采用上面的例子:当按钮点击时,如果想要采取捕获的方式,而不是冒泡的方式,办法是:可以直接在父标签上加事件修饰符`.capture`。代码如下: + +```html +
+``` + +当点击子标签时,打印结果是: + +``` + father 被点击了 + child 被点击了 +``` + + +### `.prevent`的举例1 + +比如说,超链接``默认有跳转行为,那我可以通过事件修饰符`.prevent`阻止这种跳转行为。 + + +```html + + + + + + + + Document + + + + + + + + + +``` + +上方代码中: + +- 如果去掉`.prevent`,点击按钮后,既会打印log,又会跳转到百度页面。 + +- 现在加上了`.prevent`,就只会打印loeg,不会跳转到百度页面。 + + + +### `.prevent`的举例2 + +现在有一个form表单: + +```html +
+ +
+``` + + +我们知道,上面这个表单因为`type="submit"`,因此它是一个提交按钮,点击按钮后,这个表单就会被提交到form标签的action属性中指定的那个页面中去。这是表单的默认行为。 + +现在,我们可以用`.prevent`来阻止这种默认行为。修改为:点击按钮后,不提交到服务器,而是执行我们自己想要的事件(在submit方法中另行定义)。如下: + +```html + + + + + + Document + + + + +
+ +
+ + +
+ +
+ + + + + +``` + +上方代码中,我们通过`.prevent`阻止了提交按钮的默认事件,点击按钮后,执行的是`mySubmit()`方法里的内容。这个方法名是可以随便起的,我们甚至可以起名为`submit`,反正默认的submit已经失效了。 + + + +### `.self`举例 + +- `.self` 只有当事件在该元素本身(比如不是子元素)触发时,才会触发回调。 + +我们知道,在事件触发机制中,当点击子标签时,父标签会通过冒泡的形式被触发(父标签本身并没有被点击)。可如果我给父标签的点击事件设置`.self`修饰符,达到的效果是:子标签的点击事件不会再冒泡到父标签了,只有点击符标签本身,父标签的事件才会被触发。代码如下: + +```html +
+``` + + +**疑问**:既然`.stop`和`.self`都可以阻止冒泡,那二者有什么区别呢?区别在于:前者能够阻止整个冒泡行为,而后者只能阻止自己身上的冒泡行为。 + + diff --git "a/12-Vue\345\237\272\347\241\200/04-Vue\347\232\204\347\263\273\347\273\237\346\214\207\344\273\244(\344\272\214).md" "b/12-Vue\345\237\272\347\241\200/04-Vue\347\232\204\347\263\273\347\273\237\346\214\207\344\273\244(\344\272\214).md" new file mode 100644 index 00000000..e32846d8 --- /dev/null +++ "b/12-Vue\345\237\272\347\241\200/04-Vue\347\232\204\347\263\273\347\273\237\346\214\207\344\273\244(\344\272\214).md" @@ -0,0 +1,840 @@ +--- +title: 03-v-on的事件修饰符 +publish: true +--- + + + + + + + +## 前言 + +本文主要内容: + +- v-model + +- v-for + +- v-if + +- v-show + +## v-model:双向数据绑定 + + +> 重点:**双向数据绑定,只能用于表单元素,或者用于自定义组件**。 + +之前的文章里,我们通过v-bind,给``标签绑定了`data`对象里的`name`属性。当`data`里的`name`的值发生改变时,``标签里的内容会自动更新。 + +可我现在要做的是:我在``标签里修改内容,要求`data`里的`name`的值自动更新。从而实现双向数据绑定。该怎么做呢?这就可以利用`v-model`这个属性。 + +**区别**: + +- v-bind:只能实现数据的**单向**绑定,从 M 自动绑定到 V。 + +- v-model:只有`v-model`才能实现**双向**数据绑定。注意,v-model 后面不需要跟冒号, + +**注意**:v-model 只能运用在**表单元素**中,或者用于自定义组件。常见的表单元素包括:input(radio, text, address, email....) 、select、checkbox 、textarea。 + +代码举例如下: + +```html + + + + + Document + + + +
+ +
+ + + + + + +
+
+ + + + + +``` + +此时,便可实现我们刚刚要求的双向数据绑定的效果。 + +## v-model举例:实现简易计算器 + +题目:现在两个输入框,用来做加减乘除,将运算的结果放在第三个输入框。 + +实现代码如下: + +```html + + + + + + + + Document + + + + +
+ + + + + + + + + +
+ + + + + +``` + +注意上方代码中的注释,可以了解下`eval()`的用法。 + +## Vue中通过属性绑定为元素设置class 类样式 + +注意,是**类样式**。 + +### 引入 + +我们先来看下面这段代码: + +```html + + + + + + + + Document + + + + +

我是生命壹号,smyhvae

+ + + +``` + +上面的代码中,我们直接通过正常的方式,给`

`标签设置了两个 class 类的样式。代码抽取如下: + +```html +

我是生命壹号,smyhvae

+``` + +上面的效果,我们还可以用Vue来写。这就引入了本段要讲的方式。 + +### 方式一:数组 + +**方式一**:直接传递一个数组。注意:这里的 class 需要使用 v-bind 做数据绑定。 + +代码如下: + +```html + + + + + + + + Document + + + + + +
+ + +

我是生命壹号,smyhvae

+ + +

我是smyhvae,生命壹号

+ +
+ + + + + +``` + +代码抽取如下: + +```html + +

我是smyhvae,生命壹号

+``` + +上方代码中,注意,数组里写的是字符串;如果不加单引号,就不是字符串了,而是变量。 + +演示效果如下: + +![](http://img.smyhvae.com/20180509_1058.png) + +### 写法二:在数组中使用三元表达式 + +```html + +
+ + +

我是smyhvae,生命壹号

+
+ + + +``` + +上方代码的意思是,通过data中布尔值 flag 来判断:如果 flag 为 true,就给 h1 标签添加`my-active`样式;否则,就不设置样式。 + +注意,三元表达式的格式不要写错了。 + + +### 写法三:在数组中使用 对象 来代替 三元表达式(提高代码的可读性) + +上面的写法二,可读性较差。于是有了写法三。 + +**写法三**:在数组中使用**对象**来代替**三元表达式**。 + +代码如下: + +```html + +
+ +

我是smyhvae,生命壹号

+
+ + + +``` + +### 写法四:直接使用对象 + +写法四:直接使用对象。代码如下: + +```html + + +

我是smyhvae,生命壹号

+``` + +上方代码的意思是,给`

`标签使用样式`style1`,不使用样式`style2`。注意: + +1、既然class样式名是放在对象中的,这个样式名不能有中划线,比如说,写成`:class="{my-red:true, my-active:false}`,是会报错的。 + +2、我们也可以对象通过存放在 data 的变量中。也就是说,上方代码可以写成: + +```html + +
+ + +

我是smyhvae,生命壹号

+
+ + + +``` + +## Vue中通过属性绑定为元素设置 style 行内样式 + +注意,是行内样式(即内联样式)。 + +### 写法一 + +**写法一**:直接在元素上通过 `:style` 的形式,书写样式对象。 + +例如: + +```html +

我是生命壹号,smyhvae

+``` + +### 写法二 + +**写法二**:将样式对象,定义到 `data` 中,并直接引用到 `:style` 中。 + +也就是说,把写法一的代码改进一下。代码如下: + +```html + +
+

我是生命壹号,smyhvae

+
+ + + +``` + +### 写法三 + +写法二只用到了一组样式。如果想定义**多组**样式,可以用写法三。 + +**写法三**:在 `:style` 中通过数组,引用多个 `data` 上的样式对象。 + +代码如下: + +```html + +
+

我是生命壹号,smyhvae

+
+ + + +``` + + +## v-for:for循环的四种使用方式 + +**作用**:根据数组中的元素遍历指定模板内容生成内容。 + +### 引入 + +比如说,如果我想给一个`ul`中的多个`li`分别赋值1、2、3...。如果不用循环,就要挨个赋值: + +```html + +
+
    +
  • {{list[0]}}
  • +
  • {{list[1]}}
  • +
  • {{list[2]}}
  • +
+
+ + + +``` + +效果: + +![](http://img.smyhvae.com/20180329_1713.png) + +为了实现上面的效果,如果我用`v-for`进行赋值,代码就简洁很多了: + +```html + +
+
    + +
  • {{item}}
  • +
+
+ + + +``` + +接下来,我们详细讲一下`v-for`的用法。需要声明的是,Vue 1.0的写法和Vue 2.0的写法是不一样的。本文全部采用Vue 2.0的写法。 + +### 方式一:普通数组的遍历 + +针对下面这样的数组: + +```html + +``` + +将数组中的**值**赋给li: + +```html +
  • {{item}}
  • +``` + +将数组中的**值和index**赋给li: + + +```html + +
  • 值:{{item}} --- 索引:{{index}}
  • +``` + +效果如下: + +![](http://img.smyhvae.com/20180329_1856.png) + +### 方式二:对象数组的遍历 + +```html + + + + + + + + Document + + + + + +
    +
      + +
    • 姓名:{{item.name}} --- 年龄:{{item.age}} --- 索引:{{index}}
    • + +
    +
    + + + + + + +``` + +效果如下: + +![](http://img.smyhvae.com/20180509_1500.png) + +### 方式三:对象的遍历 + +针对下面这样的对象: + +```html + +``` + +将上面的`obj1`对象的数据赋值给li,写法如下: + +```html + +
    +
      + +
    • 值:{{value}} --- 键:{{key}}
    • + +

      ---分隔线---

      + + +
    • 值:{{value}} --- 键:{{key}} --- index:{{index}}
    • +
    +
    + + +``` + +效果如下: + +![](http://img.smyhvae.com/20180329_1850.png) + +### 方式四:遍历数字 + +`in`后面还可以直接放数字。举例如下: + +```html +
      + + +
    • 这是第 {{myCount}}次循环
    • +
    +``` + +效果如下: + +![](http://img.smyhvae.com/20180509_1505.png) + +### v-for中key的使用注意事项 + +**注意**:在 Vue 2.2.0+ 版本里,当在**组件中**使用 v-for 时,key 属性是必须要加上的。 + +这样做是因为:每次 for 循环的时候,通过指定 key 来标示当前循环这一项的**唯一身份**。 + +> 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “**就地复用**” 策略。如果数据项的顺序被改变,Vue将**不是移动 DOM 元素来匹配数据项的顺序**, 而是**简单复用此处每个元素**,并且确保它在特定索引下显示已被渲染过的每个元素。 + +> 为了给 Vue 一个提示,**以便它能跟踪每个节点的身份,从而重用和重新排序现有元素**,你需要为每项提供一个唯一 key 属性。 + +key的类型只能是:string/number,而且要通过 v-bind 来指定。 + +代码举例: + +```html + + + + + + + + Document + + + + +
    + +
    + + + + + +
    + + + + +

    + {{item.id}} --- {{item.name}} +

    +
    + + + + + +``` + +## v-if:设置元素的显示和隐藏(添加/删除DOM元素) + +**作用**:根据表达式的值的真假条件,来决定是否渲染元素,如果为false则不渲染(达到隐藏元素的目的),如果为true则渲染。 + +在切换时,元素和它的数据绑定会被销毁并重建。 + +举例如下:(点击按钮时,切换和隐藏盒子) + +```html + + + + + + Document + + + + +
    + +
    我是盒子
    +
    + + + + + +``` + +效果如下: + +![](http://img.smyhvae.com/20180329_1920.gif) + +## v-show:设置元素的显示和隐藏(在元素上添加/移除`style="display:none"`属性) + +**作用**:根据表达式的真假条件,来切换元素的 display 属性。如果为false,则在元素上添加 `display:none`属性;否则移除`display:none`属性。 + +举例如下:(点击按钮时,切换和隐藏盒子) + +我们直接把上一段代码中的`v-if`改成`v-show`就可以了: + +```html + + + + + + Document + + + + +
    + +
    我是盒子
    +
    + + + + + + +``` + +效果如下: + +![](http://img.smyhvae.com/20180329_2040.gif) + +### v-if和v-show的区别 + +`v-if`和`v-show`都能够实现对一个元素的隐藏和显示操作。 + +区别: + +- v-if:每次都会重新添加/删除DOM元素 + +- v-show:每次不会重新进行DOM的添加/删除操作,只是在这个元素上添加/移除`style="display:none"`属性,表示节点的显示和隐藏。 + +优缺点: + +- v-if:有较高的切换性能消耗。这个很好理解,毕竟每次都要进行dom的添加/删除操作。 + +- v-show:**有较高的初始渲染消耗**。也就是说,即使一开始`v-show="false"`,该节点也会被创建,只是隐藏起来了。而`v-if="false"`的节点,根本就不会被创建。 + +**总结**: + +- 如果元素涉及到频繁的切换,最好不要使用 v-if, 而是推荐使用 v-show + +- 如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if + + + + + + + + + + diff --git "a/12-Vue\345\237\272\347\241\200/05-Vue\347\232\204\344\270\276\344\276\213\357\274\232\345\210\227\350\241\250\345\212\237\350\203\275.md" "b/12-Vue\345\237\272\347\241\200/05-Vue\347\232\204\344\270\276\344\276\213\357\274\232\345\210\227\350\241\250\345\212\237\350\203\275.md" new file mode 100644 index 00000000..88b721e5 --- /dev/null +++ "b/12-Vue\345\237\272\347\241\200/05-Vue\347\232\204\344\270\276\344\276\213\357\274\232\345\210\227\350\241\250\345\212\237\350\203\275.md" @@ -0,0 +1,617 @@ +--- +title: 05-Vue的举例:列表功能 +publish: true +--- + + + + + + + +## 列表功能举例 + +### 步骤 1:列表功能 + +完整的代码如下: + +```html + + + + + + + + Document + + + + + + + +
    + + + + + + + + + + + + +
    编号名称创建时间操作
    {{item.id}}{{item.name}}{{item.ctime}}删除
    +
    + + + + + + +``` + +**代码分析**:数据是存放在data的list中的,将data中的数据通过`v-for`遍历给表格。 + + +上方代码运行的效果: + +![](http://img.smyhvae.com/20180401_1517.png) + +### 步骤 2:无数据时,增加提示 + +如果list中没有数据,那么表格中就会只显示表头``,这样显然不太好看。 + +为此,我们需要增加一个`v-if`判断:当数据为空时,显示提示。如下: + +```html + + 列表无数据 + +``` + +代码解释:`colspan="4"`指的是让当前这个``横跨4个单元格的位置。如下: + +![](http://img.smyhvae.com/20180401_1535.png) + +### 步骤 3:item的添加 + +具体实现步骤如下: + +(1)用户填写的数据单独存放在data属性里,并采用`v-model`进行双向绑定。 + +(2)用户把数据填好后,点击add按钮。此时需要增加一个点击事件的方法,将data中的数据放到list中(同时,清空文本框中的内容)。 + +(3)将数据展示出来。`v-for`有个特点:当list数组发生改变后,vue.js就会自动调用`v-for`重新将数据生成,这样的话,就实现了数据的自动刷新。 + +完整的代码如下: + +```html + + + + + + + + Document + + + + + + + +
    + +
    + + 编号: + 名称: + + +
    + + + + + + + + + + + + + + + +
    编号名称创建时间操作
    列表无数据
    {{item.id}}{{item.name}}{{item.ctime}}删除
    +
    + + + + + + + +``` + +### 步骤 4:item的删除 + +html部分: + +```html + + 删除 +``` + +js部分: + +```javascript + delData: function (id) { + // 0 提醒用户是否要删除数据 + if (!confirm('是否要删除数据?')) { + //当用户点击的取消按钮的时候,应该阻断这个方法中的后面代码的继续执行 + return; + } + + // 1 调用list.findIndex()方法根据传入的id获取到这个要删除数据的索引值(在数组中的索引值) + var index = this.list.findIndex(function (item) { + return item.id == id + }); + + // 2.0 调用方法:list.splice(待删除的索引, 删除的元素个数) + this.list.splice(index, 1); + } +``` + + +代码解释:`find()`和`findIndex()`是ES6中为数组新增的函数。详细解释如下: + +```javascript + // 根据id得到下标 + + // 默认去遍历list集合,将集合中的每个元素传入到function的item里, + var index = this.list.findIndex(function(item){ + //根据item中的id属性去匹配传进来的id + //如果是则返回true ;否返回false,继续下面的一条数据的遍历,以此类推 + return item.id ==id; //如果返回true,那么findIndex方法会将这个item对应的index + }); +``` + +也就是说,我们是根据 item.id 找到这个 item 是属于list 数组中的哪个index索引。找到了index,就可以根据index来删除数组中的那个元素了。 + +当item被删除后,v-for会被自动调用,进而自动更新view。 + +完整版代码: + +```html + + + + + + + + Document + + + + + + + +
    + +
    + + 编号: + 名称: + + + +
    + + + + + + + + + + + + + + + + +
    编号名称创建时间操作
    列表无数据
    {{item.id}}{{item.name}}{{item.ctime}} + 删除 +
    +
    + + + + + + +``` + +### 步骤 5:按条件筛选item + +现在要求实现的效果是,在搜索框输入关键字 keywords,列表中仅显示匹配出来的内容。也就是说: + +- 之前, v-for 中的数据,都是直接从 data 上的list中直接渲染过来的。 + +- 现在, 我们在使用`v-for`进行遍历显示的时候,不能再遍历全部的 list 了;我们要自定义一个 search 方法,同时,把keywords作为参数,传递给 search 方法。即`v-for="item in search(keywords)"`。 + +在 search(keywords) 方法中,为了获取 list 数组中匹配的item,我们可以有两种方式实现。如下。 + +**方式一**:采用`forEach + indexOf()` + +```javascript + search(keywords) { // 根据关键字,进行数据的搜索,返回匹配的item + + //实现方式一:通过 indexOf() 进行匹配。 + var newList = []; + this.list.forEach(item => { + if (item.name.indexOf(keywords) != -1) { //只要不等于 -1,就代表匹配到了 + newList.push(item) + } + }) + return newList + } +``` + +上方代码中, 我们要注意 indexOf(str) 的用法。举例如下: + +```javascript + var str = 'smyhvae'; + + console.log(str.indexOf('s')); //打印结果:0 + + console.log(str.indexOf('')); //打印结果:0。(说明,即使去匹配空字符串,也是返回0) + + console.log(str.indexOf('h')); //打印结果:3 + + console.log(str.indexOf('x')); //打印结果:-1 (说明,匹配不到任何字符串) +``` + +上方代码中,也就是说,如果参数为空字符串,那么,每个item都能匹配到。 + +**方式二**: filter + includes()方法 + +```javascript + search(keywords) { // 根据关键字,进行数据的搜索,返回匹配的item + + var newList = this.list.filter(item => { + // 注意 : ES6中,为字符串提供了一个新方法,叫做 String.prototype.includes('要包含的字符串') + // 如果包含,则返回 true ,否则返回 false + if (item.name.includes(keywords)) { + return item + } + }) + + return newList + } +``` + +注意:forEach some filter findIndex,这些都属于数组的新方法,都会对数组中的每一项,进行遍历,执行相关的操作。这里我们采用数组中的 filter 方法, + +总的来说,方式二的写法更优雅,因为字符串的 includes()方法确实很实用。 + +完整版代码如下: + +```html + + + + + + + + Document + + + + + + + +
    + +
    + + 编号: + 名称: + + + + 搜索: + + +
    + + + + + + + + + + + + + + + + +
    编号名称创建时间操作
    列表无数据
    {{item.id}}{{item.name}}{{item.ctime}} + 删除 +
    +
    + + + + + + + +``` + +备注:在1.x 版本中可以通过filterBy指令来实现过滤,但是在2.x中已经被废弃了。 + + + + + diff --git "a/12-Vue\345\237\272\347\241\200/06-\350\207\252\345\256\232\344\271\211\350\277\207\346\273\244\345\231\250\357\274\232\346\227\266\351\227\264\346\240\274\345\274\217\345\214\226\344\270\276\344\276\213.md" "b/12-Vue\345\237\272\347\241\200/06-\350\207\252\345\256\232\344\271\211\350\277\207\346\273\244\345\231\250\357\274\232\346\227\266\351\227\264\346\240\274\345\274\217\345\214\226\344\270\276\344\276\213.md" new file mode 100644 index 00000000..96c3d505 --- /dev/null +++ "b/12-Vue\345\237\272\347\241\200/06-\350\207\252\345\256\232\344\271\211\350\277\207\346\273\244\345\231\250\357\274\232\346\227\266\351\227\264\346\240\274\345\274\217\345\214\226\344\270\276\344\276\213.md" @@ -0,0 +1,638 @@ +--- +title: 06-自定义过滤器:时间格式化举例 +publish: true +--- + + + + + + + + + +## 前言 + + +> 我们接着上一篇文章01-04来讲。 + +### 过滤器的概念 + +**概念**:Vue.js 允许我们自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两个地方:mustache **插值表达式**、 **v-bind表达式**。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示。 + + +### Vue1.X中的系统过滤器 + +Vue提供了一系列的固定逻辑来使程序员更加容易的实现这些功能,这些过滤器称之为系统过滤器。 + +系统过滤器是Vue1.0中存在的,在Vue2.0中已经删除了。 + +系统过滤器的使用,可以参考参考文档: + + +Vue也提供了一个接口用来供程序员定义属于自己的特殊逻辑,Vue称之为自定义过滤器。我们接下来讲一讲。 + + +## 自定义全局过滤器 + +文档地址: + + +### 全局过滤器的基本使用 + + +我们可以用全局方法`Vue.filter()`自定义一个全局过滤器。这样的话,每一个Vue的对象实例(每一个VM实例)都可以拿到这个过滤器。它接收两个参数:过滤器的名称 、过滤器函数。 + +比如说,我要将`曾经,我也是一个单纯的少年,单纯的我,傻傻的问,谁是世界上最单纯的男人`这句 msg 中的“单纯”改为“邪恶”。可以这样做: + +(1)在差值表达式中这样调用: + +```html +

    {{ msg | msgFormat }

    +``` + + +上方代码的意思是说: + +- **管道符前面**的`msg`:要把 `msg` 这段文本进行过滤, + +- **管道符后面**的`msgFormat`:是通过`msgFormat`这个过滤器进行来操作。 + +(2)定义过滤器`msgFormat`: + +```javascript + // Vue.filter 中的第一个参数是过滤器的名称,第二个参数是具体的过滤器函数 + // 定义一个 Vue 全局的过滤器,名字叫做 msgFormat + Vue.filter('msgFormat', function (myMsg) { // function 的第一个参数指的是管道符前面的 msg + // 字符串的 replace 方法,第一个参数,除了可写一个 字符串之外,还可以定义一个正则 + return myMsg.replace(/单纯/g, '邪恶') + }) +``` + +上方代码解释: + +- `Vue.filter(‘过滤器的名称’, 具体的过滤器函数)`中的第一个参数指的就是过滤器的名称(必须和**管道符后面**的名称**完全一致**),第二个参数是具体的过滤器函数 + +- 过滤器函数function中,第一个参数指的**管道符前面的**msg。 + +- `replace()`方法是用来做字符串的替换的。第一个参数如果只写成`单纯`,那么就会只修改 msg 中的第一个`单纯`字样。所以这里就用正则去匹配msg 中所有的`单纯`字样。 + +最终,完整版代码如下: + +```html + + + + + + + + Document + + + + +
    + +

    {{ msg | msgFormat }}

    +
    + + + + + +``` + + +网页显示效果如下: + +![](http://img.smyhvae.com/20180522_1240.png) + +### 给过滤器添加多个参数 + +上面的举例代码中,`{{ msg | msgFormat }}`中,**过滤器的调用并没有加参数**,其实它还可以添加多个参数。 + +接下来,我们在上面的举例代码中进行改进。 + + +**改进一**:过滤器加一个参数。如下: + + +将 msg 这个字符串中的“单纯”改为 xxx 变量。代码如下: + +```html + + + + + + + + Document + + + + +
    + +

    {{ msg | msgFormat('xxx') }}

    + +
    + + + + + + +``` + + +![](http://img.smyhvae.com/20180525_2135.png) + +注意代码中那行重要的注释:括号里的参数代表 function中的 arg2。 + +**改进二**:过滤器加两个参数。如下: + +```html + + + + + + + + Document + + + + +
    + + +

    {{ msg | msgFormat('【牛x】', '【参数arg3】') }}

    + +
    + + + + + +``` + + +效果如下: + +![](http://img.smyhvae.com/20180525_2150.png) + + +**改进3:同时使用多个过滤器** + +对 msg 同时使用多个过滤器。例如: + +```html + + + + + + + + Document + + + + +
    + + +

    {{ msg | msgFormat('【牛x】', '【参数arg3】') | myFilter2}}

    + +
    + + + + + +``` + +效果如下: + +![](http://img.smyhvae.com/20180525_2200.png) + +上方代码中,添加了多个过滤器,实现的思路是:**将 msg 交给第一个过滤器来处理,然后将处理的结果交给第二个过滤器来处理** 。 + + + + +### 举例1:时间格式化 + +```html + + + + + + Document + + + + +
    + {{ time }} +
    {{ time | datefmt }} +
    + +
    + {{ time | datefmt }} +
    + + + + +``` + +运行效果: + +![](http://img.smyhvae.com/20180525_2230.png) + +### 举例2:时间格式化 + +上面的举例1,时间格式化的过滤器,我们还有个更高端的写法:(字符串模板) + +```html + + + + + + Document + + + + +
    + 2018-05-25T14:06:51.618Z +
    {{ '2018-05-25T14:06:51.618Z' | dateFormat }} +
    + + + + + +``` + +运行结果: + +![](http://img.smyhvae.com/20180526_2319.png) + +【荐】**举例2的改进**:(字符串的padStart方法使用) + +上图中,我们可以看到,箭头处的时间有些问题,比如说,`6`要写成`06`更合适。为了实现这个功能,我们可以这样做: + +使用ES6中的字符串新方法 `String.prototype.padStart(maxLength, fillString='')` 或 `String.prototype.padEnd(maxLength, fillString='')`来填充字符串。 `pad`在英文中指的是`补充`。 + +实现举例如下: + + +```html + + + + + + Document + + + + +
    + 2018-05-25T14:06:51.618Z +
    {{ '2018-05-25T14:06:51.618Z' | dateFormat }} +
    + + + + + +``` + + +运行效果如下: + +![](http://img.smyhvae.com/20180526_2323.png) + +`pattern`参数的解释: + +在做`if (pattern && pattern.toLowerCase() === 'yyyy-mm-dd')`这个判断时,逻辑是:**先保证pattern参数传进来了,然后继续后面的判断**。 + +我们不能写成:`if (pattern.toLowerCase() === 'yyyy-mm-dd')`。因为,万一在调用的时候,不传递参数pattern,那么 if语句就相当于`if (undefined.toLowerCase() === 'yyyy-mm-dd')`,就会报错。 + +当然,ES6中有个新特性叫“默认参数”,我们就可以这样写: + +```html + + + + + + Document + + + + +
    + 2018-05-25T14:06:51.618Z +
    {{ '2018-05-25T14:06:51.618Z' | dateFormat }} +
    + + + + + + +``` + + +## 自定义私有过滤器 + +**私有过滤器**:在某一个 vue 对象内部定义的过滤器称之为私有过滤器。这种过滤器只有在当前vue对象的el指定的监管区域有用。 + + +**举例**:日期格式化 + +```html + + + + + + Document + + + + +
    + {{ time }} +
    + {{ time | datefmt }} +
    + + + + + +``` + +上面的代码中,我们在vue实例中,通过`filters`关键字,在里面定义了一个局部过滤器`datefmt`。 + + +运行结果: + +![](http://img.smyhvae.com/20180405_2038.png) + +第一行代码显示的是默认的date。第二行代码显示的是格式化之后的date,说明过滤器是起到了作用的。 + +### 总结 + +过滤器调用的时候,采用的是**就近原则**,如果私有过滤器和全局过滤器名称一致了,这时候 优先调用私有过滤器。 + + + + + + + + + + + + + + + + + + + + + + + + + +## axios + +axios是在Vue中专门用来发送ajax请求的。 + +但是,axios并不依赖于Vue.js库,而是基于promise的。 \ No newline at end of file diff --git "a/12-Vue\345\237\272\347\241\200/07-\350\207\252\345\256\232\344\271\211\346\214\211\351\224\256\344\277\256\351\245\260\347\254\246&\350\207\252\345\256\232\344\271\211\346\214\207\344\273\244.md" "b/12-Vue\345\237\272\347\241\200/07-\350\207\252\345\256\232\344\271\211\346\214\211\351\224\256\344\277\256\351\245\260\347\254\246&\350\207\252\345\256\232\344\271\211\346\214\207\344\273\244.md" new file mode 100644 index 00000000..db13d20a --- /dev/null +++ "b/12-Vue\345\237\272\347\241\200/07-\350\207\252\345\256\232\344\271\211\346\214\211\351\224\256\344\277\256\351\245\260\347\254\246&\350\207\252\345\256\232\344\271\211\346\214\207\344\273\244.md" @@ -0,0 +1,385 @@ +--- +title: 07-自定义按键修饰符&自定义指令 +publish: true +--- + + + + + + + + +## v-on的按键修饰符 + +### Vue 内置的按键修饰符 + +通俗一点讲,指的是:监听键盘输入的事件。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符。如下: + +Vue内置的按键修饰符: + +``` + .enter + .tab + .delete (捕获 “删除” 和 “退格” 键) + .esc + .space + .up + .down + .left + .right + 1.0.8+版本:支持单字母的按键别名。 +``` + + +比如说,`keyup`指的是:键盘(任何键位)抬起时的监听事件。`.enter`指的是:按enter键的按键修饰符。我们把这两个结合起来看看。 + +**`@keyup.enter`举例**:按enter键后的监听事件 + +`@keyup.enter="addData"`表示:按住enter键后,执行addData()方法。**全称**是`v-on:key.enter="addData"`。 + +我们还是拿`01-04`这篇文章中的列表功能来举例。之前是点击“添加”按钮后,列表中会添加一个item。现在要求:在**输入框**中按enter键后,也能添加一个item。 + +核心代码如下: + +```html + +``` + +注意,如果写成`@keyup="addData"`,效果却是:只要键盘的任何键位打了字(还没来得及按enter键),就会执行addData()方法,这种效果显然不是我们想要的。所以要加上修饰符`.enter`,表示只针对enter键。 + +### 自定义的按键修饰符 + +如果我们直接在代码的``标签里写`@keyup.f2="addData"`,那么,按住「F2键」后,是没有效果的,因为「F2键」不是内置的按键修饰符(如果F2不能验证,你可以试一下F7)。 + +我们知道,每个按键都有一个键盘码。参考链接: + +- [js 里面的键盘事件对应的键码](http://www.cnblogs.com/wuhua1/p/6686237.html) + +通过查阅,我们知道了「F2键」的键盘码为`113`,那代码可以这样写:(按住F2键后,执行 addData 方法) + +```html + +``` + +虽然键盘码很全,但是不好记呀。于是,接下来,我们给键盘码定义别名。 + +**自定义全局按键修饰符**: + +``` + //自定义全局按键修饰符 + Vue.config.keyCodes.f2 = 113; +``` + +上方代码的书写位置,与自定义全局过滤器的位置,是并列的。 + +然后,我们就可以使用键盘码的别名了。 + +## 自定义全局指令 + +### 自定义全局指令的举例1 + +**举例1**:让指定文本框自动获取焦点 + +如果我们想实现这个例子,原生js的写法是: + +```javascript + //原生js写法:网页一打开,就让指定的输入框自动获取焦点 + document.getElementById('search').focus() +``` + +代码的位置: + +![](http://img.smyhvae.com/20180527_2340.png) + +但我们不建议这样做。我们可以通过Vue中的自定义指令来实现这个例子。步骤如下。 + +(1)使用`Vue.directive()`自定义全局指令: + +```javascript + + //自定义全局指令 v-focus:让文本框自动获取焦点 + //参数1:指令的名称。注意,在定义的时候,指令的名称前面,不需要加 v- 前缀;但是:在`调用`的时候,必须在指令名称前 加上 v- 前缀 + //参数2:是一个对象,这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作 + Vue.directive('focus', { + //在每个函数中,第一个参数,永远是 el ,表示 被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象(DOM对象) + bind: function (el) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,【只执行一次】 + // 在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用 + // 因为,一个元素,只有插入DOM之后,才能获取焦点 + // el.focus() + }, + inserted: function (el) { // inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】 + el.focus() + // 和JS行为有关的操作,最好在 inserted 中去执行,放置 JS行为不生效 + }, + updated: function (el) { // 当VNode更新的时候,会执行 updated, 【可能会触发多次】 + + } + }) +``` + +上方的代码中,如果我们把`el.focus()`这行代码写在`bind`方法里,是没有效果的(但不会报错)。没有效果是因为,在执行到`bind`方法的时候,元素还没有插入到dom中去。 + +由此可以看看出:`bind`、`inserted`、`updated`这三个钩子函数的执行时机不同,且执行的次数有区别。 + +(2)在指定的文本框上加``: + +```html + +``` + +完整版代码如下: + +```html + + + + + + + + Document + + + + + +
    + 搜索框: + +
    + + + + + + +``` + + +### 自定义全局指令:使用钩子函数的第二个binding参数拿到传递的值 + +**举例2**:设置DOM元素的color样式 + + +参考举例1中的写法,我们可能会这样给DOM元素设置样式: + +```html + + + + + + + + Document + + + + + +
    + 搜索框: + +
    + + + + + +``` + +如上方代码所示,我们自定义了一个指令`v-color`,然后在`input`标签中用上了这个指令,就给元素设置了color属性。但是这个代码有个弊端是:color的属性值在定义指令的时候,被写死了。如何完善呢?我们可以在DOM元素中传参。一起来看看。 + +代码如下:【荐】 + +```html + + + + + + + + Document + + + + + +
    + 搜索框1: + +
    + + + + + +``` + +上方代码中,bind方法里传递的第二个参数`binding`,可以拿到DOM元素中`v-color`里填的值。注意,`v-color="'green'"`,这里面写的是字符串常量;如果去掉单引号,就成了变量,不是我们想要的。 + +效果: + +![](http://img.smyhvae.com/20180610_1323.png) + +**自定义全局指令的简写形式**: + + +在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如上面的代码中,我们可以写成简写形式: + +```javascript + Vue.directive('color', function (el, binding) { //注意,这个function等同于把代码写到了 bind 和 update 中去 + el.style.color = binding.value + }) +``` + + +## 自定义私有指令 + +**自定义私有指令**:在某一个 vue 对象内部自定义的指令称之为私有指令。这种指令只有在当前vue对象的el指定的监管区域有用。 + +代码举例:(设置文字的font-weight属性) + +```html + + + + + + + + Document + + + + + +
    + 生命壹号 +
    + + + + +``` + +效果: + +![](http://img.smyhvae.com/20180610_1400.png) + +注意, el.style.fontWeight设置属性值,至少要600,否则看不到加粗的效果。 + +**自定义私有指令的简写形式**: + +在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如上面的代码中,我们可以写成简写形式: + +``` + //自定义私有指令(简写形式) + directives: { + 'fontweight': function (el, binding) { //注意,这个function等同于把代码写到了 bind 和 update 中去 + el.style.fontWeight = binding.value; + } + } +``` + + + + + + + diff --git "a/12-Vue\345\237\272\347\241\200/08-Vue\345\256\236\344\276\213\347\232\204\347\224\237\345\221\275\345\221\250\346\234\237\345\207\275\346\225\260.md" "b/12-Vue\345\237\272\347\241\200/08-Vue\345\256\236\344\276\213\347\232\204\347\224\237\345\221\275\345\221\250\346\234\237\345\207\275\346\225\260.md" new file mode 100644 index 00000000..37652a49 --- /dev/null +++ "b/12-Vue\345\237\272\347\241\200/08-Vue\345\256\236\344\276\213\347\232\204\347\224\237\345\221\275\345\221\250\346\234\237\345\207\275\346\225\260.md" @@ -0,0 +1,202 @@ +--- +title: 08-Vue实例的生命周期函数 +publish: true +--- + + + + + + + + + +## 介绍 + + + +- [vue实例的生命周期](https://cn.vuejs.org/v2/guide/instance.html#实例生命周期):从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期。 + + +- [生命周期钩子](https://cn.vuejs.org/v2/api/#选项-生命周期钩子):就是生命周期事件的别名而已。 + +生命周期钩子 = 生命周期函数 = 生命周期事件。 + + +## 生命周期函数的主要分类 + +![](http://img.smyhvae.com/20180422_1650.png) + +根据上面这张图,我们把生命周期函数主要分为三类。 + + +### 1、创建期间的生命周期函数 + +- beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性 + +- created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板。我们可以在这里进行Ajax请求。 + +- beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中 + +- mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示。(mounted之后,表示**真实DOM渲染完了,可以操作DOM了**) + + +**举例**: + + +```html + + + + + + Title + + + + + +
    +
    + + + + + +``` + +打印结果: + +![](http://img.smyhvae.com/20180610_1500.png) + +### 运行期间的生命周期函数 + +- beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点 + +- updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了。 + +PS:数据发生变化时,会触发这两个方法。不过,我们一般用watch来做。 + + +**举例**: + +```html + + + + + + Title + + + + + +
    + +

    {{ flag }}

    +
    + + + + + +``` + + +当我们点击按钮后,运行效果是: + +![](http://img.smyhvae.com/20180610_1528.png) + +可以看出: + +- 当执行 beforeUpdate 的时候,页面中的显示的数据还是旧的,但此时 data 数据是最新的 + +- updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的 + + + +### 3、销毁期间的生命周期函数 + +- beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。 + +- destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 + +PS:可以在beforeDestroy里**清除定时器、或清除事件绑定**。 + + +## 生命周期函数图解 + +![](http://img.smyhvae.com/20180611_2130.png) + +PS:图片来自网络。 + + + + + diff --git "a/12-Vue\345\237\272\347\241\200/09-Vue\344\270\255\347\232\204Ajax\350\257\267\346\261\202.md" "b/12-Vue\345\237\272\347\241\200/09-Vue\344\270\255\347\232\204Ajax\350\257\267\346\261\202.md" new file mode 100644 index 00000000..573bdcce --- /dev/null +++ "b/12-Vue\345\237\272\347\241\200/09-Vue\344\270\255\347\232\204Ajax\350\257\267\346\261\202.md" @@ -0,0 +1,561 @@ +--- +title: 09-Vue中的Ajax请求 +publish: true +--- + + + + + + + + + +## vue-resource的介绍 + +`vue-resource`是Vue高度集成的第三方包。 + +官网链接: + +- 文档(http相关): + +vue-resource 依赖于 Vue。所以,我们要按照先后顺序,导入vue.js和vue-resource.js文件。 + +**解释**: + +`vue.js`文件向Windows对象暴露了`Vue`这个关键词;`vue-resource.js`向Vue身上挂载了`this.$http`这个属性。于是,我们可以直接写`this.$http.get`或者`this.$http.post`或者`this.$http.jsonp`来调用。 + +## vue-resource 发送Ajax请求 + +常见的数据请求类型包括:get、post、jsonp。下面我们分别讲一讲。 + + +### get 请求 + +**格式举例**: + +```javascript + this.$http.get(url) + .then(function (result) { // 当发起get请求之后,通过 .then 来设置成功的回调函数 + console.log(result.body); // response.body就是服务器返回的成功的数据 + var result = result.body; + }, + function (err) { + //err是异常数据 + }); +``` + +获取到的`response.body`就是要获取的数据,但直接打印出来是 object,所以要记得转成string。 + +**举例**:获取数据 + +现规定,获取品牌数据的 api 接口说明如下: + +![](http://img.smyhvae.com/20180422_2140.png) + + +```html + + + + + + Document + + + + + + +
    + + + + + + + + + + + + + + + + + +
    编号名称创建时间操作
    {{item.id}}{{item.name}}{{item.ctime}} + 删除 +
    +
    + + + + + +``` + +上方代码中,我们用到了生命周期函数`created`,意思是:程序一加载,就马上在`created`这个函数里执行`getlist()`方法。 + + +运行的结果如下: + +![](http://img.smyhvae.com/20180422_2152.png) + +如果我直接在浏览器中输入请求的url,获取的json数据如下:(可以看到,这种方式获取的是相同的数据) + +![](http://img.smyhvae.com/20180422_2150.png) + + +### post请求 + +**格式举例**: + +```javascript + // 方法:$http.post(url, 传给服务器的请求体中的数据, {emulateJSON:true}) + // 通过 post 方法的第三个参数{ emulateJSON: true } ,来设置 提交的内容类型 为 普通表单数据格式 + this.$http.post(url, { name: '奔驰' }, { emulateJSON: true }) + .then(function (response) { + alert(response.body.message); + }, + function (error) { + + }); +``` + +上方代码中,post()方法中有三个参数,其中第三个参数是固定值,照着写就可以了。 + + +**代码举例**:(添加数据) + +现规定,添加品牌数据的 api 接口说明如下: + +![](http://img.smyhvae.com/20180422_1720.png) + + +代码如下:(在上一段代码的基础之上,添加代码) + +```html + + + + + + Document + + + + + + +
    + + + + + + + + + + + + + + + + +
    编号名称创建时间操作
    {{item.id}}{{item.name}}{{item.ctime}} + 删除 +
    +
    + + + + +``` + + +**代码举例**:(删除数据) + +```html + + + + + + Document + + + + + + +
    + + + + + + + + + + + + + + + + +
    编号名称创建时间操作
    {{item.id}}{{item.name}}{{item.ctime}} + + 删除 +
    +
    + + + + + +``` + + +### jsonp + +![](http://img.smyhvae.com/20180420_2250.png) + + +**格式举例**: + +```javascript + // 利用vue-resource中的jsonp方法实现跨域请求数据,这里要注意的是: + // url后面不需要跟callback=fn这个参数了,jsonp方法会自动加上 + this.$http.jsonp('http://vuecms.ittun.com/api/getlunbo?id=1') + .then(function (response) { + console.log(JSON.stringify(response.body)); + }, function (err) { + //err是异常数据 + }); +``` + +请求结果: + +![](http://img.smyhvae.com/20180420_2256.png) + + +## JSONP的实现原理 + +由于浏览器的安全性限制,默认不允许Ajax发起跨域(协议不同、域名不同、端口号不同)的请求。浏览器认为这种访问不安全。 + +**JSONP的实现原理**:通过动态创建script标签的形式,用script标签的src属性,代表api接口的url,因为script标签不存在跨域限制,这种数据获取方式,称作JSONP(注意:根据JSONP的实现原理,知晓,JSONP只支持Get请求)。 + + + 具体实现过程: + + +- 先在客户端定义一个回调方法,预定义对数据的操作 + +- 再把这个回调方法的名称,通过URL传参的形式,提交到服务器的api接口; + +- 服务器api接口组织好要发送给客户端的数据,再拿着客户端传递过来的回调方法名称,拼接出一个调用这个方法的字符串,发送给客户端去解析执行; + +- 客户端拿到服务器返回的字符串之后,当作Script脚本去解析执行,这样就能够拿到JSONP的数据了 + + +## axios + +除了 vue-resource 之外,还可以使用 `axios` 的第三方包实现实现数据的请求。 + + +## 通过Vue全局配置api接口的url地址 + +api接口的url地址包括:绝对路径+相对路径。 + +我们在做Ajax请求的时候,所填写的url建议填**相对路径**,然后把**绝对路径**放在全局的位置。 + +Vue就提供了这个功能。举例如下: + +```html + + + +``` + +如上方代码所示,第一步是在全局的位置写**绝对路径**: + +```javascript + Vue.http.options.root = 'http://smyhvae/'; +``` + +第二步是在Ajax请求的url中写**相对路径**:(注意,前面不要带`/`) + +```javascript +this.$http.get('api/getprodlist') +``` + + + diff --git "a/12-Vue\345\237\272\347\241\200/10-Vue\345\212\250\347\224\273.md" "b/12-Vue\345\237\272\347\241\200/10-Vue\345\212\250\347\224\273.md" new file mode 100644 index 00000000..dd420478 --- /dev/null +++ "b/12-Vue\345\237\272\347\241\200/10-Vue\345\212\250\347\224\273.md" @@ -0,0 +1,1158 @@ +--- +title: 10-Vue动画 +publish: true +--- + + + + + + + + + +## 前言 + +动画的作用:提高用户的体验,帮助用户更好的理解页面中的功能。 + + +## 使用过渡类名实现动画 + +### 官方文档的截图 + +过渡类名如下: + +![](http://img.smyhvae.com/20180616_1555.png) + +动画进入: + +- v-enter:动画进入之前的**初始**状态 + +- v-enter-to:动画进入之后的**结束**状态 + +- v-enter-active:动画进入的时间段 + +PS:第一、第二个是时间点;第三个是时间段。 + +动画离开: + +- v-leave:动画离开之前的**初始**状态 + +- v-leave-to:动画离开之后的**结束**状态 + +- v-leave-active:动画离开的时间段 + +PS:第一、第二个是时间点;第三个是时间段。 + + +### 使用举例(通过Vue的过渡类名来实现) + +`v-enter-to`和`v-leave`的状态是一样的。而且一般来说,`v-enter`和`v-leave-to`的状态也是一致的。所以,我们可以把这四个状态写成两组。 + +现在我们来做个例子:点击按钮时,让div显示/隐藏。 + +**1、引入**: + +如果我们不使用动画,应该是这样做: + + +```html + + + + + + + + Document + + + + +
    + + +

    这是一个H3

    +
    + + + + + +``` + + +**2、使用动画**:(通过Vue的过渡类名来实现) + +现在,我们加**淡入淡出**的动画,让div显示和隐藏。代码如下: + +```html + + + + + + + + Document + + + + + + +
    + + + + + +

    这是一个H3

    +
    +
    + + + + + + +``` + + +上方代码中,我们使用vue提供的``标签把需要被动画控制的元素,包裹起来;然后使用`.v-enter`、`.v-leave-to`等进行动画的定义。 + +运行效果如下: + +![](http://img.smyhvae.com/20180615_2200.gif) + + +**3、再加一个 transform 属性进行位移**: + +我们在上方代码的基础之上,加一个 transform 属性,让动画有一个位移的效果。完整代码如下: + + +```html + + + + + + + + Document + + + + + + +
    + + + + + +

    这是一个H3

    +
    +
    + + + + + +``` + + +效果如下: + +![](http://img.smyhvae.com/20180615_2205.gif) + +### 修改过渡类名的前缀 + +在上一小段中,`.v-enter`、`.v-leave-to`这些过渡类名都是以`v-`开头的。这样做,会有一个局限性:假设有两个DOM元素都用``进行了包裹,那这两个DOM元素就都具备了`v-`中所定义的动画。 + +那**如果我们想把两个DOM元素的动画进行分开定义**,该怎么做呢?这里,我们可以通过修改过渡类名的前缀来做。比如: + +第一步:(自定义别名) + +```html + +
    这是一个H6
    +
    +``` + +上方代码中,我们加了`name="my"`。 + +第二步:(我们就可以使用 `my-enter`、`.my-leave-to`这些类名了) + +```css + .my-enter, + .my-leave-to { + opacity: 0; + transform: translateY(70px); + } + +``` + + +完整代码举例如下; + + +```html + + + + + + + + Document + + + + + +
    + + + + + +

    这是一个H3

    +
    + +
    + + + + + + + +
    这是一个H6
    +
    +
    + + + + + +``` + +运行效果如下: + +![](http://img.smyhvae.com/20180616_1513.gif) + +## 使用第三方animate.css类库实现动画 + +animate.css网址: + +- 官方网站: + + +**代码举例**: + +下面的代码中,我们使用animate.css提供的`bounceIn`、`bounceOut`这两个类来做入场、离场的动画。代码如下: + +```html + + + + + + + + Document + + + + + + +
    + + + +

    这是一个H3

    +
    + +
    + + + + + +``` + + + +上面的代码中,注意: + +注意1:`enter-active-class`和`leave-active-class`这两个类名是Vue动画里的关键词,不能写成自己**随意起**的类名。 + +注意2:`bounceIn`、`bounceOut`这两个类不能直接使用,要在前面加上`animated`这个类;否则动画是不会生效的。当然,上面的代码中,我们还可以把`class = animated`这个代码移到`

    `标签里,效果是一样的,如下: + +```html + + +

    这是一个H3

    +
    + +``` + + +运行效果如下: + +![](http://img.smyhvae.com/20180616_1538.gif) + +**改进1**:(统一设置入场、出场动画的持续时间) + +我们把上面的代码改进一下,如果我们想给入场、出场动画设置持续的时间,可以使用`:duration`来做。如下: + + +```html + + + +

    这是一个H3

    +
    +``` + + +**改进2**:(分别设置入场、出场动画的持续时间) + +```html + + + +

    这是一个H3

    +
    +``` + + +## 钩子函数实现半场动画 + +只有出场动画、没有离场动画,这种就是属于半场动画。比如你把一件商品加入收藏,会出现一个动画;当再次点击收藏按钮的时候却看不到动画效果,这就说明,只有前一半才有动画。 + + +半场动画,可以使用钩子函数来实现。 + + +### 动画的钩子函数介绍 + +可以在属性中声明 JavaScript 钩子函数:(这八个钩子函数可以理解成是动画的生命周期) + +```html + + + +``` + + +我们可以这样理解:上面这八个钩子函数(四个入场、四个离场),对应了八个事件,我们要紧接着在methods中定义八个函数。 + +如果要定义半场动画,做法是:直接在methods中写入场动画的函数,不写离场动画的函数即可。 + +### 举例:使用钩子函数模拟小球半场动画 + +现在要实现的例子是:点击按钮后,让小球进行移动。完整代码如下: + +```html + + + + + + + + Document + + + + + +
    + + + +
    +
    +
    + + + + + + +``` + + +运行效果如下:(我们可以用这种动画效果,做类似于“加入购物车”的动画效果) + +![](http://img.smyhvae.com/20180616_1618.gif) + +上面的代码中,有两个地方要注意: + + +**注意1**: + +`el.offsetWidth`这行代码不能少。虽然这行代码没有实际的意义,但是少了之后,动画效果出不来: + +![](http://img.smyhvae.com/20180616_1620.gif) + +当然,我们也可以把这行代码换成`el.offsetHeight`、`el.offsetLeft`、`el.offsetTop`之类的,只要包含了offset就行。 + + +**注意2**: + +`enter()`函数里,函数的第二个参数要加上`done`,函数体的最后一行要写`done()`,表示**立即执行**后面的`afterEnter()`函数;如果没有这个`done`,则会**延迟执行**后面的`afterEnter()`函数: + +![](http://img.smyhvae.com/20180616_2145.gif) + +Vue官方文档的解释是这样: + + + > 当只用 JavaScript 过渡的时候,在`enter`和`leave`中必须使用`done`进行回调。否则,它们将被同步调用,过渡会立即完成。 + + + + +## 使用transition-group元素实现列表动画 + +现在的场景是:在一个`
      `列表中,如果我想给**指定的某个**`li`添加动画效果,该怎么做呢?(需要声明的是,这些`li`是用v-for循环进行遍历的) + +如果我们用``把`li`包裹起来,就会让所有的`li`都具备了动画,这显然是不可取的。 + +那该怎么做呢?这里我们就可以用`transition-group`进行包裹。 + +**代码举例1**:点击添加按钮后,给新增的 item 加个动画 + +```html + + + + + + + + Document + + + + + +
      + +
      + + + + + +
      + + + + + +
    • + {{item.id}} --- {{item.name}} +
    • +
      + + +
      + + + + + +``` + +运行效果如下: + +![](http://img.smyhvae.com/20180616_2240.gif) + + +**改进1**:添加删除item的功能 + +基于上面的代码,我们来添加**删除item**的功能,代码本应该是这样写: + + +```html + + + + + + + + Document + + + + + +
      + +
      + + + + + +
      + + + + + +
    • + {{item.id}} --- {{item.name}} +
    • +
      + + +
      + + + + + + +``` + +运行效果如下: + +![](http://img.smyhvae.com/20180617_1555.gif) + +**改进2:**: + +上图中,我们发现,当我删除第2个item时,**第3、第4个item在往上移动的过程比会较突兀**。为了改进这个地方,我们可以给`.v-move`、`.v-leave-active`加一些动画属性。最终,完整版代码如下: + +```html + + + + + + + + Document + + + + + +
      + +
      + + + + + +
      + + + + + +
    • + {{item.id}} --- {{item.name}} +
    • +
      + + +
      + + + + + +``` + +运行效果如下: + +![](http://img.smyhvae.com/20180617_1556.gif) + +### transition-group中appear和tag属性的作用 + +我们可以在上面的代码基础之上,给transition-group加上`appear`属性,这样的话,可以让transition-group包裹的所有DOM元素在刷新时,有**淡入效果**。 + +```html + + + + + + + + Document + + + + + +
      + +
      + + + + + +
      + +
        + + + + + +
      • + {{item.id}} --- {{item.name}} +
      • +
        +
      + +
      + + + + + +``` + +![](http://img.smyhvae.com/20180617_1600.gif) + +**改进**:`transition-group`的`tag`属性 + +上面的代码中,我们审查一下代码元素会发现,用`transition-group`包裹的元素,会被默认套上一层``: + +![](http://img.smyhvae.com/20180617_1620.png) + +这个``虽然没有太大副作用,但是不符合代码规范。为了解决这个问题,我们可以通过`tag`属性给`transition-group`包谷的元素套上一层`
        `,然后把现有的`
          `注释掉,就可以了。最终代码如下: + +```html + + + + + + + + Document + + + + + +
          + +
          + + + + + +
          + + + + + + + +
        • + {{item.id}} --- {{item.name}} +
        • +
          + + +
          + + + + + +``` + +这样的话,审查元素的效果如下: + +![](http://img.smyhvae.com/20180617_1621.png) + diff --git "a/12-Vue\345\237\272\347\241\200/11-Vue\347\273\204\344\273\266\347\232\204\345\256\232\344\271\211\345\222\214\346\263\250\345\206\214.md" "b/12-Vue\345\237\272\347\241\200/11-Vue\347\273\204\344\273\266\347\232\204\345\256\232\344\271\211\345\222\214\346\263\250\345\206\214.md" new file mode 100644 index 00000000..0419fab4 --- /dev/null +++ "b/12-Vue\345\237\272\347\241\200/11-Vue\347\273\204\344\273\266\347\232\204\345\256\232\344\271\211\345\222\214\346\263\250\345\206\214.md" @@ -0,0 +1,888 @@ +--- +title: 11-Vue组件的定义和注册 +publish: true +--- + + + + + + + + +## 前言 + +### 什么是组件 + +**组件**: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可。 + + +### 模块化和组件化的区别 + +- 模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一 + +- 组件化:是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用 + + +## 全局组件的定义和注册 + +组件`Component`是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。 + +全局组件的定义和注册有三种方式,我们接下来讲一讲。 + +### 写法一 + +写法一:使用Vue.extend方法定义组件,使用 Vue.component方法注册组件。 + +代码举例: + +```html + + + + + + + + Document + + + + +
          + + +
          + + + + + +``` + +上方代码中,在注册组件时,第一个参数是标签名,第二个参数是组件的定义。 + +运行结果如下: + +![](http://img.smyhvae.com/20180422_2230.png) + +代码截图如下: + +![](http://img.smyhvae.com/20180422_2223.png) + +上图中,注意两点: + +**注意1**、红框部分,要保证二者的名字是一致的。如果在注册时,组件的名称是**驼峰命名**,比如: + +```javascript +Vue.component('myComponent', myAccount); //第一个参数是组件的名称(标签名),第二个参数是模板对象 +``` + +那么,在标签中使用组件时,需要把大写的驼峰改为小写的字母,同时两个单词之间使用`-`进行连接: + +```html + + +``` + +所以,为了避免名字不一致的问题,我们注册组件时,组件的名称可以直接写成`my-component`。比如:(避免驼峰不一致的建议写法) + +```javascript + Vue.component('my-component', myAccount); +``` + + + +**注意2**、绿框部分,一定要用一个大的根元素(例如`
          `)包裹起来。如果我写成下面这样,就没有预期的效果: + +``` + template: '

          登录页面

          注册页面

          ' +``` + +结果如下:(并非预期的效果) + +![](http://img.smyhvae.com/20180422_2232.png) + +### 写法二 + +写法二:Vue.component方法定义、注册组件(一步到位)。 + +代码如下: + +```html + + + + + + + + Document + + + + +
          + +
          + + + + + +``` + +代码截图如下: + +![](http://img.smyhvae.com/20180422_2251.png) + +上图中,同样注意两点: + +1、红框部分,要保证二者的名字是一致的。 + +2、绿框部分,一定要用一个大的根元素(例如`
          `)包裹起来。如果我写成下面这样,就没有预期的效果: + +``` + template: '

          登录页面

          注册页面

          ' +``` + +结果如下:(并非预期的效果) + +![](http://img.smyhvae.com/20180422_2232.png) + + +### 写法三【荐】 + +> 上面的写法一、写法二并不是很智能,因为在定义模板的时候,没有智能提示和高亮,容易出错。我们不妨来看看写法三。 + +写法三:将组件内容定义到template标签中去。 + +代码如下: + +```html + + + + + + + + Document + + + + + + + +
          + + +
          + + + + + +``` + +代码截图如下: + +![](http://img.smyhvae.com/20180422_2256.png) + +写法三其实和方法二差不多,无非是把绿框部分的内容,单独放在了`