-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsearch.xml
223 lines (223 loc) · 132 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[前端开发规范手册(命名、HTML、CSS、JS、ES6、React)]]></title>
<url>%2F2019%2F03%2F05%2Fstandard%2Findex%2F</url>
<content type="text"><![CDATA[简介前端开发规范手册(命名、HTML、CSS、JS、ES6、React)完整链接,欢迎给出您的宝贵意见; GitHub源码地址,要是觉得文档还能凑合着看,欢迎 star ~ 不以规矩,不能成方圆。 对于团队而言,统一很重要,代码是写给人看的,然后顺便跑在机器上而已。 有过忧虑吗你是不是总是在抱怨项目组的各方面不统一,不好维护,千奇百怪? 你是不是每次提交代码的时候总要拉某某人过来看下各种冲突? 你是不是每次merge代码的时候总要话很长的时间去解决不同格式的代码冲突? 你是不是有时候为了解决一个bug好几天没睡好,最终定位的问题也许是一个分号、或是书写规范? 人人都在恐慌,人人都在责怪他人,但殊不知,换了好几个项目都是类似,想过为什么吗? 规范的意义每一种事物都有它被发明时,都会有其用处和目的,每一个事物都是自己擅长和适合的领域; 我们要在对的地方使用它,让它做自己擅长的事。 规范的代码可以促进团队合作; 规范的代码可以减少bug处理; 规范的代码可以降低维护成本; 规范的代码有助于代码审查; 养成代码规范的习惯,有助于程序员自身的成长; 规范的目的我们知道,当一个团队开始指定并实行编码规范的话,错误就会变得更加显而易见。 如果一段特定的代码不符合规范的话,它有可能只是代码风格错误,而也有可能会是 bug。 早期指定规范就使得代码审核得以更好的开展,并且可以更精确的地定位到错误。 只要开发者们能够保证源代码源文件都严格遵循规范,那接下去所使用的混淆、压缩和编译工具则可投其所好不尽相同。 为了提高工作效率,便于后台人员添加功能及前端后期优化维护,输出高质量的文档。 在项目构建中,使结构更加清晰,代码简明有序,有一个更好的前端架构。 介绍工程架构基于 vuepress 搭建而成,源码地址https://github.com/niceboybao/front-end-develop-standard,如有问题请点击New Issue,欢迎 push 相关内容加入贡献者行列,要是觉得文档还能凑合着看,欢迎 star ~ 文档编写参考多个热门的前端开源规范参考,并结合个人项目总结而成。项目 快速预览图 如下: 参考文档 使用Doctype激活浏览器模式 AMD 和 CMD 的区别有哪些? AMD规范与CMD规范的区别 airbnb JavaScript Style Guide airbnb JavaScript Style Guide中文版 通过分析github代码库总结出来的工程师代码书写习惯 「掘金」前端开发规范:命名规范、html规范、css规范、js规范 编码规范 by @mdo Max Yu javascript编码规范 Max Yu CSS编码规范 前端编码规范之JavaScript 网易前端开发规范-css规范-html规范-工程师规范 Baidu EFE team 前端开发规范大全(包括react.js规范) 前端架构之路(3) - 前端开发规范 腾讯前端IMWEB团队社区 前端编码规范(4)- CSS 和 Sass (SCSS) 规范 JavaScript 开发规范 开源协议MIT License]]></content>
<categories>
<category>Standard</category>
</categories>
<tags>
<tag>Standard</tag>
</tags>
</entry>
<entry>
<title><![CDATA[前端免费高清电子书(史上最全)]]></title>
<url>%2F2019%2F03%2F05%2Fothers%2Fbooks%2F</url>
<content type="text"><![CDATA[简介平时自己收藏和整理的前端系列免费高清电子书(大概有100多本),点击下面对应链接即可下载,无需密码;电子书种类全面,如下图所示。 小编自己也喜欢看书,平时也会收集一些电子书先翻一翻,如果看得还ok的话,就买实体书 注:转载请注明出处,谢谢配合 Html+css系列 零基础学HTML+CSS [第三版].pdf HTML5移动Web开发指南.pdf HTML5权威指南.pdf HTML5 Canvas开发详解(第2版).pdf HTML5 CANVAS游戏开发实战高清版.pdf CSS禅意花园.pdf CSS网站布局实录(第二版).pdf CSS世界(张鑫旭著).pdf CSS3学习必备书籍(CSS3 实战).pdf [精通CSS高级Web标准解决方案].pdf web系列 响应式Web设计 HTML5和CSS3实战(第2版).pdf 渐进增强的Web设计.pdf Web性能权威指南.pdf Web前端黑客技术揭秘.pdf WEB前端标准在各浏览器中的差异.pdf Web开发敏捷之道.pdf WEB 性能实践日志_目录 高清完整版.pdf Web前端自动化构建:Gulp、Bower和Yeoman开发指南.pdf 高性能网站建设指南.pdf JavaScript系列 JavaScript高级程序设计-第3版.pdf 你不知道的JavaScript-上卷.pdf 你不知道的JavaScript-中卷.pdf 你不知道的JavaScript-下卷.pdf 同构JavaScript应用开发.pdf 深入理解JavaScript.pdf 高性能JavaScript编程.pdf JavaScript数据结构与算法.pdf JavaScript语言精粹.pdf JavaScript异步编程.pdf JavaScript性能优化:度量、监控与可视化.pdf JavaScript网页动画设计.pdf JavaScript面向对象编程指南.pdf JavaScript框架设计.pdf JavaScript快速全栈开发.pdf JavaScript脚本特效编程给力起飞.pdf JavaScript程序的188个建议 .pdf JavaScript编程实战.pdf JavaScript+DOM编程艺术.pdf JavaScript 权威指南(第6版).pdf JavaScript ES6 函数式编程入门经典-试读.pdf 21天学通JavaScript.pdf 精通正则表达式(第3版)中文版.pdf JavaScript模式.扫描版.pdf Es6标准入门.pdf leetcode-solution.pdf Ajax从入门到精通.pdf jquery系列 jQuery权威指南.pdf jQuery开发从入门到精通.pdf 锋利的jQuery(高清扫描版-有书签).pdf Typescript系列 Typescript手书.pdf Learning TypeScript中文版.pdf 公众号和小程序系列 小程序从0到1:微信全栈工程师一本通.pdf 微信小程序入门指南.pdf 微信小程序:开发入门及案例详解.pdf 21天精通微信小程序开发.pdf 微信公众帐号开发教程 (1).pdf node.js系列 深入浅出Node.js.pdf 超实用的Node.js代码段.pdf Node与Express开发.pdf nodejs实战pdf+源码.zip Node.js项目实践-构建可扩展的Web应用.pdf Node.js进阶之路.pdf Learning.Node-Node学习指南.pdf python系列 Python数据挖掘入门与实践(中文完整版).pdf Python核心编程 第3版.pdf Python编程:从入门到实践.pdf Python宝典.pdf python.pdf 服务器配置必读 精通Nginx.pdf Nginx高性能Web服务器详解.pdf Linux运维之道(丁明一).pdf Linux Shell脚本攻略(第2版).pdf 前端框架系列 Bootstrap实战.pdf Bootstrap入门经典.pdf 深入浅出React和Redux.pdf 深入REACT技术栈 .pdf react中文入门教程.pdf React全栈.pdf react快速上手开发完整版.pdf React精髓.pdf React开发实战.pdf React Native跨平台移动应用开发.pdf 权威指南Vue.js.pdf Vue.js实战.pdf Vue.js 前端开发 快速入门与专业应用.pdf Angular权威教程-高清完整版.pdf 迈向Angular 2:基于TypeScript的高性能SPA框架.pdf 揭秘Angular2.pdf 全栈开发之道:MongoDB+Express+AngularJS+Node.js.pdf Ionic实战:基于AngularJS的移动混合应用开发.pdf 其他 Jenkins权威指南.pdf Cocos2d-JS游戏开发.pdf THREE.JS开发指南.pdf WebGL入门指南_PDF电子书下载 高清 带索引书签目录.pdf 前端架构设计中文版.pdf 精通Git 第二版.pdf 代码整洁之道.pdf 代码阅读方法与实践.pdf Sass和Compass设计师指南.pdf HTTPS权威指南.rar 图解HTTP.pdf 深入浅出Webpack.pdf 如何构建后现代前端工程化开发体系.pdf 百度、淘宝、网易、搜狐前端开发面试题集锦.pdf 目前就是这些,后期还有相关文档的话不定期更新。大家有好的前端电子书的话欢迎留言,乐于交流,我们一起做朋友。转发请注明出处,原文链接https://juejin.im/post/5c0098f66fb9a049dd80019e]]></content>
<categories>
<category>Others</category>
</categories>
<tags>
<tag>Others</tag>
</tags>
</entry>
<entry>
<title><![CDATA[阿里云服务器(2、jenkins实现前端自动化部署)]]></title>
<url>%2F2019%2F03%2F05%2Fothers%2Fjenkins%2F</url>
<content type="text"><![CDATA[先直接怼成品 工程项目开源在GitHub上,平时迭代提交一些功能后,点击对应的Jenkins工程一键构建,即完成发布。是不是听了后感觉很高大上! 听起来是不是感觉很省事,平时我们要发布工程代码到自己的服务器上,像那种(vue/angular/react)项目的话,总是要跑很多npm命令,然后打包啊,移动啊,解压啊。想想每次都这样是不是很浪费时间,要是一个工程build10分钟,那你还要时刻看着,以便接着运行命令。 如何解决问题呢?接下来我们进入正文。 简介Jenkins是一款开源自动化服务器,旨在自动化连续集成和交付软件所涉及的重复技术任务。 Jenkins是基于Java的,可以从Ubuntu软件包安装,也可以通过下载和运行其Web应用程序ARchive(WAR)文件进行安装 - 构成一个完整的Web应用程序的集合,该文件旨在在服务器上运行。 准备工作 自己的GitHub账号,及想要部署的仓库 有自己的云服务器(小编的为阿里云Ubuntu 16.04 64位) 云服务器已做过nginx配置(未做的请参考阿里云服务器(1、nginx配置实战)) GitHub账号方便Jenkins直接从平台上拉取代码,然后做一系列操作,云服务器用于安装Jenkins不用每次用都需要启动,小编的为阿里云Ubuntu 16.04 64位,没有对号入座的请酌情参考。在配置Jenkins前需要先配置下nginx,需要的请参考我的文档 阿里云服务器(1、nginx配置实战) 先安装javaJenkins基于Java, 所以需要先安装java。到官网下载即可jdk-8u191-linux-x64.tar.gz 我一般习惯把安装的软件放到目录/usr/local下。下载上传好后,解压java到相应目录 1tar -zxvf jdk-8u65-linux-x64.tar.gz /usr/local 编辑环境变量,在/etc/profile文件中添加环境变量,Linux的所有用户都可以使用。 1vim /etc/profile 在文件最后添加内容如下: 123export JAVA_HOME=/usr/local/jdk1.8.0_191export PATH=$JAVA_HOME/bin:$PATHexport CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jart 到此,java已安装完成,检查时候出现如下图即安装完成 后安装Jenkins包含在默认Ubuntu软件包中的Jenkins版本往往落后于项目本身的最新版本。 为了利用最新的修复和功能,我们将使用项目维护的软件包来安装Jenkins。 首先,我们将存储库密钥添加到系统。 1wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add - 添加密钥后,系统将返回 OK 。 接下来,我们将Debian包存储库地址附加到服务器的sources.list : 1echo deb http://pkg.jenkins.io/debian-stable binary/ | sudo tee /etc/apt/sources.list.d/jenkins.list 当这两个都到位时,我们将运行update ,以便apt-get将使用新的存储库: 1sudo apt-get update 最后,我们将安装Jenkins及其依赖项 1sudo apt-get install jenkins 启动Jenkins使用systemctl我们将启动Jenkins: 1sudo systemctl start jenkins 由于systemctl不显示输出,我们将使用其status命令来验证它是否成功启动: 1sudo systemctl status jenkins 如果一切顺利,输出的开始应显示服务处于活动状态。 注意:我在安装的过程中遇到了java路径找不到的问题,解决方案是建立一个软连接即可,请参考 ERROR: No Java executable found in current PATH 设置防火墙(ufw)ufw是一个主机端的iptables类防火墙配置工具 安装的话,ubuntu很友好,一般都会给安装命令的 1sudo apt-get install ufw 开启,建议默认关闭所有外部访问 12sudo ufw enablesudo ufw default deny 默认情况下,Jenkins在端口8080上运行,因此我们将使用ufw打开该端口:(自定义的端口需另外开启) 1sudo ufw allow 8080 查看防火墙状态 1sudo ufw status 注意:既然开启了防火墙,那不要吧自己给墙了,比如ssh,nginx,http,https等这些端口可别忘记打开了。 可以使用sudo netstat -plntu 查看端口占用情况 1sudo netstat -plntu 然后根据端口占用情况按需开启防火墙 12345sudo ufw allow 80 #允许外部访问80端口(nginx默认端口)sudo ufw allow ssh #ssh默认端口sudo ufw allow http #http默认端口sudo ufw allow https #https默认端口sudo ufw allow 9180 #Jenkins自定义端口端口 自定义Jenkins端口Jenkins 默认端口是8080,在配置文件/etc/default/jenkins 中定义。 1234# UMASK=027# port for HTTP connector (default 8080; disable with -1)HTTP_PORT=9180 自定义好端口后,需要重启下Jenkins,打开http:// ip_address_or_domain_name :8080应该看到”解锁Jenkins“屏幕 123sudo systemctl start jenkins #启动sudo systemctl status jenkins #查看sudo systemctl restart jenkins #重启 配置JenkinsJenkins安装完成后,打开http:// ip_address_or_domain_name :8080应该看到”解锁Jenkins“屏幕如下图: 按照提示 输入如下命令获取到密码 1sudo cat /var/lib/jenkins/secrets/initialAdminPassword 将获取的密码字符串粘贴到password字段中,点击继续,跳转到插件安装页面 如果是Jenkins小白的话,还是建议用推荐的方式安装插件,安装过程中需要比较长的一段时间。 安装完成后,系统将提示您设置第一个管理用户。 可以跳过此步骤,并使用上面使用的初始密码作为admin继续,但是我们将花一点时间创建用户。 注意:默认Jenkins服务器未加密,因此使用此表单提交的数据不受保护。 当您准备好使用此安装时,请按照指南如何使用Nginx反向代理将SSL配置为Jenkins 。 这将保护用户凭据和关于通过Web界面发送的构建的信息。 注意:小编在安装Jenkins后,有出现过登录页白屏的情况,解决方案如下 jenkins配置权限不对导致无法登陆或者空白页面解决办法 123<authorizationStrategy class="hudson.security.FullControlOnceLoggedInAuthorizationStrategy"> <denyAnonymousReadAccess>true</denyAnonymousReadAccess></authorizationStrategy> 用Jenkins自动化部署一个GitHub工程登录Jenkins后,我们先新建一个任务 输入一个任务名称,选择构建一个自由风格的软件项目 配置过程中可适当写点描述,源码管理选择git,然后贴上你GitHub上对应要构建的仓库克隆链接,可对应的分支。如下图: 在构建里面输入你拉取代码到Jenkins工作环境后,需要执行的一些命令行,如npm install,build等。 因为我是一个react工程,所以我先执行npm install,后打包构建,最后移到我服务器的根目录下面,即完成发布。命令如下: 1234567891011121314151617181920echo 'check project path'pwdlsecho 'check npm && node version'npm --versionnode --versionecho 'start npm install'npm installecho 'start build project'npm run build-prodtar czvf www.tar.gz ./www/*echo 'delete dist and cache-loader'rm -rf www/rm -rf .cache-loader/mv -f www.tar.gz /usr/share/nginx/html/pccd /usr/share/nginx/html/pcecho 'delete old dist'rm -rf www/tar -xzvf www.tar.gzrm -rf www.tar.gz 构建完成后,显示蓝色即为构建成功,可以选择具体一次的构建,里面还可以看构建日志 注意:一个工程首次构建的话,为了保险起见,把工程clone下来后,先在工程对应的文件下,把需要执行的命令跑一遍,一步步测试成功后,在贴到Jenkins里面一键构建。 默认Jenkins 各个工程路径路径为 1cd /var/lib/jenkins/workspace/ 默认Jenkins 各个工程build详细结果的路径为 1cd /var/lib/jenkins/jobs/ 其他构建场景Jenkins比较常见的除了构建自由风格工程外,还可以构建一条pipeline(中文名:流水线) 新建任务的时候,选择pipeline,再选择pipeline script,用pipeline语法编辑每个管道要执行的步骤即可,如图: 1234567891011121314151617181920pipeline{ agent any stages { stage('Build') { steps{ echo 'This is a build step' } } stage('Test') { steps{ echo 'This is a test step' } } stage('Deploy') { steps{ echo 'This is a deploy step' } } }} 这样构建完后,构建步骤一目了然 小编后续讲发布一篇在服务器搭建gitlab的文档,那时可以选择用pipeline构建自己的gitlab工程。 遇到的问题及解决方案 ERROR: No Java executable found in current PATH jenkins转换显示语言为中文简体(jenkins汉化) ubuntu的ufw如何开放特定端口? ssh开启防火墙情况下远程连接服务器【解决密码正确但拒绝访问问题】 jenkins配置权限不对导致无法登陆或者空白页面解决办法]]></content>
<categories>
<category>Others</category>
</categories>
<tags>
<tag>Others</tag>
</tags>
</entry>
<entry>
<title><![CDATA[阿里云服务器(1、nginx配置实战)]]></title>
<url>%2F2019%2F03%2F05%2Fothers%2Fnginx%2F</url>
<content type="text"><![CDATA[简介先来一波福利广告(已过期)双十一了,阿里云推出了史上最优惠的云服务器产品(点击这里查看详情),1核2G新用户只需要99元/年,一次性买3年只需要不到300元,价格确实极大的优惠。 要是老用户的话可以用新开一个账号,用亲戚朋友的身份证认证一下也能享受1折优惠,加入我的战队(点击这里查看详),邀请一个人差不多能瓜分战队的 50元分红+50元现金红包+25%返现 。打个比方,假如你是新用户,你买了一个3年的云服务器一共300块,买过后,你成功邀请一人(下单3年的云服务器)就可分50(战队红包) + 50(现金红包) + 300*25%(返利红包)。相当于买服务器的钱回来了一半(折上5折),听着是不是很诱惑人,进来了解下吧;目前战队排名是top15,后名次靠前的话还有更大的优惠。https://m.aliyun.com/act/team1111/#/share?params=N.QJPTsZki4i.0vr9aipb nginx配置连接服务器很多前端的小伙伴买了云服务器后,担心不会配置,毕竟很多的前端还不是很会配置nginx,这里小编详细讲解下我买的阿里云服务器配置的过程。 点击上面链接就可参团购买,购买过程中推荐系统选择CentOS和Ubuntu系统。Ubuntu系统用户占用率高,所以文档自然也多,比较适合新手;CentOS比较适合企业和商用,一般看你们公司用的都是CentOS系统的;具体2者的区别可查看这里;小编买的是Ubuntu 16.04 64位。其他的选项选择默认就行,地区只要是国内的都很快。 买好后,点击头像=>选择产品服务=>云服务器,即可看到购买过的服务器产品。基本信息,配置信息,对cpu的监控一目了然。买阿里云的一个主要原因还是阿里云盾安全。 可以在更多里面修改远程连接密码和重置服务器密码,修改好后,尝试远程连接下,先输入远程连接密码,后登陆用户名(root)、密码即可。 当然,也可直接使用命令行链接 : 12sudo ssh 服务器外网ip输入电脑密码,输入服务器密码 除此之外,你也可用工具链接,对于 lunix 命令不是很熟悉的小伙伴比较实用。 这里推荐用Transmit和Filezilla其他的都一样,用户名输入root,端口选择 22 即可。 安装Nginx更新ubuntu软件源 1234sudo apt-get updatesudo apt-get install -y python-software-properties software-properties-commonsudo add-apt-repository ppa:chris-lea/node.jssudo apt-get update 安装nginx 123sudo apt-get install nginx# 检查是否安装成功nginx -v 安装好的文件位置: 1234/usr/sbin/nginx:主程序/etc/nginx:存放配置文件/usr/share/nginx:存放静态文件/var/log/nginx:存放日志 其实从上面的根目录文件夹可以知道,Linux系统的配置文件一般放在 /etc,日志一般放在 /var/log,运行的程序一般放在 /usr/sbin 或者 /usr/bin。当然,如果要更清楚Nginx的配置项放在什么地方,可以打开 /etc/nginx/nginx.conf。 安装其他常用工具1、安装nodejs 123sudo apt-get install nodejssudo apt install nodejs-legacysudo apt install npm 更新npm的包镜像源,方便快速下载 12sudo npm config set registry https://registry.npm.taobao.orgsudo npm config list 全局安装n管理器(用于管理nodejs版本) 1sudo npm install n -g 安装最新的nodejs(stable版本) 1234sudo n stable# 检查是否安装成功node -vnpm -v 2、安装webpack 12npm install webpack-cli -gnpm install webpack -g 3、安装git 如果系统未安装git的话,就会非常友好的提示安装git的命令: 1apt-get install git 在云服务器上,关于git的相关操作就不方便用图形界面化工具了,现在命令行的优势出来了,具体git命令请参考 遗漏的工具后续会补上 配置nginxnginx安装完成后,配置文件为 /etc/nginx/nginx.conf 和 /etc/nginx/conf.d/default.conf 1234cd /etc/nginxvim nginx.confcd /etc/nginx/conf.dvim default.conf 自定义nginx.conf 配置 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485#运行用户,默认即是nginx,可以不进行设置user root;#Nginx进程,一般设置为和CPU核数一样worker_processes 1;#进程pid存放位置pid /run/nginx.pid;events { worker_connections 1024; # 单个后台进程的最大并发数 # multi_accept on;}http { ## # Basic Settings ## sendfile on; #开启高效传输模式 tcp_nopush on; #减少网络报文段的数量 tcp_nodelay on; keepalive_timeout 65; #保持连接的时间,也叫超时时间 types_hash_max_size 2048; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; #文件扩展名与类型映射表 default_type application/octet-stream; #默认文件类型 ## # SSL Settings ## ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ## # Logging Settings ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # Gzip Settings ## gzip on; #开启gzip压缩 gzip_disable "msie6"; # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; ## # Virtual Host Configs ## include /etc/nginx/conf.d/*.conf; #包含的子配置项位置和文件 # include /etc/nginx/sites-enabled/*;}#mail {# # See sample authentication script at:# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript## # auth_http localhost/auth.php;# # pop3_capabilities "TOP" "USER";# # imap_capabilities "IMAP4rev1" "UIDPLUS";## server {# listen localhost:110;# protocol pop3;# proxy on;# }## server {# listen localhost:143;# protocol imap;# proxy on;# }#} 自定义default.conf 配置 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162server { listen 80; #配置监听端口 server_name localhost; #配置域名 #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location / { #服务默认启动目录 root /usr/share/nginx/html/pc; #pc # nginx适配pc和app设备 if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') { root /usr/share/nginx/html/app; #app } index index.html; #默认访问文件 allow all; #允许访问的ip # deny all; #拒绝访问的ip } # redirect error pages to the static page /404.html error_page 404 /static/html/404/404.html; # 配置404页面 # redirect server error pages to the static page /50x.html error_page 500 502 503 504 /static/html/404/500.html; #错误状态码的显示页面,配置后需要重启 # ^~ 表示uri以某个常规字符串开头,大多情况下用来匹配url路径,nginx不对url做编码,因此请求为/static/20%/aa, # 可以被规则^~ /static/ /aa匹配到(注意是空格)。 location ^~ /static/ { root /usr/share/nginx/html; allow all; #允许访问的ip # deny all; #拒绝访问的ip } location = /50x.html { root /usr/share/nginx/html/pc/; #pc # nginx适配pc和app设备 if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') { root /usr/share/nginx/html/app/; #app } } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } 自定义默认目录我们服务的默认目录放在 /usr/share/nginx/html 了下。 12cd /usr/share/nginx/htmlls 假如你要定义服务器的默认访问目录,修改 location / 中的root即可,不过需要开通下你自定义目录的权限。 以/root/www是自定义目录为例 123# 需要一层层分别开通权限chmod -R 777 /rootchmod -R 777 /root/www 假如你使用的是 Transmit 等服务器工具,也可用工具查看 自定义错误页面1234# redirect error pages to the static page /404.htmlerror_page 404 /static/html/404/404.html; # 配置404页面# redirect server error pages to the static page /50x.htmlerror_page 500 502 503 504 /static/html/404/500.html; #错误状态码的显示页面,配置后需要重启 然后在你默认或者自定义的服务器目录下,根据你的错误页配置,新建相关的页面即可。 Nginx访问权限和路径匹配规则在匹配规则里面,有2个字段可以控制这个规则下的访问权限 1234location / { allow all; #允许访问的ip # deny all; #拒绝访问的ip} 实际情况中,访问权限的控制还是比较复杂的,例如,要求服务器 static(静态目录)所有用户都能访问,且,重新定义访问路径,我们需要location块来完成相关的需求匹配。 1234567# ^~ 表示uri以某个常规字符串开头,大多情况下用来匹配url路径,nginx不对url做编码,因此请求为/static/20%/aa,# 可以被规则^~ /static/ /aa匹配到(注意是空格)。location ^~ /static/ {root /usr/share/nginx/html;allow all; #允许访问的ip# deny all; #拒绝访问的ip} 对于nginx路径匹配规则,也需要简单的了解一下 = 表示精确匹配 ^~ 表示uri以某个常规字符串开头,大多情况下用来匹配url路径,nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。 ~ 正则匹配(区分大小写) ~* 正则匹配(不区分大小写) !~和!~*分别为区分大小写不匹配及不区分大小写不匹配 的正则 / 任何请求都会匹配 符号的优先级 首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。 Nginx反向代理的设置后续补充。 Nginx适配PC或移动设备如上述配置: 123456#服务默认启动目录root /usr/share/nginx/html/pc; #pc# nginx适配pc和app设备if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {root /usr/share/nginx/html/app; #app} 123456#服务默认启动目录root /usr/share/nginx/html/pc; #pc# nginx适配pc和app设备if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {root /usr/share/nginx/html/app; #app} 可用app和pc访问我的服务器查看效果 47.99.212.100 配置阿里云安全组从上面的配置文件可以看出,nginx服务监听的是80端口,所以记得到ECS实例一下打开端口。步骤如下: 进入阿里云控制台,并找到ECS实例。 点击实例后边的”更多” 点击”网络和安全组” ,再点击”安全组配置” 选择”安全组列表”,再点击”安全组配置”,再点击”加入安全组规则” 进行80端口的设置,具体设置如图。 nginx 相关命令 在nginx配置的过程中,我们①先安装nginx;安装好后,检查是否安装成功;②然后开始做相关nginx配置;③配置完后检查配置是否正常;④然后启动nginx;⑤后续每次改动nginx配置都需重启nginx; 启动nginx 服务 1234#方法一nginx#方法二systemctl start nginx.service 查看所有启动的nginx进程 1ps aux | grep nginx 停止Nginx服务 123456#方法一nginx -s stop#方法二nginx -s quit#方法三killall nginx 检查nginx配置是否正常 1nginx -t 重启nginx服务 1sudo nginx -s reload 查看端口占用情况 1netstat -tlnp nginx操作常用的一些命令ssh链接云服务器 1sudo ssh 服务器外网ip 新建文件夹 1mkdir www 移动文件 1mv node-v6.10.0-linux-x64 nodejs 解压文件 1tar -xvf node-v6.10.0-linux-x64.tar.xz 查看文件路径 1pwd 访问文件 12cdls 编辑文件 1vim nginx.conf]]></content>
<categories>
<category>Others</category>
</categories>
<tags>
<tag>Others</tag>
</tags>
</entry>
<entry>
<title><![CDATA[还在记git命令?快试试SourceTree]]></title>
<url>%2F2019%2F03%2F05%2Ftools%2FSourceTree%2F</url>
<content type="text"><![CDATA[简介背景用过 git 版本管理的,对 SourceTree 应该不陌生的。它是 git 一个跨平台的 GUI 工具。界面很不错,而且功能也是很强大的。下面小编就针对SourceTree做一个小小的总结归纳,希望大家喜欢! SourceTree下载官网下载地址Download for Mac OSX or Windows 这款软件是免费的,但是需要注册,登录授权;登录和授权这两个步骤没啥问题,但对于注册需要科学上网才能注册的了。 其实一些编辑器也是可以用作git提交代码的,包括合并代码等都行,之前整理过一 篇关于 Visual Studio Code如何提交代码的,在VS Code中也有很多git提交的插件。但是对比了发现SourceTree更强大更专业一点。 添加仓库clone仓库 新建分支在GitHub或者gitlab上面新建一个新的远程分支比较简单,只需要规定从哪边clone的即可。 ⚡ 需要注意的是,新建的远程分支也许在SourceTree上面没显示,这时候我们可以从origin在拉取一遍,也许数据没有同步过来。 检出分支在本地开发的话,当然要新建一个某远程分支相对应的本地分支,这时候 SourceTree的检出功能就显得很强大了。检出分支相当于在本地创建一个和远程代码同步的分支,在项目功能迭代的时候很常用,你可以在不同的分支上面提交不同的功能代码,互不影响。 在origin里面找到要同步检出的远程分支,右键检出即可 你可以更改本地分支名,但是建议保持一致方便查找 检出后在分支标签下显示出分支,并切换成当前分支,你也可以双击分支完成切换 提交流程 先说下大致思路 提交流程很简单,大致是这样的,先暂存要提交的文件,提交,拉取分支代码(这里是拉取别人写的代码),有冲突解决冲突(你和别人改了同一个地方了),再提交,最后推送上去即可。简单吧! 暂存代码在为暂存文件里面勾选即可暂存,暂存的意思就是说,我这里面的文件是准备要提交的。 提交 解决冲突解决冲突这个工具处理的不是很好,这边建议用编辑器解决,一目了然。Vs Code解决冲突 回滚提交有些时候,我们提交的代码有问题,需要回滚回去。 将某次变更(在sourcetree里是某个节点)右键选择回滚提交。 总结 提交的流程很清晰,总之记住要先拉取在 推送就是了。 操纵分支切换分支切换分支很简单,在分支标签下双击一个分支即可 ⚡ 需要注意的是,在切换分支之前尽量吧切换前分支代码的提交一下,不然要是代码有冲突的时候会报错 合并分支(合并代码)合并分支相当于在A远程分支上 去merge B远程分支的代码,做到A包含B的效果,大致流程就是,①先在本地切换成A分支,②merge B分支代码,③有冲突的话解决冲突,④提交完成合并。 这里以master分支为例,merge [email protected]分支的代码:首先拉取[email protected]到master 方法一: 拉取过后要是有冲突文件本地需要解决冲突(冲突过多的话建议用编辑器解决冲突) 解决冲突 提交(和正常提交流程一致) 方法二:点合并分支 选合并已抓取,找到需要合并过来的分支,确定即可 合并好后,还可以在本地对比下新增了哪些文件及所做的改动(有冲突解决冲突,推荐用编辑器解决冲突) 后面提交流程同上。 常见问题1.每次用sourceTree拉代码都需要输入密码,如何解决?如图所示: 解决方案一: 在每个git或者gitlab仓库上面拼上gitname@即可,如图: 解决方案二: 在设置的网络里面先删除git分支对应的用户,然后重试即可!]]></content>
<categories>
<category>Tools</category>
</categories>
<tags>
<tag>Tools</tag>
</tags>
</entry>
<entry>
<title><![CDATA[强大的VS Code]]></title>
<url>%2F2018%2F08%2F15%2Ftools%2Fvscode%2F</url>
<content type="text"><![CDATA[简介在 Build 2015 大会上,微软除了发布了 Microsoft Edge 浏览器和新的 Windows 10 系统外,最大的惊喜莫过于宣布推出免费跨平台的 Visual Studio Code 编辑器了! Visual Studio Code (简称 VS Code / VSC) 是一款免费开源的现代化轻量级代码编辑器,支持几乎所有主流的开发语言的语法高亮、智能代码补全、自定义快捷键、括号匹配和颜色区分、代码片段、代码对比 Diff、GIT命令 等特性,支持插件扩展,并针对网页开发和云端应用开发做了优化。软件跨平台支持 Win、Mac 以及 Linux,运行流畅,可谓是微软的良心之作…… 为什么选择VS Code工程开发 作为前端开发的我,之前的开发过程中一直用的是Atom这一款IDE,再配上了好看的主题插件很nice,Atom的界面是真心好看,但是插件装多了你们真的不觉得卡吗,VS Code比Atom更加的流畅,比webstorm更轻量级。一次偶然换的工作后,项目组要求统一IDE,让我了解到了VS Code,这边简单介绍下VS Code日常开发的需求。 VS Code精选主题 主题插件安装流程首先先简单介绍些主题插件的安装流程: 第一步,点击扩展商店搜索你要找的插件名称如Atom One Dark Theme,点击安装; 第二部,安装好了之后只是证明你本地的VS Code上面有这个插件了,还需要将当前使用的主题插件切换成你想要的才行; ①点击右下角的设置按钮,进入命令面板; ②搜索颜色主题关键字; ③点击想要的主题完成切换。 一个编辑器界面的好看与否,真心挺重要的,之前对atom一直恋恋不舍,完全就是因为它的主题界面太优雅了。下图是笔者配置好的VS Code界面截图,下面推荐几款好看的主题: VS Code 主题插件列表(推荐)1. One Dark ProOne Dark Pro的主题界面效果如下(推荐指数5星) One Dark Pro 2. Atom One Dark ThemeAtom One Dark Theme的主题界面效果如下(推荐指数5星) Atom One Dark Theme 3. Eva ThemeEva Theme的主题界面效果如下(推荐指数5星) Eva Theme 4. Material Palenight ThemeMaterial Palenight Theme的主题界面效果如下(推荐指数5星) Material Palenight Theme 更多Visual Studio Code 主题插件请参考VS Code Downloads VS Code精选插件VS Code所有的插件都可以在VS Code Downloads插件库中找到,如下图: Auto Close Tag Auto Close Tag:匹配标签,关闭对应的标签。对于HTML/XML很实用。 Auto Rename Tag Auto Rename Tag:改变标签的时候同时改动开闭合标签;对于HTML/XML很实用。 HTML CSS Support HTML CSS Support : 这个也是HTML必备插件之一。 CSS Peek CSS Peek : html和css中关联css的跳转 Code Runner Code Runner : 代码编译运行看结果,支持众多语言 Git History Git History : 查看git分支提交日志的插件 Git History Diff Git History Diff : 寻找每一个git分支上面提交过的节点,并可以对比差异性。 Path Autocomplete Path Autocomplete : 路径智能补全插件。 Path Intellisense Path Intellisense : 路径智能提示插件。 beautify beautify :良好的拓展性,可以格式化JSON|JS|HTML|CSS|SCSS,比内置格式化好用;但是react工程的jsx文件用beautify插件格式化会乱掉,建议不要用 Prettier - Code formatter Prettier - Code formatter : 代码格式化插件,主要针对工程中的JavaScript / TypeScript / CSS Prettier Now Prettier Now : 支持语言比较全面的代码格式化插件,主要是支持jsx /tsx ,还有sass / less等(问的react工程基本上就是用这2个Prettier插件格式化代码) Terminal Terminal : vs code 内置的命令行插件,也比较实用。 Bookmarks Bookmarks : 这个插件支持在文件特定的行做标记,更好的提高开发效率。 Bracket Pair Colorizer Bracket Pair Colorizer :很多括号的情况下,这个插件可以做一个颜色的区分,代码一目了然。 Chinese (Simplified) Language Pack for Visual Studio Code Chinese (Simplified) Language Pack for Visual Studio Code : 适用于 VS Code 的中文(简体)语言包。 filesize filesize : 编辑器底部显示当前文件的大小。 Markdown Preview Enhanced Markdown Preview Enhanced : 本地Markdown文档预览插件。 vscode-icons vscode-icons : 一套vs code的图标插件。 npm npm : 不多说npm。 open-in-browser open-in-browser : 一键在浏览器中打开 Live Server Live Server :一键开启本地服务。 Local History Local History :个人感觉很有用 本地代码的一个保存日志,在没有git,svn,或者很长时间没有提交过代码的情况下,感觉挺实用,再也不怕代码回滚。 GitLens – Git supercharged GitLens – Git supercharged : GitLens能增强Visual Studio代码中内置的Git功能。它帮助您通过Git blame注解和代码镜头直观地显示代码作者,无缝地导航和探索Git存储库,通过强大的比较命令获得有价值的见解。 VS Code常用快捷键VS Code的快捷键有很多,需要具体的请仔细参考 VS Code => 右下角设置按钮 => 键盘快捷方式 我们也可以自定义快捷键,在keybindings.json里面设置覆盖即可 快捷键完全是个人操作习惯,这里不多介绍,我常用的有这几个: 12345打开命令面板 cmd + shift + p / F1打开设置页面 cmd + ,删除一行 cmd + E(自定义)添加书签 cmd + option + k代码格式化 control + opiton + B VS Code git代码管理实战git现在是很常见的代码管理工具,VS Code 也有内置的git插件,当然,要是你觉得不完美,可以安装一些常用的git插件等,简单介绍下VS Code 下git的提交步骤。 这里我以GitHub上面新建的一个仓库为例,仓库新建后默认分支是master,这里我在GitHub上新建了2个远程分支develop01和develop02,当你在VS Code中点击切换到某一个远程分支的时候,VS Code会自动给你创建一个和当前远程分支对应的本地分支,如origin/develop02 对应develop02,如origin/master 对应master,如上图所示。 现在我们在master分支上面提交代码, 第一步,先暂存要提交的文件 第二步,填下提交日志 第三步,点击对勾按钮完成提交 提交好了之后还需要拉取git远程分支的代码才能推送。 第四步,拉取远程代码,解决冲突 第五步,推送到远程分支上 然后就没有然后了😝,提交完成。 假如你因为工作需求的原因,需要在不同的分支上面提交不同的代码,那就涉及到分支的切换了。首先第一步,切换分支之前先提交代码,不然老是有报错日志,切换了分支后,本地的代码也会对应分支改变。 如上图,master切换成develo01之后,master分支上刚提交的代码成了develo01上对应的代码。 你问我答1.VS Code 怎么更改默认的设置?笔者使用的是mac,使用快捷键 Com + , 打开用户默认设置界面,左边是默认设置,右边是自定义设置,根据个人工作场景而定吧,就像我这边就统一格式化代码缩进4格等,还可以设置忽略一些文件夹等。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849{ "explorer.confirmDelete": false, // 主题 "workbench.iconTheme": "vscode-icons", // 小地图 "editor.minimap.enabled": true, // 主题风格One Dark Pro "workbench.colorTheme": "One Dark Pro", "window.zoomLevel": 1, "extensions.autoUpdate": false, // 字体大小 "editor.fontSize": 13, "editor.snippetSuggestions": "top", "diffEditor.ignoreTrimWhitespace": true, // 设置格式化缩进4格 "prettier.tabWidth": 4, "vetur.format.defaultFormatter.html": "prettier", "gitlens.advanced.messages": { "suppressShowKeyBindingsNotice": true }, "gitlens.historyExplorer.enabled": true, "atomKeymap.promptV3Features": true, "editor.multiCursorModifier": "ctrlCmd", //粘贴自动格式化 "editor.formatOnPaste": false, //保存自动格式化 "editor.formatOnSave": false, // 用来忽略工程打开的文件夹 "files.exclude": { "**/.vscode": true, "**/.DS_Store": true, "**/.history":true, "**/nbproject":true }, // 用来忽略搜索的文件夹 "search.exclude": { "**/node_modules/**": true, "**/bower_components/**": true, "**/image/**": true, "**/*.xml": true, "**/.history/**":true, "**/nbproject/**":true, "**/vscode/**":true }, // 创建和更新代码的头部信息作者 "fileheader.Author": "Baldwin", "fileheader.LastModifiedBy": "Baldwin",} 2.假如我几天没有提交代码了(git),今天突然发现代码youbug,需要还原到昨天版本,VS Code能做到吗?能。参考上面的 VS Code插件 Local History 基本上就介绍到这里(有好的插件或者主题欢迎留言,一定给update上去),希望对你使用VS Code有帮助,有问题欢迎留言,一定积极回复 😑😑😑]]></content>
<categories>
<category>Tools</category>
</categories>
<tags>
<tag>Tools</tag>
</tags>
</entry>
<entry>
<title><![CDATA[js中的声明提前]]></title>
<url>%2F2018%2F04%2F27%2Fjavascript%2Fvar-before%2F</url>
<content type="text"><![CDATA[简介不多说,直接上代码 12345678var num = 100;function fun() { console.log(num); //undefined var num = 10; console.log(num); //10}fun(); 等价于 => 123456789var num = 100;function fun() { var num; console.log(num); //undefined num = 10; console.log(num); //10}fun(); 其实上面2段代码是等价的 var 声明一个变量的时候,会把它提前到改作用域的最前面。 参考 谈谈 JavaScript 中的 声明提前(hoisting)]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ES6处理异步的一些机制]]></title>
<url>%2F2018%2F04%2F19%2Fes6%2Fasync%2F</url>
<content type="text"><![CDATA[简介JavaScript 里面处理异步调用一直是非常恶心的一件事情。以前只能通过回调函数,后来渐渐又演化出来很多方案 参考 ES6 async/await 大概也许是」目前最好的 JavaScript 异步方案 async/await Promise generator函数 ES6–Promise、Generator及async generator函数PromisePromise 用异步的方式写出看上去同步的代码(看上去是同步的代码,实际执行是异步的。) 12345//传统的异步方式出现的问题代码逻辑书写顺序与执行顺序不一致,不利于阅读与维护。异步操作的顺序变更时,需要大规模的代码重构。回调函数基本都是匿名函数,bug 追踪困难。回调函数是被第三方库代码(如上例中的 ajax )而非自己的业务代码所调用的,造成了 IoC 控制反转。 Promise 是一个构造函数, new Promise 返回一个 promise对象 接收一个excutor执行函数作为参数, excutor有两个函数类型形参resolve reject 1234const promise = new Promise((resolve, reject) => { // 异步处理 // 处理结束后、调用resolve 或 reject}); Promise相当于一个状态机有3种状态:pending,fulfilled,rejected promise 对象初始化状态为 pending 当调用resolve(成功),会由pending => fulfilled 当调用reject(失败),会由pending => rejected async/await async 函数就是 Generator 函数的语法糖。 async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。 但是,async函数对 Generator 函数有改进,体现在以下四点: 内置执行器。 更好的语义。 更广的适用性。 co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。 返回值是 Promise。 12345678910//基本用法async function getStockPriceByName(name) { const symbol = await getStockSymbol(name); const stockPrice = await getStockPrice(symbol); return stockPrice;}getStockPriceByName('goog').then(function (result) { console.log(result);});]]></content>
<categories>
<category>ES6</category>
</categories>
<tags>
<tag>ES6</tag>
</tags>
</entry>
<entry>
<title><![CDATA[面试知识点大全(2018)]]></title>
<url>%2F2018%2F04%2F17%2Finterview%2Ffull-knowledge-interview%2F</url>
<content type="text"><![CDATA[简介后面会不断吧内容完善的,实在太多了!呜呜 文档目录Html 部分 HTML5 新特性,语义化 行内元素和块级元素,及区别 浏览器的标准模式和怪异模式 CSS 部分 如何实现水平 居中和垂直居中 解释一下before和after中的双冒号和单冒号的区别 JavaScript 部分 js的基本类型有哪些,引用类型有哪些,null和undefined的区别 防抖和节流 js有哪些内置对象 Object是引用类型嘛,引用类型和基本类型有什么区别,哪个是存在堆哪一个是存在栈上面的 如何判断一个变量是Array类型,如何判断一个变量是Number类型 this有哪些使用场景,跟C,Java中的this有什么区别,如何改变this的值 call,apply,bind 浅拷贝和深拷贝 ES6 部分 计算机网络 部分 浏览器相关 部分工程化 部分模块化 部分框架 部分数据结构 部分性能优化 部分一、HtmlHTML5 新特性,语义化什么是语义化? Web语义化是指使用恰当语义的html标签、class类名等内容,让页面具有良好的结构与含义,从而让人和机器都能快速理解网页内容。简单说就是,用合理、正确的标签来展示内容,比如h1~h6定义标题。 语义化优点? 正确的标签做正确的事情 易于用户阅读,样式丢失的时候能让页面呈现清晰的结构。 页面内容结构化 便于浏览器、搜索引擎解析。 利于爬虫标记、利于SEO,搜索引擎根据标签来确定上下文和各个关键字的权重。 方便其他设备解析,如盲人阅读器根据语义渲染网页。 有利于开发和维护,语义化更具可读性,代码更好维护。 与CSS3关系更和谐。 参考 Html 语义化 快速理解web HTML5的十大新特性 [↑] 回到顶部 行内元素和块级元素,及区别行内元素:inline element span i b em strong small 行内元素不会独占一行,相邻的行内元素会排在同一行。其宽度随内容的变化而变化。 行内元素不可以设置宽高 行内元素水平方向的margin-left; margin-right; padding-left; padding-right;可以生效。但是竖直方向的margin-bottom; margin-top; padding-top; padding-bottom;却不能生效。 display:inline; 可以通过修改display属性来切换块级元素和行内元素 块级元素:block element div p h1-h6 table hr ol ul 块级元素会独占一行,默认情况下宽度自动填满其父元素宽度 块级元素可以设置宽高 块级元素可以设置margin,padding display:block; 可以通过修改display属性来切换块级元素和行内元素 行内块元素:inline-block img input td (1)不自动换行 (2)能够识别宽高 (3)默认排列方式为从左到右 [↑] 回到顶部 浏览器的标准模式和怪异模式现代的浏览器一般都有两种渲染模式:标准模式和怪异模式。在标准模式下,浏览器按照HTML与CSS标准对文档进行解析和渲染;而在怪异模式下,浏览器则按照旧有的非标准的实现方式对文档进行解析和渲染。这样的话,对于旧有的网页,浏览器启动怪异模式,就能够使得旧网页正常显示;对于新的网页,则可以启动标准模式,使得新网页能够使用HTML与CSS的标准特性。 DOCTYPE是”document type”的缩写。它是 HTML 中用来区分标准模式和怪异模式的声明,用来告知浏览器使用标准模式渲染页面。 从中获得的启发:在页面开始处添加<!DOCTYPE html>即可。 参考 https://www.jianshu.com/p/dcab7cde8c04 [↑] 回到顶部 xhtml 和 html 的区别[↑] 回到顶部 使用 data-的好处[↑] 回到顶部 meta 标签[↑] 回到顶部 canvas[↑] 回到顶部 HTML 废弃的标签[↑] 回到顶部 css js 放置位置和原因[↑] 回到顶部 什么是渐进式渲染[↑] 回到顶部 html 模板语言[↑] 回到顶部 meta viewport 原理[↑] 回到顶部 二、CSS盒模型,box-sizing[↑] 回到顶部 CSS3 新特性,伪类,伪元素,锚伪类[↑] 回到顶部 CSS 实现隐藏页面的方式[↑] 回到顶部 如何实现水平 居中和垂直居中水平居中垂直居中1234567891011/* 1.flex */.parent-1 { display: flex; flex-direction: row; justify-content: center; align-items: center;}.child-1 { /* */} 12345678910111213/* 2.margin: auto */.parent-2 { position: relative;}.child-2 { position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto;} 12345678910111213 /* 3.transform */.parent-3 { position: relative;}.child-3 { position: absolute; top: 50%; left: 50%; /* -webkit-transform: translateX(-50%,-50%); */ transform: translate(-50%,-50%); /* animation 位置的变化 */} 1234567891011121314/* 4.宽高的一半 */.parent-4 { position: relative;}.child-4 { position: absolute; top: 50%; left: 50%; /* 高度的一半 */ margin-top: -20px; /* 宽度的一半 */ margin-left: -40px;} 1234567891011/* 5.伪类 */.child-5,.parent-5::after { display: inline-block; vertical-align: middle;}.parent-5::after { content: ''; height: 100%;} [↑] 回到顶部 说说 position,display[↑] 回到顶部 请解释*{box-sizing:border-box;}的作用,并说明使用它的好处[↑] 回到顶部 浮动元素引起的问题和解决办法?绝对定位和相对定位,元素浮动后的 display 值[↑] 回到顶部 link 和@import 引入 css 的区别[↑] 回到顶部 解释一下 css3 的 flexbox,以及适用场景[↑] 回到顶部 inline 和 inline-block 的区别[↑] 回到顶部 哪些是块级元素那些是行级元素,各有什么特点[↑] 回到顶部 grid 布局[↑] 回到顶部 table 布局的作用[↑] 回到顶部 实现两栏布局有哪些方法?[↑] 回到顶部 css dpi[↑] 回到顶部 你知道 attribute 和 property 的区别么[↑] 回到顶部 css 布局问题?css 实现三列布局怎么做?如果中间是自适应又怎么做?[↑] 回到顶部 流式布局如何实现,响应式布局如何实现[↑] 回到顶部 移动端布局方案[↑] 回到顶部 实现三栏布局(圣杯布局,双飞翼布局,flex 布局)[↑] 回到顶部 清除浮动的原理为什么要清除浮动,父元素高度塌陷 解决父元素高度塌陷问题:一个块级元素如果没有设置height,其height是由子元素撑开的。对子元素使用了浮动之后,子元素会脱离标准文档流,也就是说,父级元素中没有内容可以撑开其高度,这样父级元素的height就会被忽略,这就是所谓的高度塌陷。 12345678910/* 经益求精写法 */.clearfix:after { /* content:""; */ content:”\200B”; display:block; height:0; clear:both; } /* 照顾IE6,IE7就可以了 */.clearfix { *zoom:1; } 参考 https://juejin.im/post/5a954add6fb9a06348538c0d [↑] 回到顶部 overflow:hidden 有什么缺点?[↑] 回到顶部 padding 百分比是相对于父级宽度还是自身的宽度[↑] 回到顶部 css3 动画,transition 和 animation 的区别,animation 的属性,加速度,重力的模拟实现[↑] 回到顶部 CSS 3 如何实现旋转图片(transform: rotate)[↑] 回到顶部 sass less[↑] 回到顶部 对移动端开发了解多少?(响应式设计、Zepto;@media、viewport、 JavaScript 正则表达式判断平台。)[↑] 回到顶部 什么是 bfc,如何创建 bfc?解决什么问题?[↑] 回到顶部 CSS 中的长度单位(px,pt,rem,em,ex,vw,vh,vh,vmin,vmax)[↑] 回到顶部 CSS 选择器的优先级是怎样的?[↑] 回到顶部 雪碧图[↑] 回到顶部 svg[↑] 回到顶部 媒体查询的原理是什么?[↑] 回到顶部 CSS 的加载是异步的吗?表现在什么地方?[↑] 回到顶部 常遇到的浏览器兼容性问题有哪些?常用的 hack 的技巧[↑] 回到顶部 外边距合并[↑] 回到顶部 解释一下before和after中的双冒号和单冒号的区别层叠样式表(CSS)的主要目的是给HTML元素添加样式,然而,在一些案例中给文档添加额外的元素是多余的或是不可能的。事实上CSS中有一个特性允许我们添加额外元素而不扰乱文档本身,这就是”伪元素”。 CSS 伪类用于向某些选择器添加特殊的效果。(:hover :active) CSS 伪元素用于将特殊的效果添加到某些选择器。 (::after,::before) 伪类和伪元素的根本区别在于:它们是否创造了新的元素(抽象)。从我们模仿其意义的角度来看,如果需要添加新元素加以标识的,就是伪元素,反之,如果只需要在既有元素上添加类别的,就是伪类。 伪元素和伪类之所以这么容易混淆,是因为他们的效果类似而且写法相仿,但实际上 css3 为了区分两者,已经明确规定了伪类用一个冒号来表示,而伪元素则用两个冒号来表示。 单引号是伪类,逻辑上可以视为filter 双引号是伪元素,逻辑上可以视为child 12:Pseudo-classes::Pseudo-elements 但因为兼容性的问题,所以现在大部分还是统一的单冒号,但是抛开兼容性的问题,我们在书写时应该尽可能养成好习惯,区分两者。 参考 http://www.alloyteam.com/2016/05/summary-of-pseudo-classes-and-pseudo-elements/ [↑] 回到顶部 三、JavaScript js的基本类型有哪些,引用类型有哪些,null和undefined的区别 基本类型有:undefined , null , boolean , srting , number 引用类型有:object , array , function , date , error null是一个表示”无”的对象,转为数值时为0;undefined是一个表示”无”的原始值,转为数值时为NaN。 null表示”没有对象”,即该处不应该有值。undefined表示”缺少值”,就是此处应该有一个值,但是还没有定义。 12345typeof NaN = 'number'typeof null = 'object'//这2个有点难记Number(undefined) = NaN;Number(null) = 0; js中的NaN如何产生的? 怎么区分内存的堆区与栈区。参考 https://juejin.im/post/5acc7e606fb9a028c67609f7 数据结构中的堆和栈是两种不同的、数据项按序排列的数据结构。 基本类型变量:在内存中分别占有固定大小的空间,他们的值保存在栈空间,通过按值访问、拷贝和比较。(变量的拷贝过程就是拷贝了内存中的一个副本???) 引用类型变量:栈内存中存放的只是该对象的访问地址,在堆内存中为该值分配空间,由于这种值的大小不固定,因此不能把他们保存到栈内存中;但内存地址大小是固定的,因此可以将堆内存地址保存到栈内存中。这样,当查询引用类型的变量时,就先从栈中读取堆内存地址,然后再根据该地址取出对应的值。 很显而易见的一点就是,JavaScript 中所有引用类型创建实例时,都是显式或隐式地 new 出对应类型的实例,实际上就是对应 C 语言的 malloc 分配内存函数。 js 中变量的赋值分为「传值」与「传址」。 [↑] 回到顶部 js有哪些内置对象 内置对象就是指javascript这个语言自带的一些对象 Array数组对象 , string字符串 , Math对象 , Date日期对象 123456789101112//数组对象unshift() //数组开头增加shift() //数组开头删除push() //数组末尾添加pop() //数组末尾删除concat() //数组拼接 //concat可以实现数组的克隆()不传值splice(index, howmany, item1, ...itemx) //数组的删除,增加,替换 ???slice(n,m) //数组截取reverse() //数组翻转sort() //数组排序toString() //数组转字符数join() //数组拼接 12345678910//字符串charAt() //通过索引找字符indexOf() //从前向后找,返回索引lastIndexOf() //从后向前找,返回索引slice() //字符串截取substring() // 这里等价于slice()substr(n,m) // 从索引n开始截取m 个split() //字符串分隔成数组toUpperCase() //转成大写toLowerCase() //转成小写 123456789//MathMath.floor() //向下取整Math.ceil() //向上取整Math.random() //取0-1之间的随机小数Math.round() //四舍五入Math.abs() //取绝对值Math.pow(x,y) //x的y次幂Math.sqrt() //开平方Math.max() //取最大值 [↑] 回到顶部 Object是引用类型嘛,引用类型和基本类型有什么区别,哪个是存在堆哪一个是存在栈上面的基本类型 基本类型的值是不可变得 基本类型的比较是值的比较 基本类型的变量是存放在栈内存中的 在从一个变量向另一个变量赋值基本类型时,会在该变量上创建一个新值,然后再把该值复制到为新变量分配的位置上: 引用类型 引用类型的值是可变的 引用类型的值是同时保存在栈内存和堆内存中的对象 引用类型的比较是引用的比较 两个变量都保存了同一个对象地址,则这两个变量指向了同一个对象 1234567var person1 = '{}';var person2 = '{}';console.log(person1 == person2); // truevar person2 = {};var person4 = {};console.log(person3 == person4); // false 参考 https://www.cnblogs.com/focusxxxxy/p/6390536.html [↑] 回到顶部 如何判断一个变量是Array类型,如何判断一个变量是Number类型typeof 检查基本类型ok,引用类型GG 12345678//判断是Array类型let arr = [];arr instanceof Array //truearr.constructor == Array //true// Array.isArray()Array.isArray(arr) //true// 利用对象的toString方法Object.prototype.toString.call([]) === "[object Array]"; // true 后2种较为准确 12345//判断是Number类型let num = 123;typeof num == "number" //truearr.constructor ==Number //trueObject.prototype.toString.call(num) == "[object Number]"; //true 12// isNaNisNaN(123) = false; [↑] 回到顶部 防抖和节流 函数节流是指一定时间内js方法只跑一次。比如人的眨眼睛,就是一定时间内眨一次。这是函数节流最形象的解释。 函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次。比如生活中的坐公交,就是一定时间内,如果有人陆续刷卡上车,司机就不会开车。只有别人没刷卡了,司机才开车。 JS 常见的 dom 操作 api[↑] 回到顶部 解释一下事件冒泡和事件捕获[↑] 回到顶部 事件委托(手写例子),事件冒泡和捕获,如何阻止冒泡?如何组织默认事 件?[↑] 回到顶部 对闭包的理解?什么时候构成闭包?闭包的实现方法?闭包的优缺点?先看一个列子 1234567891011let add=(function(){let now=0;return { doAdd:function(){ now++; console.log(now);}}})();//方法调用add.doAdd(); now 这个变量,并没有随着函数的执行完毕而被回收,而是继续保存在内存里面。 由于 add 里面有函数是依赖于 now 这个变量。所以 now不会被销毁,回收。这就是闭包的用途之一(延续变量周期)。由于 now 在外面访问不到,这就是闭包的另一个用途(创建局部变量,保护局部变量不会被访问和修改)。 《JavaScript权威指南》中的概念 函数对象可以通过作用域链互相关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学中成为闭包 《JavaScript权威指南》中的概念 闭包是指有权访问另一个函数作用域中的变量的函数。 《JavaScript忍者秘籍》中的概念 闭包是一个函数在创建时允许该自身函数访问并操作该自身函数以外的变量时所创建的作用域。 《你不知道的JavaScript》中的概念 闭包是基于词法作用域书写代码时所产生的自然结果。当函数记住并访问所在的词法作用域,闭包就产生了。 闭包就是一个函数,一个可以访问并操作其他函数内部变量的函数。也可以说是一个定义在函数内部的函数。因为JavaScript没有动态作用域,而闭包的本质是静态作用域(静态作用域规则查找一个变量声明时依赖的是源程序中块之间的静态关系),所以函数访问的都是我们定义时候的作用域,也就是词法作用域。所以闭包才会得以实现。 我们常见的闭包形式就是a 函数套 b 函数,然后 a 函数返回 b 函数,这样 b 函数在 a 函数以外的地方执行时,依然能访问 a 函数的作用域。其中”b 函数在 a 函数以外的地方执行时”这一点,才体现了闭包的真正的强大之处。 参考 https://juejin.im/post/5ab4ab126fb9a028d4448365 https://juejin.im/post/5ab4ab126fb9a028d4448365 [↑] 回到顶部 this有哪些使用场景,跟C,Java中的this有什么区别,如何改变this的值JavaScript中的jsthis的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,记住关键的一句话: 哪个对象调用函数,函数里面的this指向哪个对象 12345678//this指向全局对象//作为函数调用function a(){ var user = "追梦子"; console.log(this.user); //undefined console.log(this); //Window}a(); 1234567891011121314151617181920// this指向o对象(o对象调用了函数)// 作为对象调用var o = { user:"追梦子", fn:function(){ console.log(this.user); //追梦子 }}o.fn();// this指向obj对象,obj对象下 无b属性window.b=2222let obj={ a:111, fn:function(){ alert(this.a);//111 alert(this.b);//undefined }}obj.fn(); 1234567891011//this指向o.b对象var o = { a:10, b:{ a:12, fn:function(){ console.log(this.a); //12 } }}o.b.fn(); 123456789101112//作为构造函数调用let TestClass = function() { this.name = '111';}TestClass.prototype.name = '11';let subClass = new TestClass();subClass.name = 'niceboybao';console.log(subClass); //niceboybaolet subClass1 = new TestClass();console.log(subClass1.name) //111 作为构造函数调用,可行了解下js中的new()一个对象具体做了什么一个对象具体做了什么) 1234567891011// apply和call调用let obj1 = { a: 222};let obj2 = { a: 111, fn: function() { console.log(this.a); //222 }}obj2.fn.call(obj1); 此时虽然是 obj2 调用方法,但是使用 了call,动态的把 this 指向到 obj1。相当于这个 obj2.fn 这个执行环境是 obj1 。 当然,apply和call会改变传入函数的this this 有哪些使用场景 作为对象方法调用(参考上面) 作为函数调用 作为构造函数调用 使用 apply 或 call 调用 参考 https://www.cnblogs.com/faith3/p/6209741.html https://juejin.im/post/5ab4ab126fb9a028d4448365 [↑] 回到顶部 call,apply,bindcall和apply 共同点:改变 this 的指向;方法借用 不同点:参数不同而已 call 和 apply 的作用,完全一样,唯一的区别就是在参数上面。call 接收的参数不固定,第一个参数是函数体内 this 的指向,第二个参数以下是依次传入的参数。apply接收两个参数,第一个参数也是函数体内 this 的指向。第二个参数是一个集合对象(数组或者类数组) 123456789//注意如果call和apply的第一个参数写的是null,那么this指向的是window对象var a = { user:"追梦子", fn:function(){ console.log(this); //Window }}var b = a.fn;b.apply(null); bind() bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。 bind()也可以用来改变this的指向,但是有点不同 12345678var a = { user:"追梦子", fn:function(){ console.log(this.user); }}var b = a.fn;b.bind(a); 123456789var a = { user: "追梦子", fn: function() { console.log(this.user); }}var b = a.fn;var c = b.bind(a);console.log(c); //ƒ () {console.log(this.user);} 我们发现代码没有被打印,对,这就是bind和call、apply方法的不同,实际上bind方法返回的是一个修改过后的函数。 [↑] 回到顶部 显示原型和隐式原型,手绘原型链,原型链是什么?为什么要有原型链[↑] 回到顶部 创建对象的多种方式[↑] 回到顶部 实现继承的多种方式和优缺点[↑] 回到顶部 js中的new()一个对象具体做了什么参考 https://www.cnblogs.com/faith3/p/6209741.html [↑] 回到顶部 手写 Ajax,XMLHttpRequest[↑] 回到顶部 变量提升[↑] 回到顶部 举例说明一个匿名函数的典型用例[↑] 回到顶部 指出 JS 的宿主对象和原生对象的区别,为什么扩展 JS 内置对象不是好的做法?有哪些内置对象和内置函数?[↑] 回到顶部 attribute 和 property 的区别[↑] 回到顶部 document load 和 document DOMContentLoaded 两个事件的区别[↑] 回到顶部 === 和 == , [] === [], undefined === undefined,[] == [], undefined== undefined[↑] 回到顶部 typeof 能够得到哪些值[↑] 回到顶部 什么是”use strict”,好处和坏处[↑] 回到顶部 函数的作用域是什么?js 的作用域有几种?[↑] 回到顶部 JS 如何实现重载和多态[↑] 回到顶部 常用的数组 api,字符串 api[↑] 回到顶部 原生事件绑定(跨浏览器),dom0 和 dom2 的区别?[↑] 回到顶部 给定一个元素获取它相对于视图窗口的坐标[↑] 回到顶部 如何实现图片滚动懒加载[↑] 回到顶部 js 的字符串类型有哪些方法? 正则表达式的函数怎么使用?[↑] 回到顶部 浅拷贝和深拷贝浅拷贝浅拷贝只会将对象的各个属性进行依次复制,并不会进行递归复制,也就是说只会赋值目标对象的第一层属性。 对于目标对象第一层为基本数据类型的数据,就是直接赋值,即「传值」; 而对于目标对象第一层为引用数据类型的数据,就是直接赋存于栈内存中的堆内存地址,即「传址」。 深拷贝深拷贝不同于浅拷贝,它不只拷贝目标对象的第一层属性,而是递归拷贝目标对象的所有属性。 参考 js 深浅拷贝知多少 [↑] 回到顶部 编写一个通用的事件监听函数[↑] 回到顶部 web 端 cookie 的设置和获取[↑] 回到顶部 setTimeout 和 promise 的执行顺序[↑] 回到顶部 JavaScript 的事件流模型都有什么?[↑] 回到顶部 navigator 对象,location 和 history[↑] 回到顶部 js 的垃圾回收机制[↑] 回到顶部 内存泄漏的原因和场景[↑] 回到顶部 DOM 事件的绑定的几种方式[↑] 回到顶部 DOM 事件中 target 和 currentTarget 的区别[↑] 回到顶部 typeof 和 instanceof 区别,instanceof 原理[↑] 回到顶部 js 动画和 css3 动画比较[↑] 回到顶部 JavaScript 倒计时(setTimeout)[↑] 回到顶部 js 处理异常[↑] 回到顶部 js 的设计模式知道那些[↑] 回到顶部 轮播图的实现,以及轮播图组件开发,轮播 10000 张图片过程[↑] 回到顶部 websocket 的工作原理和机制。[↑] 回到顶部 手指点击可以触控的屏幕时,是什么事件? 什么是函数柯里化?以及说一下 JS 的 API 有哪些应用到了函数柯里化的实现?(函数柯里化一些了解,以及在 函数式编程的应用,- 最后说了一下 JS 中 bind 函数和数组的 reduce 方法用 到了函数柯里化。)[↑] 回到顶部 JS 代码调试[↑] 回到顶部 四、ES6谈一谈 promise[↑] 回到顶部 所有的 ES6 特性你都知道吗?如果遇到一个东西不知道是 ES6 还是 ES5, 你该怎么区分它[↑] 回到顶部 es6 的继承和 es5 的继承有什么区别[↑] 回到顶部 promise 封装 ajax[↑] 回到顶部 let const 的优点[↑] 回到顶部 es6 generator 是什么,async/await 实现原理[↑] 回到顶部 ES6 和 node 的 commonjs 模块化规范区别[↑] 回到顶部 箭头函数,以及它的 this[↑] 回到顶部 五、计算机网络HTTP 协议头含有哪些重要的部分,HTTP 状态码网络 url 输入到输出怎么做?性能优化为什么要减少 HTTP 访问次数?Http 请求的过程与原理https(对是 https)有几次握手和挥手?https 的原理。http 有几次挥手和握手?TLS 的中文名?TLS 在哪一网络层?TCP 连接的特点,TCP 连接如何保证安全可靠的?为什么 TCP 连接需要三次握手,两次不可以吗,为什么为什么 tcp 要三次握手四次挥手?tcp 的三次握手和四次挥手画图(当场画写 ack 和 seq 的值)?tcp 与 udp 的区别get 和 post 的区别?什么情况下用到?http2 与 http1 的区别?websocket什么是 tcp 流,什么是 http 流babel 是如何将 es6 代码编译成 es5 的http2 的持久连接和管线化域名解析时是 tcp 还是 udp域名发散和域名收敛Post 一个 file 的时候 file 放在哪的?HTTP Response 的 Header 里面都有些啥?六、浏览器相关跨域,为什么 JS 会对跨域做出限制前端安全:xss,csrf…浏览器怎么加载页面的?script 脚本阻塞有什么解决方法?defer 和 async 的 区别?浏览器强缓存和协商缓存浏览器的全局变量有哪些浏览器同一时间能够从一个域名下载多少资源按需加载,不同页面的元素判断标准web 存储、cookies、localstroge 等的使用和区别浏览器的内核如何实现缓存机制?(从 200 缓存,到 cache 到 etag 再到)说一下 200 和 304 的理解和区别什么是预加载、懒加载一个 XMLHttpRequest 实例有多少种状态?dns 解析原理,输入网址后如何查找服务器服务器如何知道你?浏览器渲染过程ie 的某些兼容性问题session拖拽实现拆解 url 的各部分七、工程化对 webpack,gulp,grunt 等有没有了解?对比。webpack 的入口文件怎么配置,多个入口怎么分割。webpack 的 loader 和 plugins 的区别gulp 的具体使用。前端工程化的理解、如何自己实现一个文件打包,比如一个 JS 文件里同时又ES5 和 ES6 写的代码,如何编译兼容他们八、模块化对 AMD,CMD,CommonJS 有没有了解?为什么要模块化?不用的时候和用 RequireJs 的时候代码大概怎么写?说说有哪些模块化的库,有了解过模块化的发展的历史吗?分别说说同步和异步模块化的应用场景,说下 AMD 异步模块化实现的原理?如何将项目里面的所有的 require 的模块语法换成 import 的 ES6 的语法?使用模块化加载时,模块加载的顺序是怎样的,如果不知道,根据已有的知识,你觉得顺序应该是怎么样的?九、框架使用过哪些框架?zepto 和 jquery 是什么关系,有什么联系么?jquery 源码如何实现选择器的,为什么$取得的对象要设计成数组的形式,这样设计的目的是什么jquery 如何绑定事件,有几种类型和区别什么是 MVVM,MVC,MVPVue 和 Angular 的双向数据绑定原理Vue,Angular 组件间通信以及路由原理react 和 vue 的生命周期react 和 vue 的虚拟 dom 以及 diff 算法vue 的 observer,watcher,compilereact 和 angular 分别用在什么样的业务吗?性能方面和 MVC 层面上的区别jQuery 对象和 JS 的 Element 有什么区别jQuery 对象是怎么实现的jQuery 除了它封装了一些方法外,还有什么值得我们去学习和使用的?jQuery 的$(‘xxx’)做了什么事情介绍一下 bootstrap 的栅格系统是如何实现的十、数据结构基本数据结构:(数组、队列、链表、堆、二叉树、哈希表等等)8种排序算法,原理,以及适用场景和复杂度说出越多越好的斐波那契数列的实现方法?十一、性能优化cdn 的用法是什么?什么时候用到?浏览器的页面优化?如何优化 DOM 操作的性能单页面应用有什么 SEO 方案?单页面应用首屏显示比较慢,原因是什么?有什么解决方案?]]></content>
<categories>
<category>Interview</category>
</categories>
<tags>
<tag>Interview</tag>
</tags>
</entry>
<entry>
<title><![CDATA[react中遇到的一些问题的解答]]></title>
<url>%2F2018%2F04%2F11%2Freact%2Fquestions%2F</url>
<content type="text"><![CDATA[简介Question1 为什么请求数据要在钩子函数componentDidMount里面调用?这与React组件的生命周期有关,组件挂载时有关的生命周期有以下几个: constructor() componentWillMount() render() componentDidMount() 上面这些方法的调用是有次序的,由上而下,也就是当说如果你要获取外部数据并加载到组件上,只能在组件”已经”挂载到真实的网页上才能作这事情,其它情况你是加载不到组件的。 componentDidMount方法中的代码,是在组件已经完全挂载到网页上才会调用被执行,所以可以保证数据的加载。此外,在这方法中调用setState方法,会触发重渲染。所以,官方设计这个方法就是用来加载外部数据用的,或处理其他的副作用代码。 constructor被调用是在组件准备要挂载的最一开始,所以此时组件尚未挂载到网页上。 componentWillMount方法的调用在constructor之后,在render之前,在这方法里的代码调用setState方法不会触发重渲染,所以它一般不会用来作加载数据之用,它也很少被使用到。 一般的从后台(服务器)获取的数据,都会与组件上要用的数据加载有关,所以都在componentDidMount方法里面作。虽然与组件上的数据无关的加载,也可以在constructor里作,但constructor是作组件state初绐化工作,并不是设计来作加载数据这工作的,所以所有有副作用的代码都会集中在componentDidMount方法里。 Question2 在componentWillMount()钩子函数里面 setState 为啥不会再次触发render()?setState会有一个批量处理的操作 Question3 子组件和父组件componentDidMount哪一个先执行 子组件先执行 父组件的componentDidMount方法会在其render的全部内容装载到DOM后执行,若父组件中包含定义的子组件,则componentDidMount方法会在子组件执行完实例化周期后再执行 所有平行子组件首次render后,再依次执行componentDidMount]]></content>
<categories>
<category>React</category>
</categories>
<tags>
<tag>React</tag>
</tags>
</entry>
<entry>
<title><![CDATA[TSX回调中必须注意的 this 指向]]></title>
<url>%2F2018%2F04%2F10%2Freact%2Fjsx-class-this%2F</url>
<content type="text"><![CDATA[简介class关键字基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。上面的代码用 ES6 的class改写,就是下面这样。 123456789101112131415161718192021222324class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; // 这个绑定是必要的,使`this`在回调中起作用 this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(prevState => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'ON' : 'OFF'} </button> ); }}]]></content>
<categories>
<category>React</category>
</categories>
<tags>
<tag>React</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Airbnb React/JSX 编码规范]]></title>
<url>%2F2018%2F04%2F10%2Freact%2Freact-jsx-style-guide%2F</url>
<content type="text"><![CDATA[简介 参考 Airbnb React/JSX Style Guide 算是最合理的React/JSX编码规范之一了。 Create创建模块如果你的模块有内部状态或者是refs, 推荐使用 class extends React.Component 而不是 React.createClass。 123456789101112131415// badconst Listing = React.createClass({ // ... render() { return <div>{this.state.hello}</div>; }});// goodclass Listing extends React.Component { // ... render() { return <div>{this.state.hello}</div>; }} 如果你的模块没有状态或是没有引用refs, 推荐使用普通函数(非箭头函数)而不是类: 12345678910111213141516// badclass Listing extends React.Component { render() { return <div>{this.props.hello}</div>; }}// bad (relying on function name inference is discouraged)const Listing = ({ hello }) => ( <div>{hello}</div>);// goodfunction Listing({ hello }) { return <div>{hello}</div>;} Naming 命名 文件名: 文件名使用帕斯卡命名. 如, ReservationCard.jsx. 引用命名: React模块名使用帕斯卡命名,实例使用骆驼式命名. 1234567891011// badimport reservationCard from './ReservationCard';// goodimport ReservationCard from './ReservationCard';// badconst ReservationItem = <ReservationCard />;// goodconst reservationItem = <ReservationCard />; 模块命名: 模块使用当前文件名一样的名称. 比如 ReservationCard.jsx 应该包含名为 ReservationCard的模块. 但是,如果整个文件夹是一个模块,使用 index.js作为入口文件,然后直接使用 index.js 或者文件夹名作为模块的名称: 12345678// badimport Footer from './Footer/Footer';// badimport Footer from './Footer/index';// goodimport Footer from './Footer'; 属性命名: 避免使用DOM相关的属性来用作其他的用途。 12345// bad<MyComponent style="fancy" />// good<MyComponent variant="fancy" /> Alignment 代码对齐1234567891011121314151617181920// bad<Foo superLongParam="bar" anotherSuperLongParam="baz" />// good, 有多行属性的话, 新建一行关闭标签<Foo superLongParam="bar" anotherSuperLongParam="baz"/>// 若能在一行中显示, 直接写成一行<Foo bar="bar" />// 子元素按照常规方式缩进<Foo superLongParam="bar" anotherSuperLongParam="baz"> <Quux /></Foo> Quotes 单引号还是双引号 对于JSX属性值总是使用双引号(“), 其他均使用单引号(‘). 为什么? HTML属性也是用双引号, 因此JSX的属性也遵循此约定. 1234567891011// bad<Foo bar='bar' />// good<Foo bar="bar" />// bad<Foo style={{ left: "20px" }} />// good<Foo style={{ left: '20px' }} /> Props 属性 JSX属性名使用骆驼式风格camelCase. 123456789// bad<foo username="hello" phone_number="{12345678}"></foo>// good<foo username="hello" phonenumber="{12345678}"></foo> 如果属性值为 true, 可以直接省略. 12345678910111213// bad<Foo hidden={true}/>// good<Foo hidden/>// good<Foo hidden /> 避免使用数组的index来作为属性key的值,推荐使用唯一ID. 12345678910111213141516// bad{todos.map((todo, index) => <Todo {...todo} key={index} />)}// good{todos.map(todo => ( <Todo {...todo} key={todo.id} />))} 对于所有非必须的属性,总是手动去定义defaultProps属性. 1234567891011121314151617181920212223// badfunction SFC({ foo, bar, children }) { return <div>{foo}{bar}{children}</div>;}SFC.propTypes = { foo: PropTypes.number.isRequired, bar: PropTypes.string, children: PropTypes.node,};// goodfunction SFC({ foo, bar, children }) { return <div>{foo}{bar}{children}</div>;}SFC.propTypes = { foo: PropTypes.number.isRequired, bar: PropTypes.string, children: PropTypes.node,};SFC.defaultProps = { bar: '', children: null,}; 特别提醒:尽可能地筛选出不必要的属性。 1234567891011//goodrender() { const { irrelevantProp, ...relevantProps } = this.props; return <WrappedComponent {...relevantProps} />}//badrender() { const { irrelevantProp, ...relevantProps } = this.props; return <WrappedComponent {...this.props} />} Refs 总是在Refs里使用回调函数 123456789// bad<Foo ref="myRef"/>// good ???<Foo ref={(ref) => { this.myRef = ref; }}/> Parentheses 括号 将多行的JSX标签写在 ()里 123456789101112131415161718192021// badrender() { return <MyComponent className="long body" foo="bar"> <MyChild /> </MyComponent>;}// goodrender() { return ( <MyComponent className="long body" foo="bar"> <MyChild /> </MyComponent> );}// good, 单行可以不需要render() { const body = <div>hello</div>; return <MyComponent>{body}</MyComponent>;} Methods 函数 当在 render() 里使用事件处理方法时,提前在构造函数里把 this 绑定上去 为什么? 在每次 render 过程中, 再调用 bind 都会新建一个新的函数,浪费资源. 123456789101112131415161718192021222324252627// badclass extends React.Component { onClickDiv() { // do stuff } render() { return <div onClick={this.onClickDiv.bind(this)} />; }}// goodclass extends React.Component { constructor(props) { super(props); this.onClickDiv = this.onClickDiv.bind(this); } onClickDiv() { // do stuff } render() { return <div onClick={this.onClickDiv} />; }} 在 render 方法中总是确保 return 返回值 123456789// badrender() { (<div />);}// goodrender() { return (<div />);} Object 定义对象的细节逗号问题 单行定义的对象结尾不要逗号: 12345// badconst a = { k1: v1, k2: v2, };// goodconst a = { k1: v1, k2: v2 }; 多行定义的对象要保留逗号: 1234567891011// badconst b = { k1: v1, k2: v2};// goodconst b = { k1: v1, k2: v2,}; 一次性初始化完全 不要声明之后又给对象添加新属性: 1234567// badconst a = {};a.x = 3;// goodconst a = { x: null };a.x = 3; 如果一定非要加请使用Object.assign: 12const a = {};Object.assign(a, { x: 3 });]]></content>
<categories>
<category>React</category>
</categories>
<tags>
<tag>React</tag>
</tags>
</entry>
<entry>
<title><![CDATA[react技术栈整理]]></title>
<url>%2F2018%2F04%2F09%2Freact%2Freact-stack-url%2F</url>
<content type="text"><![CDATA[简介使用react开发需要掌握一套完整的react技术栈,下面简单归纳下,后续会不断更新! 单列技术点总结篇 一个 react + redux 的完整项目 和 个人总结(react的生命周期) https://github.com/bailicangdu/react-pxq 现代 Web 开发–React 篇 https://github.com/wxyyxc1992/Web-Series/tree/master/React React.js 初学者应该知道的9件事 http://www.iteye.com/news/31748]]></content>
<categories>
<category>React</category>
</categories>
<tags>
<tag>React</tag>
</tags>
</entry>
<entry>
<title><![CDATA[文档写作注意点]]></title>
<url>%2F2018%2F04%2F09%2FREADME%2F</url>
<content type="text"><![CDATA[README启动项目1hexo clean && hexo g && hexo s 项目打包部署(Github)1hexo clean && hexo g && hexo d 线上预览发布完成输入niceboybao.github.io 或者 https://blogs.niceboybao.com/ 即可以访问。 文章更新注意事项 文件夹及文件路径 不要乱更改,更改会重置文档阅读量; date熟悉的更改也会重置文档阅读量,update和title不会; 技术标签 和 分类标签 尽量统一,且字母开头大写;]]></content>
<categories>
<category>README</category>
</categories>
<tags>
<tag>README</tag>
</tags>
</entry>
<entry>
<title><![CDATA[react的diff算法]]></title>
<url>%2F2018%2F04%2F09%2Freact%2Fdiff%2F</url>
<content type="text"><![CDATA[简介参考 https://segmentfault.com/a/1190000000606216]]></content>
<categories>
<category>React</category>
</categories>
<tags>
<tag>React</tag>
</tags>
</entry>
<entry>
<title><![CDATA[操作数组的一些方法]]></title>
<url>%2F2018%2F04%2F08%2Fjavascript%2Fhandle-array%2F</url>
<content type="text"><![CDATA[简介在实际的项目开发过程中,基于对象或者数组而开发是特别常见的,所以整理了下能操作数组的一些js方法。(包括ES6的) reduce()定义Array.prototype.reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。reduce() 可以作为一个高阶函数,用于函数的 compose。 语法 array.reduce(function(total, currentValue, currentIndex, arr), initialValue) 12345total: 必需。初始值, 或者计算结束后的返回值。currentValue: 必需。当前元素currentIndex: 可选。当前元素的索引arr: 可选。当前元素所属的数组对象。initialValue: 可选。传递给函数的初始值 实例计算所有count值的总和12345//数组求和var sum = [0, 1, 2, 3].reduce((total, item)=> { return total + item;}, 0);// sum is 6 12345678910111213//二维数组变成一维数组var flattened = [[0, 1], [2, 3], [4, 5]].reduce((total, item) => { return total.concat(item);}, []);//orvar flattened = [[0, 1], [2, 3], [4, 5]].reduce((total, item) => { return [...total, ...item];}, []);// flattened is [0, 1, 2, 3, 4, 5] 1234567891011121314//计算数组中每个元素出现的次数var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];var countedNames = names.reduce(function (allNames, name) { if (name in allNames) { allNames[name]++; } else { allNames[name] = 1; } return allNames;}, {});// countedNames is:// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 } Object.keys()定义Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for…in 循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in 循环还会枚举其原型链上的属性)。 语法 Object.keys(obj) 1234567891011// simple arrayvar arr = ['a', 'b', 'c'];console.log(Object.keys(arr)); // console: ['0', '1', '2']// array like objectvar obj = { 0: 'a', 1: 'b', 2: 'c' };console.log(Object.keys(obj)); // console: ['0', '1', '2']// array like object with random key orderingvar anObj = { 100: 'a', 2: 'b', 7: 'c' };console.log(Object.keys(anObj)); // console: ['2', '7', '100'] 实例ES6 (for in) (for of) (forEach)for in for…in语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行。 语法 for (variable in object) {…} 提示:for…in不应该用于迭代一个 Array,其中索引顺序很重要。 实例12345678910var obj = {a:1, b:2, c:3};for (var prop in obj) { console.log("obj." + prop + " = " + obj[prop]);}// Output:// "obj.a = 1"// "obj.b = 2"// "obj.c = 3" 123for (let index in arr) { console.log("for in:" + arr[index]);} 1.index索引为字符串型数字,不能直接进行几何运算(for in遍历的是数组的索引(即键名),而for of遍历的是数组元素值。) 2.遍历顺序有可能不是按照实际数组的内部顺序 3.使用for in会遍历数组所有的可枚举属性,包括原型。例如上栗的原型方法method和name属性.所以for in更适合遍历对象,不要使用for in遍历数组。 for of for…of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。 12345678910//迭代 arraylet iterable = [10, 20, 30];for (let value of iterable) { value += 1; console.log(value);}// 11// 21// 31 123456789//迭代 stringlet iterable = "boo";for (let value of iterable) { console.log(value);}// "b"// "o"// "o" forEach Array.prototype.forEach()性能方面都很好,只能遍历数组,不可遍历字符串等!不能使用break,return等 12345678const arr = ['a', 'b', 'c'];arr.forEach(function (element, index, array) { // element: 指向当前元素的值 // index: 指向当前索引 // array: 指向Array对象本身 console.log(element + ',' + index + ',' + typeof (array));}); Map/Set Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。 Set对象是值的集合,你可以按照插入的顺序迭代它的元素。 Set中的元素只会出现一次,即 Set 中的元素是唯一的。 123//所以可以用Set做数组去重[...new Set([1,1,2,2,3,3])] // [1,2,3] Array.from(new Set([1,1,2,2,3,3])) // [1,2,3] find()/findIndex() find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。 123456let arr = [1, 2, 3, 4];//find方法的回调函数可以接受4个参数,依次为当前的值、当前的位置和原数组,thisValuelet find = arr.find((item, index, arrs) => { return item === 3;});找不到返回undefined findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。 12345//findIndex方法的回调函数可以接受4个参数,依次为当前的值、当前的位置和原数组,thisValuelet arr = [1, 2, 3, 4];let findIndex = arr.findIndex((item, index, arrs) => { return item === 3;}) map()Array.prototype.map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。 语法 array.map(function(currentValue,index,arr), thisValue) 12345currentValue: 必须。当前元素的值currentValue: 可选。当期元素的索引值currentValue: 可选。当期元素属于的数组对象currentValue: 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值。如果省略了 thisValue ,"this" 的值为 "undefined" 实例jsx语法中,遍历循环的话使用map的情况特别多。 123456//普通用法let arr = [1, 2, 3, 4, 5];let mapArr = arr.map((item, index) => { return item * item;});//[1,3,9,16,25] 123//数组的数字转化为字符串[1, 2, 3, 4, 5, 6, 7, 8, 9].map(String);//["1", "2", "3", "4", "5", "6", "7", "8", "9"] .forEach和.map()的主要区别在于.map()返回一个新的数组。如果你想得到一个结果,但不想改变原始数组,用.map()。如果你只需要在数组上做迭代修改,用forEach。 数组拼接的一些方法concat()定义concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。 语法 arrayObject.concat(arrayX,arrayX,……,arrayX) 1arrayX: 必需。该参数可以是具体的值,也可以是数组对象。可以是任意多个。 实例12const a = [1,2,3];let b = a.concat(4,5); //[1,2,3,4,5] join()定义 join() 方法用于把数组中的所有元素转换一个字符串。 语法1array.join(separator)//指定要使用的分隔符 […] es6 扩展运算符 123const arr1 = [1,2,3];const arr2 = [4,5];const arr3 = [...arr1, ...arr2]; 数组截取的一些方法splice() splice() 方法通过删除现有元素和/或添加新元素来更改一个数组的内容。 语法12345array.splice(start)array.splice(start, deleteCount)array.splice(start, deleteCount, item1, item2, ...) start: 指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容. deleteCount?: 整数,表示要移除的数组元素的个数。如果 deleteCount 是 0,则不移除元素。 item1, item2, … 要添加进数组的元素,从start 位置开始。 12345var myFish = ["angel", "clown", "mandarin", "surgeon"];//从第 2 位开始删除 0 个元素,插入 "drum"var removed = myFish.splice(2, 0, "drum");//运算后的 myFish:["angel", "clown", "drum", "mandarin", "surgeon"]//被删除元素数组:[],没有元素被删除 slice() slice(start,end),返回选定元素 从某个已有的数组返回选定的元素,从start位开始返回到end(包括start不包括end)如果是负数,表示从数组尾部进行计算 123let arr = [1, 2, 3, 4];arr.slice(1, 3); //[2,3]// 不会改变原数组 fill() 方法定义Array.prototype.fill()方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。 语法 array.fill(value, start, end) 123value: 必需。填充的值。start: 可选。开始填充位置。(下标从1开始)end: 可选。停止填充位置 (默认为 array.length) 实例12var fruits = ["Banana", "Orange", "Apple", "Mango"];fruits.fill("Runoob", 2, 4); //Banana,Orange,Runoob,Runoob 12new Array(5).fill(0); //[0, 0, 0, 0, 0]new Array(5).fill(false); // [false, false, false, false, false] 改变原数组的一些方法1234567shift: //将第一个元素删除并且返回删除元素,空即为undefinedunshift: //向数组开头添加元素,并返回新的长度pop: //删除最后一个并返回删除的元素push: //向数组末尾添加元素,并返回新的长度reverse: //颠倒数组顺序sort: //对数组排序splice:splice(start,length,item) //删,增,替换数组元素,返回被删除数组,无删除则不返回]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[做了一年的react自己的感悟和总结]]></title>
<url>%2F2018%2F04%2F04%2Freact%2Freact-think%2F</url>
<content type="text"><![CDATA[简介react确实是一个神奇而优雅的框架。在从事react项目之前,一直是在做angular的,angular是一个全面和庞大的框架,在起初设计的时候什么都有,复杂程度也很高,所以用angular做项目基本上不需要其他的辅助库来配合。但是react项目真的是不一样了,要是只会一个react的话,很难开发出需求的。因为react就只负责UI的渲染。 这里是我开发react工程的一个模板,平时开发过程中遇到的需求上面都有对应的实例,技术栈:react + react-router + react-redux + saga + reselector + webpack + ES6 + Typescript + sass。点击这里访问 做react项目需要掌握什么 react 功能单一用于UI渲染,redux 用来管理数据,react-router 用来管理路由,webpack 用来配置工程,ES6 让代码更加优雅,redux-saga 用来处理异步请求,reselect 缓存机制用来减少state改变带来的渲染压力,还有一些为了交互衍生出来的中间件 react-redux、react-router-redux、react-router-dom ,预处理器Sass或Less 尽量也掌握下。 react 前面有说过react只负责ui的渲染 从V-dom出发react最难能可贵的就是虚拟dom的思想,这里有个贴切的比喻:把dom和JavaScript想象为各自的2个岛屿,中间有桥梁相连,但是桥上设有收费站,JavaScript去访问dom岛屿的次数越多,费用就越高。这就是一个js操作dom的过程,也许我们经常听到或者看到说尽量少的去操作dom,很耗性能。但是DOM 操作成本到底高在哪儿?,这边小总结下: 从输入uri到页面加载好是一个很漫长的过程,我们就从html的解析开始说起。①解析HTML,开始构建DOM树;②解析CSS,生成CSS规则树;③合并DOM树和CSS规则树,生成render树;④布局render树(Layout/reflow),这时候负责元素尺寸大小,位置的计算,属于js中回流过程;⑤绘制render树(paint),绘制页面像素,属于重绘的过程;⑥浏览器会将各层的信息发送给GPU(图像处理器),GPU将各层合成(composite),显示在屏幕上。这是初始化渲染的过程,通过js操作DOM后,会引起 回流 和重绘,回流的成本很高,一个节点的回流会导致兄弟节点和子节点的回流,这样就一直在消耗GPU资源,所以才有了成本高的说法。 我们从操作dom的成本开始引入react,它创造了虚拟dom并且将它们储存起来,每当状态发生变化的时候就会创造新的虚拟节点和以前的进行对比,让变化的部分进行渲染。整个过程没有对dom进行获取和操作,只有等真正render时,才会去操作真实dom,从而引发页面的渲染。 V-dom的缺点ReactJS 使用虚拟 DOM 机制,让前端开发者为每个组件提供一个 render 函数。render 函数把 props 和 state 转换成 ReactJS 的虚拟 DOM,然后 ReactJS 框架根据render 返回的虚拟 DOM 创建相同结构的真实 DOM。 每当 state 更改时,ReactJS 框架重新调用 render 函数,获取新的虚拟 DOM 。然后,框架会比较上次生成的虚拟 DOM 和新的虚拟 DOM 有哪些差异,进而把差异应用到真实 DOM 上。 这样做有两大缺点: 12345//每次 state 更改,render 函数都要生成完整的虚拟 DOM,哪怕 state 改动很小,//render函数也会完整计算一遍。如果 render 函数很复杂,这个过程就会白白浪费很多计算资源。//ReactJS 框架比较虚拟 DOM 差异的过程,既慢又容易出错。比如,你想要在某个 <ul> 列表的顶部插入一项 <li> ,//那么 ReactJS 框架会误以为你修改了 <ul> 的每一项 <li>,然后在尾部插入了一个 <li>。 这是因为 ReactJS 收到的新旧两个虚拟 DOM 之间相互独立,ReactJS 并不知道数据源发生了什么操作,只能根据新旧两个虚拟 DOM 来猜测需要执行的操作。自动的猜测算法既不准又慢,必须要前端开发者手动提供 key 属性、shouldComponentUpdate 方法、componentDidUpdate 方法或者 componentWillUpdate 等方法才能帮助 ReactJS 框架猜对。 diff算法react的diff算法用在什么地方呢?当组件更新的时候,react会创建一个新的虚拟dom树并且会和之前储存的dom树进行比较,这个比较的过程就用到了diff算法,所以组件初始化的时候是用不到的。react提出了一种假设,相同的节点具有类似的结构,而不同的节点具有不同的结构。在这种假设之上进行逐层的比较,如果发现对应的节点是不同的,那就直接删除旧的节点以及它所包含的所有子节点然后替换成新的节点。如果是相同的节点,则只进行属性的更改。 对于列表的diff算法稍有不同,因为列表通常具有相同的结构,在对列表节点进行删除,插入,排序的时候,单个节点的整体操作远比一个个对比一个个替换要好得多,所以在创建列表的时候需要设置key值,这样react才能分清谁是谁。当然不写key值也可以,但这样通常会报出警告,通知我们加上key值以提高react的性能。 需要深入了解diff源码的请参考源码解析! 单项数据流 组件化组件就是拥有独立功能的视图模块,React的最大好处在于:功能组件化,遵守前端可维护的原则。 组件生命周期 组件初始化会触发的5个钩子函数1.getDefaultProps() 设置默认的props,也可以用defaultProps设置组件的默认属性。 getDefaultProps相当于ES6中的 static defaultProps = {} 2.getInitialState() 在使用es6的class语法时是没有这个钩子函数的,可以直接在constructor中定义this.state。此时可以访问this.props。 getInitialState相当于ES6 class中constructor的 this.state = {} 钩子函数1 2 只有用React.createClass方法创造的组件类才会发生作用,并且React.createClass已经被Fb官方废弃,所以这里不细讲了。 3.componentWillMount() 组件初始化时只调用,以后组件更新不调用,整个生命周期只调用一次,此时可以修改state。 4.render() react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行。 render() 应该是一个纯函数,完全根据state和props来决定返回结果,而不产生副作用,所以render中调用setState是错的,因为纯函数不应该引起状态的改变 5.componentDidMount() 组件渲染之后调用,可以通过this.getDOMNode()获取和操作dom节点,只调用一次。 did的前缀表示进入状态之后调用,比如componentDidMount,组件一般初始化都会在这里进行数据请求。 为什么请求数据要在这个钩子函数里面调用? 我的总结详见react中遇到的一些问题的解答 组件交互更新时触发的5个钩子函数6.componentWillReceiveProps(nextProps) 组件初始化时不调用,组件接受新的props时调用。 开发过程中一般是在这个钩子函数里面改变state,此方法中改变state不会二次渲染而是进行state合并。 7.shouldComponentUpdate(nextProps, nextState) react性能优化非常重要的一环。组件接受新的state或者props时调用,我们可以设置在此对比前后两个props和state是否相同,如果相同则返回false阻止更新,因为相同的属性状态一定会生成相同的dom树,这样就不需要创造新的dom树和旧的dom树进行diff算法对比,节省大量性能,尤其是在dom结构复杂的时候。不过调用this.forceUpdate会跳过此步骤。 8.componentWillUpdate(nextProps, nextState) 组件初始化时不调用,只有在组件将要更新时才调用。 千万不要在这个函数中调用this.setState()方法,会造成循环调用。 9.render() 同上render(),创建虚拟dom,进行diff算法,更新dom树都在此进行。 10.componentDidUpdate() 组件初始化时不调用,组件更新完成后调用,此时可以获取dom节点。 在componentDidUpdate后才能获取更新后的this.state。如果想获取组件默认的props,并且赋值给State ,就可以在这里修改,达到UI上的效果。 组件卸载时调用10.componentWillUnmount() 组件将要卸载时调用,一些事件监听和定时器需要在此时清除,还有此组件store上面的值也可以对应的清楚。 componentWillUnmount执行重置所有相关参数。在该方法中调用setState不会触发render,因为所有的更新队列,更新状态都被重置为null。 123456789//数据清楚需要写在reducer里面this.props.clearPointData();[CLEAR_POINT_DATA]: (state, action: Action<any>) => { return Object.assign({}, state, { selectedReadingList: {}, knowledgePoint: {}, });} 以上可以看出来react总共有10个周期函数(render重复一次),这个10个函数可以满足我们所有对组件操作的需求,利用的好可以提高开发效率和组件性能。 react-router Router就是React的一个组件,它并不会被渲染,只是一个创建内部路由规则的配置对象,根据匹配的路由地址展现相应的组件。Route则对路由地址和组件进行绑定,Route具有嵌套功能,表示路由地址的包涵关系,这和组件之间的嵌套并没有直接联系。Route可以向绑定的组件传递7个属性:children,history,location,params,route,routeParams,routes,每个属性都包涵路由的相关的信息。比较常用的有children(以路由的包涵关系为区分的组件),location(包括地址,参数,地址切换方式,key值,hash值)。react-router提供Link标签,这只是对a标签的封装,值得注意的是,点击链接进行的跳转并不是默认的方式,react-router阻止了a标签的默认行为并用pushState进行hash值的转变。切换页面的过程是在点击Link标签或者后退前进按钮时,会先发生url地址的转变,Router监听到地址的改变根据Route的path属性匹配到对应的组件,将state值改成对应的组件并调用setState触发render函数重新渲染dom。 当页面比较多时,项目就会变得越来越大,尤其对于单页面应用来说,初次渲染的速度就会很慢,这时候就需要按需加载,只有切换到页面的时候才去加载对应的js文件。react配合webpack进行按需加载的方法很简单,Route的component改为getComponent,组件用require.ensure的方式获取,并在webpack中配置chunkFilename。 1234567891011121314151617181920212223242526272829const chooseProducts = (location, cb) => { require.ensure([], require => { cb(null, require('../Component/chooseProducts').default) },'chooseProducts')}const helpCenter = (location, cb) => { require.ensure([], require => { cb(null, require('../Component/helpCenter').default) },'helpCenter')}const saleRecord = (location, cb) => { require.ensure([], require => { cb(null, require('../Component/saleRecord').default) },'saleRecord')}const RouteConfig = ( <Router history={history}> <Route path="/" component={Roots}> <IndexRoute component={index} />//首页 <Route path="index" component={index} /> <Route path="helpCenter" getComponent={helpCenter} />//帮助中心 <Route path="saleRecord" getComponent={saleRecord} />//销售记录 <Redirect from='*' to='/' /> </Route> </Router>); react-router-redux保持路由与应用状态(state)同步。使用redux管理应用状态(state),使用router管理路由,两个库不能协同工作,react-router-redux库可以协调这两个库。 react-router-dom… redux 组件间的通信react推崇的是单向数据流,自上而下进行数据的传递,但是由下而上或者不在一条数据流上的组件之间的通信就会变的复杂。解决通信问题的方法很多,如果只是父子级关系,父级可以将一个回调函数当作属性传递给子级,子级可以直接调用函数从而和父级通信。 组件层级嵌套到比较深,可以使用上下文getChildContext来传递信息,这样在不需要将函数一层层往下传,任何一层的子级都可以通过this.context直接访问。 兄弟关系的组件之间无法直接通信,它们只能利用同一层的上级作为中转站。而如果兄弟组件都是最高层的组件,为了能够让它们进行通信,必须在它们外层再套一层组件,这个外层的组件起着保存数据,传递信息的作用,这其实就是redux所做的事情。 组件之间的信息还可以通过全局事件来传递。不同页面可以通过参数传递数据,下个页面可以用location.param来获取。其实react本身很简单,难的在于如何优雅高效的实现组件之间数据的交流。 redux首先,redux并不是必须的,它的作用相当于在顶层组件之上又加了一个组件,作用是进行逻辑运算、储存数据和实现组件尤其是顶层组件的通信。如果组件之间的交流不多,逻辑不复杂,只是单纯的进行视图的渲染,这时候用回调,context就行,没必要用redux,用了反而影响开发速度。但是如果组件交流特别频繁,逻辑很复杂,那redux的优势就特别明显了。我第一次做react项目的时候并没有用redux,所有的逻辑都是在组件内部实现,当时为了实现一个逻辑比较复杂的购物车,洋洋洒洒居然写了800多行代码,回头一看我自己都不知道写的是啥,画面太感人。 先简单说一下redux和react是怎么配合的。react-redux提供了connect和Provider两个好基友,它们一个将组件与redux关联起来,一个将store传给组件。组件通过dispatch发出action,store根据action的type属性调用对应的reducer并传入state和这个action,reducer对state进行处理并返回一个新的state放入store,connect监听到store发生变化,调用setState更新组件,此时组件的props也就跟着变化。 流程是这个样子的: 值得注意的是connect,Provider,mapStateToProps,mapDispatchToProps是react-redux提供的,redux本身和react没有半毛钱关系,它只是数据处理中心,没有和react产生任何耦合,是react-redux让它们联系在一起。 接下来具体分析一下,redux以及react-redux到底是怎么实现的。 先上一张图 明显比第一张要复杂,其实两张图说的是同一件事。从上而下慢慢分析: 先说说redux: redux主要由三部分组成:store,reducer,action。 store是一个对象,它有四个主要的方法: 1、dispatch: 用于action的分发—-在createStore中可以用middleware中间件对dispatch进行改造,比如当action传入dispatch会立即触发reducer,有些时候我们不希望它立即触发,而是等待异步操作完成之后再触发,这时候用redux-thunk对dispatch进行改造,以前只能传入一个对象,改造完成后可以传入一个函数,在这个函数里我们手动dispatch一个action对象,这个过程是可控的,就实现了异步。 2、subscribe: 监听state的变化—-这个函数在store调用dispatch时会注册一个listener监听state变化,当我们需要知道state是否变化时可以调用,它返回一个函数,调用这个返回的函数可以注销监听。 let unsubscribe = store.subscribe(() => {console.log(‘state发生了变化’)}) 3、getState: 获取store中的state—-当我们用action触发reducer改变了state时,需要再拿到新的state里的数据,毕竟数据才是我们想要的。getState主要在两个地方需要用到,一是在dispatch拿到action后store需要用它来获取state里的数据,并把这个数据传给reducer,这个过程是自动执行的,二是在我们利用subscribe监听到state发生变化后调用它来获取新的state数据,如果做到这一步,说明我们已经成功了。 4、replaceReducer: 替换reducer,改变state修改的逻辑。 action: action是一个对象,其中type属性是必须的,同时可以传入一些数据。action可以用actionCreactor进行创造。dispatch就是把action对象发送出去。 reducer: reducer是一个函数,它接受一个state和一个action,根据action的type返回一个新的state。根据业务逻辑可以分为很多个reducer,然后通过combineReducers将它们合并,state树中有很多对象,每个state对象对应一个reducer,state对象的名字可以在合并时定义。 像这个样子: 12345const reducer = combineReducers({ a: doSomethingWithA, b: processB, c: c}) combineReducers: 其实它也是一个reducer,它接受整个state和一个action,然后将整个state拆分发送给对应的reducer进行处理,所有的reducer会收到相同的action,不过它们会根据action的type进行判断,有这个type就进行处理然后返回新的state,没有就返回默认值,然后这些分散的state又会整合在一起返回一个新的state树。 接下来分析一下整体的流程,首先调用store.dispatch将action作为参数传入,同时用getState获取当前的状态树state并注册subscribe的listener监听state变化,再调用combineReducers并将获取的state和action传入。combineReducers会将传入的state和action传给所有reducer,并根据action的type返回新的state,触发state树的更新,我们调用subscribe监听到state发生变化后用getState获取新的state数据。 redux的state和react的state两者完全没有关系,除了名字一样。 上面分析了redux的主要功能,那么react-redux到底做了什么? react-redux如果只使用redux,那么流程是这样的: component –> dispatch(action) –> reducer –> subscribe –> getState –> component 用了react-redux之后流程是这样的: component –> actionCreator(data) –> reducer –> component store的三大功能:dispatch,subscribe,getState都不需要手动来写了。react-redux帮我们做了这些,同时它提供了两个好基友Provider和connect。 Provider是一个组件,它接受store作为props,然后通过context往下传,这样react中任何组件都可以通过context获取store。也就意味着我们可以在任何一个组件里利用dispatch(action)来触发reducer改变state,并用subscribe监听state的变化,然后用getState获取变化后的值。但是并不推荐这样做,它会让数据流变的混乱,过度的耦合也会影响组件的复用,维护起来也更麻烦。 connect –connect(mapStateToProps, mapDispatchToProps, mergeProps, options) 是一个函数,它接受四个参数并且再返回一个函数–wrapWithConnect,wrapWithConnect接受一个组件作为参数wrapWithConnect(component),它内部定义一个新组件Connect(容器组件)并将传入的组件(ui组件)作为Connect的子组件然后return出去。 所以它的完整写法是这样的:connect(mapStateToProps, mapDispatchToProps, mergeProps, options)(component) mapStateToProps(state, [ownProps]): mapStateToProps 接受两个参数,store的state和自定义的props,并返回一个新的对象,这个对象会作为props的一部分传入ui组件。我们可以根据组件所需要的数据自定义返回一个对象。ownProps的变化也会触发mapStateToProps 123function mapStateToProps(state) { return { todos: state.todos };} mapDispatchToProps(dispatch, [ownProps]): mapDispatchToProps如果是对象,那么会和store绑定作为props的一部分传入ui组件。如果是个函数,它接受两个参数,bindActionCreators会将action和dispatch绑定并返回一个对象,这个对象会和ownProps一起作为props的一部分传入ui组件。所以不论mapDispatchToProps是对象还是函数,它最终都会返回一个对象,如果是函数,这个对象的key值是可以自定义的 123456function mapDispatchToProps(dispatch) { return { todoActions: bindActionCreators(todoActionCreators, dispatch), counterActions: bindActionCreators(counterActionCreators, dispatch) };} mapDispatchToProps返回的对象其属性其实就是一个个actionCreator,因为已经和dispatch绑定,所以当调用actionCreator时会立即发送action,而不用手动dispatch。ownProps的变化也会触发mapDispatchToProps。 mergeProps(stateProps, dispatchProps, ownProps): 将mapStateToProps() 与 mapDispatchToProps()返回的对象和组件自身的props合并成新的props并传入组件。默认返回 Object.assign({}, ownProps, stateProps, dispatchProps) 的结果。 options: pure = true 表示Connect容器组件将在shouldComponentUpdate中对store的state和ownProps进行浅对比,判断是否发生变化,优化性能。为false则不对比。 其实connect函数并没有做什么,大部分的逻辑都是在它返回的wrapWithConnect函数内实现的,确切的说是在wrapWithConnect内定义的Connect组件里实现的。 下面是一个完整的 react –> redux –> react 流程:一、Provider组件接受redux的store作为props,然后通过context往下传。 二、connect函数在初始化的时候会将mapDispatchToProps对象绑定到store,如果mapDispatchToProps是函数则在Connect组件获得store后,根据传入的store.dispatch和action通过bindActionCreators进行绑定,再将返回的对象绑定到store,connect函数会返回一个wrapWithConnect函数,同时wrapWithConnect会被调用且传入一个ui组件,wrapWithConnect内部使用class Connect extends Component定义了一个Connect组件,传入的ui组件就是Connect的子组件,然后Connect组件会通过context获得store,并通过store.getState获得完整的state对象,将state传入mapStateToProps返回stateProps对象、mapDispatchToProps对象或mapDispatchToProps函数会返回一个dispatchProps对象,stateProps、dispatchProps以及Connect组件的props三者通过Object.assign(),或者mergeProps合并为props传入ui组件。然后在ComponentDidMount中调用store.subscribe,注册了一个回调函数handleChange监听state的变化。 三、此时ui组件就可以在props中找到actionCreator,当我们调用actionCreator时会自动调用dispatch,在dispatch中会调用getState获取整个state,同时注册一个listener监听state的变化,store将获得的state和action传给combineReducers,combineReducers会将state依据state的key值分别传给子reducer,并将action传给全部子reducer,reducer会被依次执行进行action.type的判断,如果有则返回一个新的state,如果没有则返回默认。combineReducers再次将子reducer返回的单个state进行合并成一个新的完整的state。此时state发生了变化。dispatch在state返回新的值之后会调用所有注册的listener函数其中包括handleChange函数,handleChange函数内部首先调用getState获取新的state值并对新旧两个state进行浅对比,如果相同直接return,如果不同则调用mapStateToProps获取stateProps并将新旧两个stateProps进行浅对比,如果相同,直接return结束,不进行后续操作。如果不相同则调用this.setState()触发Connect组件的更新,传入ui组件,触发ui组件的更新,此时ui组件获得新的props,react –> redux –> react 的一次流程结束。 上面的有点复杂,简化版的流程是: 一、Provider组件接受redux的store作为props,然后通过context往下传。 二、connect函数收到Provider传出的store,然后接受三个参数mapStateToProps,mapDispatchToProps和组件,并将state和actionCreator以props传入组件,这时组件就可以调用actionCreator函数来触发reducer函数返回新的state,connect监听到state变化调用setState更新组件并将新的state传入组件。 connect可以写的非常简洁,mapStateToProps,mapDispatchToProps只不过是传入的回调函数,connect函数在必要的时候会调用它们,名字不是固定的,甚至可以不写名字。 简化版本: 1connect(state => state, action)(Component); redux-saga 有待更新。。。 reselect 在React中最昂贵的操作就是渲染回路.当组件检测到输入的变化,渲染回路就会被触发(译注:这里的意思的组件的action会改变redux的state,变回最终又回到组件了). 当我们初次开始React程序的时候,我们不会担心渲染回路的花销问题.但是当我们的UI变得复杂的时候,我们需要考虑这一点.React提供了一些工具让我们能劫持渲染回路,如果渲染看上去不必要,我们就可以使用工具来阻止重渲染的发生.为了这么做,我们要敲入componentShouldUpdate生命周期事件,返回一个布尔值,通知组件是否应该进行更新.这是以PureRenderMixin作为基础,它比较输入的props和state和先前的props和state,如果两者相等就返回false. 不幸的是,仅此而已. Reselect用来记忆selectors的库.我们定义的selectors是作为函数获取Redux state的某一部分.使用记忆能力,我们可以组织不必要的衍生数据的重渲染和计算过程,由此加速了我们的app. Reselect这个中间件要解决的问题是:在组件交互操作的时候,state发生变化的时候如何减少渲染的压力.在Reselect中间中使用了缓存机制 “selector”是一个简单的Redux库 Selector可以计算衍生的数据,可以让Redux做到存储尽可能少的state。 Selector比较高效,只有在某个参数发生变化的时候才发生计算过程. Selector是可以组合的,他们可以作为输入,传递到其他的selector. 参考 -使用Reselect改进React和Redux程序性能 ES6 在react工程当中,ES6/7/8到处可见,所以ES6也必须要掌握,因为内容太多就简单总结下常用的一些技巧。具体的可参考阮一峰老师的ES6入门。 其实ES6相对于ES5来说,新增了很多的东西,列举些常用的:使用let const完全抛弃var;模板的导入导出(import,export);字符串的扩展(,${});对象的扩展(结构赋值,新增了一些api如assgin(),keys(),is()等;数组的扩展(结构赋值,from(),of(),findIndex(),find()等);函数的扩展(函数参数可以设置默认值,箭头函数,没有arguments对象等);常用来遍历的(for of,forEach,for in,map等);用于解决异步的(generator函数,promise,async/await函数等);class和extends关键字等 虽然很多ES6的技巧用ES5同样能实现,但是ES6大大提高了开发效率,代码也更加优雅,况且各类的打包工具都可以将ES6转化成适配低浏览器的ES5,所以推荐大家使用。 webpack 参考webpack官网 Sass or Less 随着前端的不断发展,网站的页面复杂度也在不断提升,原生 CSS 已经让开发者力不从心,预处理器赋予我们的 “超能力”。浅谈 CSS 预处理器:为什么要使用预处理器? Sass参考Sass语法 Less参考Less语法 React Prepare最后附上react技术栈的相关链接,希望对大家有帮助! react React 入门实例教程 http://www.ruanyifeng.com/blog/2015/03/react.html React 技术栈系列教程 http://www.ruanyifeng.com/blog/2016/09/react-technology-stack.html react 组件 React创建组件的三种方式及其区别 https://www.cnblogs.com/wonyun/p/5930333.html 从性能角度看react组件拆分的重要性 https://www.cnblogs.com/libin-1/p/6810694.html react 性能篇 React性能优化总结 https://segmentfault.com/a/1190000007811296 现代 Web 开发–React 篇 https://github.com/wxyyxc1992/Web-Series/tree/master/React React.js 初学者应该知道的9件事 http://www.iteye.com/news/31748 react router React Router 使用教程 http://www.ruanyifeng.com/blog/2016/05/react_router.html redux Redux 入门教程(一):基本用法 http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html Redux 入门教程(二):中间件与异步操作 http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html Redux 入门教程(三):React-Redux 的用法 http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_three_react-redux.html Redux 中文文档 http://www.redux.org.cn/ Redux 英文文档 https://redux.js.org/ Redux 核心概念 https://www.jianshu.com/p/3334467e4b32 React 实践心得:react-redux 之 connect 方法详解 https://yq.aliyun.com/articles/59428 redux-saga/redux-thunk saga 中文文档 https://redux-saga-in-chinese.js.org/docs/api/index.html 聊一聊 redux 异步流之 redux-saga https://www.jianshu.com/p/e84493c7af35 Redux-Saga 实用指北 https://juejin.im/post/5ad83a70f265da503825b2b4 Reselect https://www.jianshu.com/p/6e38c66366cd http://baijiahao.baidu.com/s?id=1561953979797569픴=spider&for=pc Others Flux 架构入门教程 http://www.ruanyifeng.com/blog/2016/01/flux.html Immutable https://segmentfault.com/a/1190000003910357 dom diff https://calendar.perfplanet.com/2013/diff/ Generator 函数的含义与用法 http://www.ruanyifeng.com/blog/2015/04/generator.html]]></content>
<categories>
<category>React</category>
</categories>
<tags>
<tag>React</tag>
</tags>
</entry>
<entry>
<title><![CDATA[平时整理的css水平垂直居中]]></title>
<url>%2F2018%2F03%2F28%2Fcss%2Fcss-center%2F</url>
<content type="text"><![CDATA[水平垂直居中Learn more here掘金-CSS的垂直居中和水平居中总结 16种方法实现水平居中垂直居中 水平居中1.行内元素(inline element), 给其父元素设置 text-align:center (适用行内元素)什么是行内元素,块级元素 12inline element也叫内联元素、内嵌元素等;行内元素一般都是基于语义级(semantic)的基本元素,只能容纳文本或其他内联元素,常见内联元素 “a”。比如 SPAN 元素,IFRAME元素和元素样式的display : inline的都是行内元素。 2.块级元素(block element), 该元素设置 margin:0 auto即可.只有块级元素才生效(让整个块元素居中)margin 0 auto与text-align:center的区别 1text-align:center设置为文本或img标签等一些内联对象(或与之类似的元素)的居中。margin:0 auto是设置块元素(或与之类似的元素)的居中。 图片的水平居中我们设置图片标签img {margin:0 auto;} ,我们就犯了一个小错误,img类于内联对象,不可以设置图片img标签的margin属性,如果你一定想要设置,那么首先要将它的属性转变为块元素,如下面的代码: 1234img { display:block; margin:0 auto;} 3.在一个盒子里面,让一个有固定宽高的盒子实现水平居中:12display: block; /* 转化成为块级元素 */magin: auto; 4.绝对定位元素的居中实现123456.element { width: 600px; height: 400px; position: absolute; left: 50%; top: 50%; margin-top: -200px; /* 高度的一半 */ margin-left: -300px; /* 宽度的一半 */} 上面的写法需要严格知道盒子的宽高(局限性),所以有了下面的写法(手机web开发可忽略,E10+以及其他现代浏览器才支持) 12345.element { width: 600px; height: 400px; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); /* 50%为自身尺寸的一半 */} 总结下 ,margin:auto实现绝对定位元素的居中(水平垂直居中) 123456.element { width: 600px; height: 400px; position: absolute; left: 0; top: 0; right: 0; bottom: 0; margin: auto; /* 有了这个就自动居中了 */} 垂直居中1.若元素是单行文本, 则可设置 line-height 等于父元素高度1234.element { line-height: 10px; height:10px;} 2.若元素是行内块级元素(行内元素的一种)123456.element { height:10px; line-height:10px; display: inline-block; vertical-align: middle;} 3.块级元素(元素高度固定)123456.element { width: 600px; height: 400px; position: absolute; left: 0; top: 0; right: 0; bottom: 0; margin: auto; /* 有了这个就自动居中了 */} 4.很普通的一种垂直居中12345678.parent::after, .son{ display:inline-block; vertical-align:middle; } .parent::after{ content:''; height:100%; } flex弹性布局实现水平垂直居中1.实现用flex布局的水平垂直居中特别方便,想要进一步了解Flex弹性布局请参考Flex 布局教程:语法篇和 Flex 布局教程:实例篇 flex的居中 12345.element { .display: flex; align-items:center; /* 垂直方向上的对齐方式; */ justify-content:center; /* 水平方向上的对齐方式 */} 但是用了flex布局后 有一些css属性会失效? 2.存在的问题2.1 当一个块级元素要实现垂直居中(文本过短时),和上下滚动(文本过长时)这种场景的时候往往会出现问题. 12345<div class="div-bottom"> <div class="div-bottom-1"> 水平垂直居下~~~~水平垂直居下~~~~ </div></div> 1234567891011121314.div-bottom { display: flex; height: 50%; flex-direction: column; justify-content: center; align-items: center; overflow: auto;}.div-bottom-1 { margin: auto; display: flex; margin: auto;} 2.2 align-items:center;(垂直)和justify-content:center;(水平)的居中方向有的时候会相反? flex布局有主轴和辅轴的概念。]]></content>
<categories>
<category>CSS</category>
</categories>
<tags>
<tag>CSS</tag>
</tags>
</entry>
<entry>
<title><![CDATA[GitHub Pages自定义域名]]></title>
<url>%2F2018%2F03%2F28%2Ftools%2Fgithub-page%2F</url>
<content type="text"><![CDATA[简介现在有很多的前端开发者用XXX.github.io作为自己的博客,然后绑定到自己的域名上面,感觉起来挺不错。一、不用花钱买服务器了,二、一套流程下来前端完全可以搞定。部署完成是这样的 niceboybao.github.io niceboybao.com 有创意的小伙伴还可以用现在流行的三大框架(angular,react,或者vue)构建自己的博客工程呢,这一块我也在着手开始,在工作的业余时间,让自己变得更充实!对没错,生活不止眼前的苟且 还有诗和远方。下面开始正式环节,以niceboybao为例! 主要参考资料Using a custom domain with GitHub Pages 用阿里云免费ssl证书把网站从http变成https 配置 niceboybao.github.io创建repository首先需要在GitHub上面创建一个repository,并且命名为niceboybao.github.io。 添加CNAME文件小伙伴可以把repository克隆下来,在repository下创建一个CNAME文件,文件名大写且没有后缀,如下图。文件里面添加需要绑定的域名,注意没有www和https前缀。 settings然后到repository的设置页面设置将自己的仓库发布到网站上面,并且添加上域名 如图: 域名解析现在挺流行的阿里云,我这边用阿里云举例,首先要找到自己购买的域名(控制台->域名与网站(万网)->域名->解析)然后配置下面2步 第一步,@符号的是指定你的域名xxx.com映射到xxx.github.io,第二布,www那一条是指定你的主域名www.xxx.com映射到xxx.github.io。这边看别人配置的时候都说一定不要忘记`xxx.github.io.`后面的`.`,可是好像加上去了没效果,不知道有没有小伙伴遇到过呢! 配置完了勾选点击启动就ok啦!要全球解析生效,好像得等上一会了。后面就开始你们的表演吧,用自己熟悉的框架开发一个属于自己的blogs吧!niceboybao.com 另外,在GitHub上面的仓库只要在settings里面把他们发布到网站上面,就可以用niceboybao.com/xxx(xxx表示仓库名)访问到如:valentines_day。 用阿里云免费ssl证书把网站从http变成https HTTP 协议是不加密传输数据的,也就是用户跟你的网站之间传递数据有可能在途中被截获,破解传递的真实内容,所以使用不加密的 HTTP 的网站是不太安全的。所以, Google 的 Chrome 浏览器将在 2017 年 1 月开始,标记使用不加密的 HTTP 协议的网站为 Not Secure,不安全。 登录阿里云后台,找到,产品与服务-》找到证书服务,购买证书 找到免费型的DV SSL 购买后在订单页面点击补全,输入你的域名,如xxx.com,最后提交审核。当证书是已签发状态时,就可下载。]]></content>
<categories>
<category>Tools</category>
</categories>
<tags>
<tag>Tools</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hexo docs]]></title>
<url>%2F2018%2F03%2F26%2Ftools%2Fhow-to-hexo-site%2F</url>
<content type="text"><![CDATA[Hexo 配置一个优雅的博客参考链接 NexT开始使用教程 NexT主题配置教程 Hexo 中文文档 搭建个人博客-hexo+github详细完整步骤 step1 安装git,node.js和hexo1npm install -g hexo step2 初始化Hexo新建一个hexo的文件夹,在当前文件件下面执行:1hexo init 在_config.yml,进行基础配置 配置主题这里可以浏览更多主题,这里以NexT主题为例 1git clone https://github.com/iissnan/hexo-theme-next themes/next 本地浏览博客123hexo cleanhexo ghexo s step3 部署到GitHub上在自己的GitHub上面新建一个name.github.io仓库,有的话就不用新建了图片 在_config.yml进行配置123deploy: type: git repo: https://github.com/niceboybao/niceboybao.github.io.git 安装hexo-deployer-git自动部署发布工具1npm install hexo-deployer-git --save 发布到Github1hexo clean && hexo g && hexo d 发布完成输入niceboybao.github.io就可以访问 更多Hexo命令更多Hexo常用命令 12hexo new "postName" //新建文章hexo new page "pageName" //新建页面 stpex 配置时遇到的问题阅读次数统计的问题记录文章访问量的唯一标识符是文章的发布日期以及文章的标题,因此请确保这两个数值组合的唯一性,如果你更改了这两个数值,会造成文章阅读数值的清零重计。]]></content>
<categories>
<category>Tools</category>
</categories>
<tags>
<tag>Tools</tag>
</tags>
</entry>
</search>