Giter VIP home page Giter VIP logo

blog's People

Contributors

kuckboy1994 avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

blog's Issues

vi&vim

介绍

viVim都是运行在类Unix系统下的编辑器。
viVisual的不正规的缩写。
Vim是从vi发展出来的一个文本编辑器。正式名字Vi IMproved

vi琐事

vi是在伯克利加州大学,Evans Hall中,使用"Lear-Siegler ADM3A终端”编写完成,在这台机器上的“退出键”(Esc),也就是今天键盘“表格键”(Tab)的位置,目前vi用户仍使用“退出键”(Esc)来转换状态。

看了这张图,ヾ(。`Д´。) 和HHKB的键盘好像啊,怪不得大神都用HHKB。
但用HHKB不一定是大神☹。

模式编辑器

vi 是一个模式编辑器
常用的模式

  • 普通模式
  • 命令模式
  • 插入模式

简单介绍常用的操作

保存&退出

:q quit
:q! quit and abandom
:w write
:wq write and quit

移动光标

表1:vi(vim)光标移动按键
按键 移动光标
l or 右箭头 向右移动一个字符
h or 左箭头 向左移动一个字符
j or 下箭头 向下移动一行
k or 上箭头 向上移动一行
0 (零按键) 移动到当前行的行首。
^ 移动到当前行的第一个非空字符。
$ 移动到当前行的末尾。
w 移动到下一个单词或标点符号的开头。
W 移动到下一个单词的开头,忽略标点符号。
b 移动到上一个单词或标点符号的开头。
B 移动到上一个单词的开头,忽略标点符号。
Ctrl-f or Page Down 向下翻一页
Ctrl-b or Page Up 向上翻一页
numberG 移动到第 number 行。例如,1G 移动到文件的第一行。
gg 移动到文件的第一行
G 移动到文件末尾。
l、h、j、k、b、w都是可以结合数字键一起使用的 比如10k,向上移动10行
表2: 编辑模式进入
命令 编辑模式进入
i 当前字符前面插入
a 当前字符后面追加字符。
a 当前字符后面追加字符。
A 当前行尾后面追加字符。
o 当前行的下方打开一行。
O 当前行的上方打开一行。
表3: 文本删除命令
命令 删除的文本
x 当前字符
3x 当前字符及其后的两个字符。
dd 当前行。
5dd 当前行及随后的四行文本。
dW 从光标位置开始到下一个单词的开头。
d$ 从光标位置开始到当前行的行尾。
d0 从光标位置开始到当前行的行首。
d^ 从光标位置开始到文本行的第一个非空字符。
dG 从当前行到文件的末尾。
d20G 从当前行到文件的第20行。
表4: 复制命令 & 粘贴
命令 复制的内容
p 当前行光标位置之后粘贴
P 当前行光标位置之前粘贴
yy 当前行。
5yy 当前行及随后的四行文本。
yW 从当前光标位置到下一个单词的开头。
y$ 从当前光标位置到当前行的末尾。
y0 从当前光标位置到行首。
y^ 从当前光标位置到文本行的第一个非空字符。
yG 从当前行到文件末尾。
y20G 从当前行到文件的第20行。
条目 含义
: 冒号字符运行一个 ex 命令。
% 指定要操作的行数。% 是一个快捷方式,表示从第一行到最后一行。另外,操作范围也可以用 1,5 来代替(因为我们的文件只有5行文本),或者用 1,$ 来代替,意思是 “ 从第一行到文件的最后一行。”如果省略了文本行的范围,那么操作只对当前行生效。
s 指定操作。在这种情况下是,替换(查找与替代)。
/Line/line 查找类型与替代文本。
g 这是“全局”的意思,意味着对文本行中所有匹配的字符串执行查找和替换操作。如果省略 g,则只替换每个文本行中第一个匹配的字符串。
表13-5: 替换确认按键
按键 行为
y 执行替换操作
n 跳过这个匹配的实例
a 对这个及随后所有匹配的字符串执行替换操作。
q or esc 退出替换操作。
l 执行这次替换并退出。l 是 “last” 的简写。
Ctrl-e, Ctrl-y 分别是向下滚动和向上滚动。用于查看建议替换的上下文。

实例

  1. 内容查找
    文件中查找kuck
/kuck

n // 查找下一个
N // 查找上一个
  1. 内容替换
    替换shankuck
:%s/shan/kuck/g
  1. 可以同时编辑两个文档
vi shanchao.txt demo.txt

:ls
  1 %a   "shanchao.txt"                         line 1
  2 #    "demo.txt"                             line 1

:n  // 下一个文件
:N  // 上一个文件
:e newfile  // 新建一个newfile的文件

参考

讨论一下css命名

现在开发中遇到的最头痛的事情莫过于给css命名了。好的命名可以快速的帮我们定位到页面中的元素,修改上也非常轻松。
幸运的是我们有BEM

BEM

块(block)、元素(element)、修饰符方法(modifier)(通常称为BEM)是HTML和CSS类中常用的命名约定。是由Yandex团队提出的,它的目标是帮助开发者更好地理解项目中的HTML和CSS之间的关系。

  • B: block 是模块,或者称为一个组件。
  • E: element 代表块中的元素(子节点),为了表明子节点属于哪个模块,写法是block__element
  • M:modifier 代表某个节点的修饰状态。

下面是简单的例子:

.block{}    /* 模块 */
.block--modifier{}  /* 当前模块的修饰符 */
.block__element{}   /* 模块下面的元素 */
.block__element--modifier{} /* 当前模块下面的元素的修饰符 */

你可能会存在疑问为什么使用两个-或两个_,其实这个是给你用来当做连接符来使用的。这样同样增加了你命名的多样性。
例如:

.footer-bar{}
.footer-bar--full{}
.footer-bar__info{}

注意

有修饰符了并不意味原来的.block__element就不需要了,.block__element是主体,.block__element--modifier的作用仅仅是展示modifier的效果。
下面是一个good的例子:

<div class="block block--mod">...</div>
<div class="block block--size-big block--shadow-yes">...</div>

下面是一个bad的例子:

<div class="block--mod">...</div>

BEM的好处是让你看着类名就知道他在哪里(场景)使用的。不像css module 通过不断的增加层级来显示他的位置。举个类似生活中的模型来显示BEM的是如何关联的:

.person{}
.person__hand{}
.person__hand--left{}
.person--female{}
.person--female__hand{} /* 不推荐这么写 */

只要能看懂单词的意思,基本上就知道了指代是什么。
可能有人会疑惑.person--female__hand{}不就变成主体了吗?其实我是不推荐这么写的,如果你想展示的是女性的手的话,可以通过在父元素person上增加.person--female来修饰。存在多个状态可以增加.block__element--modifier来修饰,完全没有问题。

再举个官网上的例子:
我们有一个表单,想要在圣诞节增加一点节日气息,我们就可以增加一个form--theme-xmas的类,通过--修饰符我们可以快速的构建我们新的版本。

<form class="form form--theme-xmas form--simple">
  <input class="form__input" type="text" />
  <input
    class="form__submit form__submit--disabled"
    type="submit" />
</form>
.form { }
.form--theme-xmas { }
.form--simple { }
.form__input { }
.form__submit { }
.form__submit--disabled { }

再增加一个配图的例子:o(╯□╰)o

这个搜索框就可以看作一个块Block,这个块里由两个子节点,一个是输入区域input,还有一个是查询按钮button。
对于这个块的命名,按照BEM法则,我们可以写成以下这样:

<form class="site-search">
    <input type="text" class="site-search__input">
    <input type="button" class="site-search__button" value="search">
</form>

将整体的搜索框命名为site-search作为一个模块,模块下的两个子节点就在后面加上两根下划线,加上自己的名字 input 和 button,这样的命名方式,即使我们没有看到网页内容,只看了CSS样式名字,也能感受到页面结构和页面元素之间的关系。
如果要说明按钮button是灰色的,我们还可以加上修饰的类名modifier,比如可以是site-search__button--gray。

上图就说明能将某个元素进行模块化,里面能够包含多个元素,这样的命名规范能够更好的说明元素之间的关系。

Yandex提出的BEM只是一种比较严格的命名规范,个人认为最重要的是严格,你只有严格遵守了,才不会出现一些奇怪的问题。至于规则都是可以更加自身情况改变的。

BEM变异

并列选择器版本

.block-element.modifier{}

.modifier 不单独使用,所以不存在冲突
例1:

.menu{}
.menu-item{}
.menu-item.active{}

例2:

.shopCart{}
.shopCart-title{}
.shopCart-item{}
.shopCart-item.selected{}

BEN和BEM变异——并列选择器演示:demo

BEM和BEM变异和原本的命名方式的对比

BEM的优势:

  • 让原本存在多意的内容变得更加直意
  • 原本层次化的内容变成了扁平,查找更加方便

BEM的劣势:

  • 长得难看,太长了(┑( ̄Д  ̄)┍)
  • 代码量增加(现在有gzip压缩,我们不需要担心文件太大,大部分编辑有自动补全功能也能接受)

BEM变异——并列选择器的优势:

  • 让原本存在多意的内容变得更加直意
  • 比BEM的“段”

BEM变异——并列选择器的劣势:

  • 会占用修饰符类。如果修饰符类的权重变大页面维护成本变大。
  • 不兼容ie6

总结

引用一句话作为结束语:

BEM(或BEM的变异)是一个非常有用,强大,简单的命名约定,让你的前端代码更容易阅读和理解,更容易协作,更容易控制,更加健壮和明确而且更加严密。
尽管BEM看上去多少有点奇怪,但是无论什么项目,它对前端开发者都是一个巨有价值的工具。

参考

【翻译】给文本输入框增加下边框效果(Text Input with Expanding Bottom Border)

文本翻译自 css-tricks 网站的 Text Input with Expanding Bottom Border 一文。翻译有误,期待斧正。

正文

Petr Gazarov在他的文章Text input highlight, TripAdvisor style中使用了一个漂亮的小设计。

这是一个花招,在文本框下面实现这样的伸缩效果是不能实现的,所以Petr使用了span标签来同步内容,表现上想是它有一个边框一样。整个过程像是一个响应式的组件。

如果你愿意使用<span contenteditable>,你可以在CSS中完成所有的事情!

<style>
div {
    padding: 0.4rem 0;
    border-bottom: 4px solid #383838;
    width: 90vw;
}
span {
    position: relative;
    bottom: -11px;
    color: white;
    display: inline-block;
    padding: 0.4rem 0;
    border-bottom: 4px solid #D5BA5E;
    outline: 0;
}
</style>
<body>
    <div>
        <span contenteditable="true">Content</span>
    </div>
</body>

因为你没有使用input,所以placeholder(占位符)也就无效了。

拓展

contenteditable的兼容ie6+

contenteditable是有继承性(inherit)的。如果没有设置该属性,其默认值继承自父元素。

contenteditable=true在黏贴的时候会把html标签给带上,所以显示出原来的感觉和富文本编辑差不多。

张鑫旭-小tip: 如何让contenteditable元素只能输入纯文本 一文中提到了

contenteditable=""
contenteditable="events"
contenteditable="caret"
contenteditable="plaintext-only"
contenteditable="true"
contenteditable="false"

contenteditable="plaintext-only" 黏贴是纯文本的内容。但也仅限于Chrome之流的浏览器。

收获

  • 认识到自己对于样式的了解还不够
  • 可以看看W3C之后的规范和草案

参考

laydate日历组件改造心得

最近两天对layDate 5.0.85版本进行了改造。来谈一下心得。

修改内容

  1. 修复了当minmax大的时候。在切换到月份显示界面的时候,最小值的月份显示为不可点。
  2. 增加了过滤日期的功能(正选和反选)
  3. 增加了选择最近的功能
  4. 增加了暗黑主题
    想要体验的小伙伴,点击传送门

体会

当时豆饼(我的同事小伙伴)推荐了我使用layDate日历组件,我看了一下感觉样式上和功能上基本都满足我们工作所需,而且是开源的(这就方便我们个性化的定制)。号称是layui独立维护的三大组件之一,而且还是最近重写的,瞬间感觉就被他征服了。立马上手!

当时还是有点心虚的,毕竟还是第一次改源码,风险还是存在的。发现写法和我以前写原生js插件的差不多(复杂程度还是差很多的),还能看得懂些。但是有些方法就有点不知为何这么写了,但主要还是完成我的任务。读代码的时候发现他封装了很多类似jQuery的方法,如:
extend、each、addClass、removeClass、hasClass、attr、find、html、val、append、remove、on、off。
还有一些个性化的方法,如:
elem(创建元素)、elem(创建元素)、addStr(追加字符)、digit(数字前置补零)。
这些方法其实在平常的工作中也是很常用的,但jQuery已经帮我们做好了。但是如果在现在化的工作流中比如(react、vue)中我们就不会去选择使用jQuery了,可能就需要我们自己封装了。到时候可以回头看看。

组件的config和方法都设置在原型上,一个是保证方法始终可用(上下文方便传递),另一个是方便链式调用。

laydate通过window对象向外暴露。

支持amd规范。

同时试了一下修改主题,主题的设置感觉不是很方便,如果我上传到资源服务器,要是要增加样式的话,就得替换文件,后期考虑增加配置样式地址。

过几天有空了整理一下,准备给master发个pull request。

拒绝97,拥抱开源! 2333

【翻译】使用伪元素来形成类似“居中浮动”的效果(Faking ‘float: center’ with Pseudo Elements)

文本翻译自 css-tricks 网站的 Faking ‘float: center’ with Pseudo Elements 一文。翻译有误,期待斧正。

正文

比方说,你想完成一个类似这样的布局:

catinmiddle1

这个展示效果没毛病吧?特别是你想把这个猫作为文章的重点。

做到这一点其实并不容易。我们当前有的布局方法并不能真正的考虑到这一点。事实上,有时候觉得这种布局并没有真正的“网页设计”的**。我说的对吗?我不认为即使有这种流通边缘的CSS布局系统就能很好地处理这个问题。这有点像float,因为文本环绕着图像,但是文本环绕两个方向,所以有点像float: center;居中浮动;或float: both;全部浮动,但这两个都是不存在的。

但这是可以实现的!

证明:查看 查看源码

我们将通过使用浮动的伪元素占位符来实现它。每一列①放入一个伪元素占位符,一个左浮动,一个右浮动。伪元素的高度为图像的高度,宽度为图像的一半宽(差不多,不要忘记你还有padding和中间的槽【两列中间的分隔距离】需要考虑)。

主要代码:

#l:before, #r:before { 
  content: ""; 
  width: 125px; 
  height: 250px; 
}
#l:before { 
  float: right; 
}
#r:before { 
  float: left; 
}

psuedoplaceholders

现在文本中有一个洞,准备好把我们的图像放在那里。我们可以通过绝对定位来实现,就像在演示中那样。或者你可以把它放在上面的一个元素上,然后用负的顶部边缘来把文本拉出来。

标注:

  • 列①: 注意,我们使用的是div来实现文本的列,而不是CSS列,虽然使用css来实现更酷,更具有语义化,但是用css的话我们上面的就不起作用了。

前端必备技能树

前端必备技能树

今天在gitchat上看到了一个chat,主题是:“想拿互联网大厂的前端 offer, 除了技术,你还差什么?” 看完之后内心又备受煎熬...

感觉自己太弱小了,之前我还整理过一个github仓库,坚持了两个月,对于当时的我来说那段时间进步是非常快,因为那时候我啥也不懂,来什么记什么。之后我的强迫症犯了,想整理的好看一点啊什么的(balabala...)。就没去更新了,开始忙公司的项目(使用的vue),忙于每天回来看视频,每天加班工作,没时间进行记录。直到最近我忙完react的项目自后,我回头写vue的时候,感觉代码有点生疏了。之后强迫症又犯了,“重构”了一下(增加了vuex,规范了es6的写法,使用BEM规范,抽离出api简化代码等)。其实做这些操作对于我来说收获并不大,其实我是想搞一搞vue的底层,读一读源码··· 但是考虑到之后的路,还是先准备下基础的内容,希望有磨刀不误砍柴工的奇效。

这个列表就是上面chat分享的内容:
希望能两天完成一块,早日完成我的目标。

javascript 相关

  • 原型链与作用域
  • 闭包
  • 模块化(amd/cmd/umd/ES6 module)
  • 跨域多种方式,如 jsonp
  • javascript 中的 this 指向问题
  • CORS
  • AJAX 的几种状态,ajax与fetch,hijax
  • iframe 与 onload 阻塞主页面
  • 前端安全与 CSRF,XSS,SQL注入,DDOS
  • js 异步加载
  • IE 内存泄露
  • js 创建对象的几种方式
  • js 继承的几种方式与优缺点
  • SEO
  • ES6 新特性
  • promise 与 generator
  • 服务器推
  • jQuery 相关
  • js 捕获与冒泡
  • drag 和 drop 实现拖拽
  • cookie/session/本地存储
  • 雅虎网站优化的军规
  • css 与 js 的阻塞加载
  • chrome / IE 浏览器事件兼容

css 相关

  • 垂直水平居中
  • 盒模型
  • 浮动与定位
  • 排版引擎与js引擎
  • GPU 加速与动画性能
  • DOM1,DOM2,DOM3 规范
  • css 性能
  • h 标签与 title 标签
  • em 与百分比等
  • 浏览器缓存与应用缓存
  • div 与 table 布局
  • web 标准
  • css 的 hack 技术
  • png/jpg/webp 图片格式
  • canvas 与 svg
  • css3 的新特性,如 flex 布局等
  • 响应式布局
  • link 与 import 区别
  • 三栏自适应
  • b 和 strong,i 和 em 区别
  • 减少页面回流
  • BFC
  • 硬件加速与动画优化

前端自动化相关

  • webpack 相关
  • webpack-dev-server 相关
  • 单页面打包工具+多页面打包工具
  • babel 相关
  • 其他知识
  • http/1.1 与 http2
  • http 三次握手协议
  • http 状态码
  • json 与 xml
  • 前端性能优化
  • nodejs/npm 相关内容

算法

  • 几种排序算法
  • 回文字符
  • 递归(很重要)
  • 其他常见的前端算法

上面内容可能不全,后续可以再补充

获取本机的ip地址

有的时候我们需要知道我们本地机器的ip地址。

前端项目大部分都是通过localhost:端口号来运行的,但是比如我们要写RN的时候,在安卓模拟器中的我们可能就不能直接使用localhost127.0.0.1,使用的应该是局域网给我们动态分配的ip地址。

下面介绍两种三种方式获得动态分配的ip地址:

图形化获取

  1. 打开偏好设置,点击网络

  2. 红框圈起来的就是ip地址

命令行获取

  1. 打开terminal
    输入ifconfig。注意不是ipconfig

程序获取

每次链接wifi的时候,我们的ip可能就会被重新分配,每次去走上面一遍可能会比较麻烦,有没有上面比较高级的方式获取呢。

  1. 首先需要node环境
  2. 在对应的程序下安装address
npm init -y
npm install --save-dev

为了演示简单,单独写一个文件,例如:getIpAddress.js

const address = require('address')
console.log(address.ip())

使用node运行。

有了上述的方法,我们就可以在程序启动的时候,告诉开发者(我们自己)当前的ip地址是多少,我们就能直接去模拟器中打开了。

address包还可以获取IPv6MAC地址。详细查看 address-npm

XSS攻击

XSS攻击全称跨站脚本攻击,常见的就是攻击者把恶意代码植入到用户页面中。

在XSS攻击中,一般有三个角色参与:攻击者、目标服务器、受害者的浏览器。

由于服务端没有对用户的输入做安全方面的验证,攻击者就通过输入的方式,夹带一些恶意的html脚本代码(包括html, css, js)。

XSS攻击的分类

  1. 反射型XSS(Reflected XSS)

反射型XSS,又称非持久型XSS。之所以称为反射型XSS,则是因为这种攻击方式的注入代码是从目标服务器通过错误信息、搜索结果等等方式“反射”回来的。而称为非持久型XSS,则是因为这种攻击方式具有一次性。攻击者通过电子邮件等方式将包含注入脚本的恶意链接发送给受害者,当受害者点击该链接时,注入脚本被传输到目标服务器上,然后服务器将注入脚本“反射”到受害者的浏览器上,从而在该浏览器上执行了这段脚本。

比如攻击者将如下链接发送给受害者:

http://www.targetserver.com/search.asp?input=<script>alert(document.cookie);</script>

当受害者点击这个链接的时候,注入的脚本被当作搜索的关键词发送到目标服务器的search.asp页面中,则在搜索结果的返回页面中,这段脚本将被当作搜索的关键词而嵌入(服务端渲染)。这样,当用户得到搜索结果页面后,这段脚本也得到了执行。这就是反射型XSS攻击的原理,可以看到,攻击者巧妙地通过反射型XSS的攻击方式,达到了在受害者的浏览器上执行脚本的目的。由于代码注入的是一个动态产生的页面而不是永久的页面,因此这种攻击方式只在点击链接的时候才产生作用,这也是它被称为非持久型XSS的原因。
危害在用户查询的时候,可以实现把用户的cookie信息发送给攻击者

情况二,通过渲染页面进行攻击:
比如攻击者将如下链接发送给受害者:

http://www.targetserver.com/response-xss.html?input=<style>body{background:red;}</style>

需要渲染input中的内容到页面中,上面的会修改页面的背景色。
渲染模式是没办法获取用户cookie信息的(个人测试得出的结论,有异议敬请斧正)。
如果一个input的value属性值是

琅琊榜" onclick="javascript:alert('handsome boy')

就可能出现

<input type="text" value="琅琊榜" onclick="javascript:alert('handsome boy')">

点击输入框爆炸。。

  1. 存储型XSS(Stored XSS)

存储型XSS,又称持久型XSS,他和反射型XSS最大的不同就是,攻击脚本将被永久地存放在目标服务器的数据库和文件中。这种攻击多见于论坛,攻击者在发帖的过程中,将恶意脚本连同正常信息一起注入到帖子的内容之中。随着帖子被论坛服务器存储下来,恶意脚本也永久地被存放在论坛服务器的后端存储器中。当其它用户浏览这个被注入了恶意脚本的帖子的时候,恶意脚本则会在他们的浏览器中得到执行,从而受到了攻击。

可以看到,存储型XSS的攻击方式能够将恶意代码永久地嵌入一个页面当中,所有访问这个页面的用户都将成为受害者。如果我们能够谨慎对待不明链接,那么反射型的XSS攻击将没有多大作为,而存储型XSS则不同,由于它注入的往往是一些我们所信任的页面,因此无论我们多么小心,都难免会受到攻击。可以说,存储型XSS更具有隐蔽性,带来的危害也更大,除非服务器能完全阻止注入,否则任何人都很有可能受到攻击。

  1. 发一篇文章,里面包含了恶意脚本
今天天气不错啊!<script>alert('handsome boy')</script>
  1. 后端没有对文章进行过滤,直接保存文章内容到数据库。

  2. 当其他看这篇文章的时候,包含的恶意脚本就会执行。

PS:因为大部分文章是保存整个HTML内容的,前端显示时候也不做过滤,就极可能出现这种情况。

结论:

后端尽可能对提交数据做过滤,在场景需求而不过滤的情况下,前端就需要做些处理了。

开发安全措施:

  1. 首要是服务端要进行过滤,因为前端的校验可以被绕过。

  2. 当服务端不校验时候,前端要以各种方式过滤里面可能的恶意脚本,例如script标签,将特殊字符转换成HTML编码。

  3. 跨站请求伪造

跨站请求伪造(Cross-SiteRequest Forgery,CSRF),作为OWASP组织的2007年提出十大安全漏洞第五,它也属于XSS攻击的一种衍生。所谓跨站请求伪造,就是攻击者利用XSS注入攻击的方式,注入一段脚本,而当受害者的浏览器运行这段脚本时,脚本伪造受害者发送了一个合法请求。比如我们注入如下的HTML代码:

<img src="http://www.bank.com/transfer.do?toAct=123456&money=10000">

假如上面的代码中所访问的是某个银行网站的转账服务,则当受害者的浏览器运行这段脚本时,就会向攻击者指定的账户(示例的123456)执行转账操作。由于这个转账请求是在受害者的浏览器中运行的,因此浏览器也会自动将受害者的Cookie信息一并发送。这样,发送的请求就好像是受害者自己发送的一样,银行网站也将认可这个请求的合法性,攻击者也就达到了伪造请求的目的。

类似操作:
攻击者提供一个免费的wifi,连接之后,在本地开启fiddler这种抓包工具,这类工具不仅能获取到被攻击者的所有信息,还能修改用户访问的内容,模拟用户在被害者设备发起请求。

  1. 注入恶意软件

除了直接注入恶意脚本以外,通过XSS攻击,攻击者也可以很方便地在脚本中引入一些恶意软件,比如病毒、木马、蠕虫等等。例如,攻击者可以在某个自己建立的页面上放置一些恶意软件,然后用XSS注入的方式,插入一段引用该页面的脚本。这样当受害者的浏览器执行这段脚本的时候,就会自动访问放置了恶意软件的页面,从而受到这些恶意软件的感染。

利用XSS注入恶意软件的方式,攻击者可以很方便地在互联网上传播病毒、木马和蠕虫,通过这种途径,攻击者就可以通过这些病毒、木马和蠕虫,进一步地对受害者的主机发动攻击。目前,互联网上的“挂马”现象非常普遍,而XSS注入的出现也无疑给“挂马”的攻击者指明了又一个新的方向。通过传播这些木马,窃取合法用户的敏感信息,不少非法攻击者也逐渐将这一过程产业化,经常可以见到以信封方式批量兜售账号密码的现象。这也给许多正常的网络用户造成了许多无法挽回的巨大损失,造成的危害也很大。

XSS的预防

在前面的文章中,我们具体介绍了各种XSS攻击的原理和方式。可以看出,XSS是一种覆盖面很广,隐蔽性很高,危害也非常大的网络应用安全漏洞。除非网站服务器完全不存在XSS漏洞,否则就会给攻击者们留下空子。因此,如何在Web应用程序的开发过程中对XSS漏洞进行预防,是所有网站开发人员所必须注意的重中之重。下面我们介绍几种常用的XSS预防措施。

  1. 输入检测

对用户的所有输入数据进行检测,比如过滤其中的“<”、“>”、“/”等可能导致脚本注入的特殊字符,或者过滤“script”、“javascript”等脚本关键字,或者对输入数据的长度进行限制等等。同时,我们也要考虑用户可能绕开ASCII码,使用十六进行编码如“<”(“<”)、“>”(“>”)等来输入脚本。因此,对用户输入的十六进制编码,我们也要进行相应的过滤。只要开发人员能够严格检测每一处交互点,保证对所有用户可能的输入都进行检测和XSS过滤,就能够有效地阻止XSS攻击。

  1. 输出编码

通过前面对XSS攻击的分析,我们可以看到,之所以会产生XSS攻击,就是因为Web应用程序将用户的输入直接嵌入到某个页面当中,作为该页面的HTML代码的一部分。因此,当Web应用程序将用户的输入数据输出到目标页面中时,只要用HtmlEncoder等工具先对这些数据进行编码,然后再输出到目标页面中。这样,如果用户输入一些HTML的脚本,也会被当成普通的文字,而不会成为目标页面HTML代码的一部分得到执行。

  1. Cookie防盗

利用XSS攻击,攻击者可以很方便地窃取到合法用户的Cookie信息。因此,对于网站来说,不能在Cookie信息中存放太多敏感信息,也不能将Cookie作为身份认证的唯一标识,等等。因此,对于Cookie,我们可以采取以下的措施。首先,我们要尽可能地避免在Cookie中泄露隐私,如用户名、密码等;其次,我们可以将Cookie信息用MD5等Hash算法进行多次散列后存放;再次,为了防止重放攻击,我们也可以将Cookie和IP进行绑定,这样也可以阻止攻击者冒充正常用户的身份。

  1. 严格限制URL访问

攻击者使用XSS攻击,通常都要借助于自己指定的网站页面,比如用它来记录敏感信息、在该页面上“挂马”等等。因此,在页面的脚本代码执行过程中,只要我们严格限制其访问的URL,比如只允许脚本代码访问本网站的URL等方式,就可以避免脚本的执行链接到其它可能是攻击者指定的页面上。

  1. 用户注意事项

作为一名普通的网络用户,在XSS攻击的预防上总体处在被动的地位。但是我们也可以通过采取一些措施来尽可能地避免受到XSS攻击。首先,我们不要轻易相信电子邮件或者网页中的不明链接,这些链接很有可能引导反射型XSS攻击或者使我们访问到一些不安全的网页。其次,我们在不必要的时候可以禁用脚本功能,这样XSS注入的脚本就无法得到运行。再次,我们也可以使用一些安全的浏览器上网,有的浏览器提供XSS过滤功能,会提示页面中可能发生的XSS注入并将其阻挡下来。

XSS的漏洞检测

  1. 黑盒测试
    所谓黑盒测试,就是在不知道系统的代码和运行状态的条件下,对系统进行的测试。在对XSS漏洞的检测中,我们可以模拟黑客的攻击手段,在所有可能的数据输入接口处,尝试进行一些XSS注入。通过观察注入后的引用这些数据的页面,看其是否出现被注入的现象,即可确实是否存在XSS漏洞。比如我们可以用下面所列的一些脚本来尝试XSS注入:
1. 在HTML标签中输出
<script>alert(document.cookie)</script>
e.g.
<div><script>alert(document.cookie)</script></div>

2. 在HTML属性中输出
"><script>alert(document.cookie)</script><"
e.g.
<div name=""><script>alert(document.cookie)</script><""></div>
e.g.
<img src="javascript:alert('XSS')">

http://xxx.com/yyy.png" onerror="alert('XSS')
e.g.
<img src="http://xxx.com/yyy.png" onerror="alert('XSS')">

3. 在<script>标签中输出
";alert(document.cookie);//
e.g. 
<script>
var x = "";alert(document.cookie);//";
</script>

4. 在事件中输出
'');alert(document.cookie
e.g.
<a href="funcA('');alert(document.cookie)"></a>

5. 在CSS中输出(仅低版本 IE 有效)
body {background-image:url("javascript:alert('XSS')");}
body {background-image:expression(alert('xss'));}

如果在打开那些引用了该输入数据的页面时,弹出对话框显示信息,则可以确定该数据输入时有可能导致XSS注入,从而确定了XSS漏洞的位置。

  1. 静态分析

XSS漏洞静态分析方法属于白盒测试方法的一种,它通过对Web应用的代码进行分析,从而发现其中可能存在的问题。通常来说,静态分析技术只是对代码进行一些简单的扫描,找到其中有可能导致XSS注入的地方,将其报告给我们。

比如在Web应用的代码中可能存在一些读入数据的API,如Request.QueryString(),$_GET等,如果存在这些API,则表示可能引入XSS的注入。通过静态分析工具,我们可以很容易发现所有这些读入数据的API,从而详细检查每一个数据输入点是否进行了XSS注入的过滤。可以看到,静态分析的方法,只是帮助我们定位XSS漏洞的可能位置,由于静态分析工具难以判定是否对输入数据进行过XSS过滤,因此还是需要我们手动地进行检查,从而确保不存在XSS漏洞。

  1. 数据流分析

XSS漏洞之所以产生,根本原因在于不安全的数据流,使得用户的输入数据被直接嵌入到某些页面中。比如PHP中的echo语句,就能够将一些数据直接添加为HTML页面的一部分,如果这个数据是用户注入了XSS脚本的数据,则会导致产生XSS攻击。因此,数据流分析的主要**就是使用一些模型或者工具,分析Web应用程序代码中的数据传输情况,从而发现其中存在的问题。比如,我们可以将用户的输入数据所存储的变量打上污点标记,通过对数据流和变量类型的分析,逐步标记所有引用了污点变量的中间变量,最后通过观察输出到页面中的变量数据是否存在污点,来判断是否可能产生XSS漏洞。

参考

注释规范

此为开发团队遵循和约定的注释规范,意在降低后期维护的代价。

为什么要写代码注释?

  • 编码规范中有一条就是——见名知意。但有的时候直白的函数名不能表达完整的意思,这时候就是注释就可以很好的帮助我们解释和说明了。
  • 请确保你的代码能够自描述、注释良好并且易于他人理解。
  • 好的代码注释能够传达上下文关系和代码目的。

注释中写什么?

  • 难于理解的代码段
  • 可能存在错误的代码段
  • 浏览器特殊的HACK代码
  • 想吐槽的产品逻辑
  • 业务逻辑强相关的代码

对这些内容写一些注释对于自己或帮助他人理解是非常有帮助的。

什么时候写注释?

  • 在写代码前添加注释
    • 这时候你脑子里是清晰完整的思路。
  • 在写完代码之后添加注释
    • 你是在整理或者总结。
    • 它可能要花费你更多的时间。
      就好比做需求分析一样,你确认好了需求,直接写完。如果写完或者边写边确认需求,你将花费更多的时间。

注释尽量使用英文来描述 (不是必须的)

使用中文注释的弊端:
在文件编码改变的时候中文会变成乱码的问题。

用英文注释还是用中文注释, it is a problem, 但不管怎样, 注释是为了让别人看懂, 难道是为了炫耀编程语言之外的你的母语或外语水平吗;

注释的详解

注释一般的写法,遵从这个规范方便大家理解,解决强迫症的问题。。。

圣战—— tab vs space


千万不要tab和space混用,还有什么比生命更加重要呢?
优酷视频链接
o(* ̄︶ ̄*)o

单行注释

  • 双斜线后,必须跟注释内容保留一个空格
  • 可独占一行, 前边不许有空行, 缩进与下一行代码保持一致
  • 可位于一个代码行的末尾,注意这里的格式
// Good
if (condition) {
    // if you made it here, then all security checks passed
    allowed();
}
var zhangsan = "zhangsan";    // 双斜线距离分号一个tab(或多个tab,用于对齐),双斜线后始终保留一个空格

多行注释

  • 最少三行, 格式如下
  • 前边留空一行
/**
 * 注释的内容
 */

定义类型: 都是以{开始, 以}结束。

使用说明: 提供参数的说明. 使用完整的句子, 并用第三人称来书写方法说明.

栗子:

/**
 * [description]
 * @param  {[type]} params [description]
 * @return {[type]}        [description]
 */

// 以下的代码是 jquery-3.1.1.js 中的一段代码
/**
 * Checks document order of two siblings
 * @param {Element} a
 * @param {Element} b
 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
 */
function siblingCheck( a, b ) {
  var cur = b && a,
  diff = cur && a.nodeType === 1 && b.nodeType === 1 && a.sourceIndex - b.sourceIndex;

  // Use IE sourceIndex if available on both nodes
  if ( diff ) {
    return diff;
  }

  // Check if b follows a
  if ( cur ) {
    while ( (cur = cur.nextSibling) ) {
      if ( cur === b ) {
        return -1;
      }
    }
  }
  return a ? 1 : -1;
}

/**
 * 函数功能简述
 * 具体描述一些细节
 * @param    {string}  address     地址
 * @param    {array}   com         商品数组
 * @param    {string}  pay_status  支付方式
 * @returns  void
 *
 * @date     2017-04-10
 * @author   name<[email protected]>
 */

单行注释和多行注释的使用规范

  • 方法前面使用多行注释。
  • 方法内部使用单行注释,如果内容比较多,使用多个单行注释。

文档注释

/**
 * @author: who are you
 * @date: when you write it
 * @description: the function of this file.
 */

标签

@author 标识开发者信息(非常重要)

注释一般出自author之手,对代码和项目最了解的人。

开发者信息能够体现开发人员对文件的贡献,并且能够让遇到问题或希望了解相关信息的人找到维护人。通常情况文件在被创建时标识的是创建者。随着项目的进展,越来越多的人加入,参与这个文件的开发,新的作者应该被加入 @author 标识。

@author 标识具有多人时,原则是按照 责任 进行排序。通常的说就是如果有问题,就是找第一个人应该比找第二个人有效。比如文件的创建者由于各种原因,模块移交给了其他人或其他团队,后来因为新增需求,其他人在新增代码时,添加 @author 标识应该把自己的名字添加在创建人的前面。

@author 中的名字不允许被删除。任何劳动成果都应该被尊重。

业务项目中,一个文件可能被多人频繁修改,并且每个人的维护时间都可能不会很长,不建议为文件增加 @author 标识。通过版本控制系统追踪变更,按业务逻辑单元确定模块的维护责任人,通过文档与wiki跟踪和查询,是更好的责任管理方式。

对于业务逻辑无关的技术型基础项目,特别是开源的公共项目,应使用 @author 标识。

示例:

/**
 * @author author-name([email protected])
 *         author-name2([email protected])
 * @date: when you write it
 * @description: the function of this file.
 */

TODO 注释

对那些临时的, 短期的解决方案, 或已经够好但仍不完美的代码使用 TODO 注释.

TODO 注释要使用全大写的字符串 TODO, 在随后的圆括号里写上你的大名, 邮件地址, 或其它身份标识. 冒号是可选的. 主要目的是让添加注释的人 (也是可以请求提供更多细节的人) 可根据规范的 TODO 格式进行查找. 添加 TODO 注释并不意味着你要自己来修正.

// TODO([email protected]): Use a "*" here for concatenation operator.
// TODO([email protected]) change this to use relations.

全局查询
代码评审

多人合作注释

同一个文件的代码可能被多个人修改,这个时候需要标识出谁改动了哪些部分。

格式: // add begin by 作者名 ,一个分号;,再加上原因 Reason

代码添加的最后加上: //add end

Example

// add begin by liuxing ; Init post's id
var postId = 1;
// end add

或者

// add begin by liuxing
/**
 * 多行注释来说明原因
 */
var postId = 1;
// end add

工具(插件)

参考

用网页实现移动端横向纵向列固定的表格

最终效果:

当页面横向滑动的时候,纵向上不能滚动。纵向滚动的时候,横向不能滚动。

分析

简单分析来说,页面就是上面一个position:fixed;在顶部,下面的列表的最左边一列position-x:fixed(哈哈这个属性当然是不存在的啦)。

从图上的演示来看右侧的横向滚动的是联动的,但是效果其实是一致的。那我们就看底下的列表。既可以左右,又可以上下,而且还要锁定一个方向。其实每次滚动的时候我们都只能操作一个元素,不知道大家能不能理解,就好比我们页面上有一个区域a有滚动条,当前的页面很长,也有滚动条,鼠标在区域a上滚动的时候页面是不动的,只有当区域a滚到底的时候,页面才会继续滚动。所以利用这个特性,我们创造一个叠加的滚动区域,一个overflow-y:auto;,一个overflow-x:auto。一个只能纵向滚动,一个只能横向滚动。

html解释

html结构如下,左侧列表单独盛放(固定),右侧创造一个可以滚动的区域。

<div class="table-body">
    <div class="table-body-left-fixed">
        <div class="table-td">
            <p>涨停股份</p>
            <p>888888</p>
        </div>
        <div class="table-td">
            <p>涨停股份</p>
            <p>888888</p>
        </div>
        ...
    </div>
    <div class="table-body-right">
        <div class="table-tr">
            <div class="table-td">20170912</div>
            <div class="table-td">20171010</div>
            <div class="table-td">23.4%</div>
            <div class="table-td">67.9%</div>
            <div class="table-td">-19.9%</div>
            <div class="table-td">103.90</div>
            <div class="table-td">9.12</div>
        </div>
        <div class="table-tr">
            <div class="table-td">20170912</div>
            <div class="table-td">20171010</div>
            <div class="table-td">23.4%</div>
            <div class="table-td">67.9%</div>
            <div class="table-td">-19.9%</div>
            <div class="table-td">103.90</div>
            <div class="table-td">9.12</div>
        </div>
        ...
    </div>
</div>

css解释

.table-body设置为纵向滚动,.table-body-right 设置为横向滚动。
-webkit-overflow-scrolling: touch; 是为了解决IOS滑动卡顿的问题。

.table-body {
    position: absolute;
    top: 3.5rem;
    bottom: 0;
    left: 0;
    right: 0;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
}
.table-body-right {
    position: absolute;
    left: 25vw;
    top: 0;
    right: 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

联动,优化

上面的表头是简单版的列表,只有横向滚动。所以是非常easy的。

还有一个是联动,就是上面滚动的时候,得出左侧滚动距离scrollLeft,但是只是单纯去设置thead[0].scrollLeft = e.target.scrollLeft;(表头的左侧滚动距离等于目列表的左侧滚动距离),其实是有问题的,比如在高速的操作下(what...你是机器人么)。会出现你手停下来了,出现对不齐的问题。解决的办法就是把当前的操作加入异步队列中,这样所有的操作都会被执行下来。

以上就是最近写手机模板的收获。

demo

要是所有人都能理解你,你得平庸成什么样

前端优化

前端优化主要包括:网络加载类、页面渲染类、CSS优化类、JavaScript执行类、缓存类、图片类、架构协议类等几类。

网络加载

1.减少 HTTP 资源请求次数在前端页面中,通常建议尽可能合并静态资源图片、JavaScript 或 CSS 代码,减少页面请求数和资源请求消耗,这样可以缩短页面首次访问的用户等待时间。通过构建工具合并雪碧图、CSS、JavaScript 文件等都是为了减少 HTTP 资源请求次数。另外也要尽量避免重复的资源,防止增加多余请求。

2.减小 HTTP 请求大小除了减少 HTTP 资源请求次数,也要尽量减小每个 HTTP 请求的大小。如减少没必要的图片、JavaScript、CSS 及 HTML 代码,对文件进行压缩优化,或者使用 gzip 压缩传输内容等都可以用来减小文件大小,缩短网络传输等待时延。前面我们使用构建工具来压缩静态图片资源以及移除代码中的注释并压缩,目的都是为了减小 HTTP 请求的大小。

3.将 CSS 或 JavaScript 放到外部文件中,避免使用<style><script>标签直接引入在 HTML 文件中引用外部资源可以有效利用浏览器的静态资源缓存,但有时候在移动端页面 CSS 或 JavaScript 比较简单的情况下为了减少请求,也会将 CSS 或 JavaScript 直接写到 HTML 里面,具体要根据 CSS 或 JavaScript 文件的大小和业务的场景来分析。如果 CSS 或 JavaScript 文件内容较多,业务逻辑较复杂,建议放到外部文件引入。

<link rel="stylesheet" href="//cdn.domain.com/path/main.css" >
...
<script src="//cdn.domain.com/path/main.js"></script>

4.避免页面中空的 href 和 src当标签的 href 属性为空,或<script>、、<iframe>标签的 src 属性为空时,浏览器在渲染的过程中仍会将 href 属性或 src 属性中的空内容进行加载,直至加载失败,这样就阻塞了页面中其他资源的下载进程,而且最终加载到的内容是无效的,因此要尽量避免。

<!--不推荐-->
<img src="" alt="photo" >
<a href="">点击链接</a>

5.为 HTML 指定 Cache-Control 或 Expires为 HTML 内容设置 Cache-Control 或 Expires 可以将 HTML 内容缓存起来,避免频繁向服务器端发送请求。前面讲到,在页面 Cache-Control 或 Expires 头部有效时,浏览器将直接从缓存中读取内容,不向服务器端发送请求。

<meta http-equiv="Cache-Control" content="max-age=7200">
<meta http-equiv="Expires" content="Mon,20Jul201623:00:00GMT">

6.合理设置 Etag 和 Last-Modified合理设置 Etag 和 Last-Modified 使用浏览器缓存,对于未修改的文件,静态资源服务器会向浏览器端返回304,让浏览器从缓存中读取文件,减少 Web 资源下载的带宽消耗并降低服务器负载。

<meta http-equiv="last-modified" content="Sun,05 Nov 2017 13:45:57 GMT">

7.减少页面重定向页面每次重定向都会延长页面内容返回的等待延时,一次重定向大约需要200毫秒不等的时间开销(无缓存),为了保证用户尽快看到页面内容,要尽量避免页面重定向。

8.使用静态资源分域存放来增加下载并行数浏览器在同一时刻向同一个域名请求文件的并行下载数是有限的,因此可以利用多个域名的主机来存放不同的静态资源,增大页面加载时资源的并行下载数,缩短页面资源加载的时间。通常根据多个域名来分别存储 JavaScript、CSS 和图片文件。

<link rel="stylesheet" href="//cdn1.domain.com/path/main.css" >
...
<script src="//cdn2.domain.com/path/main.js"></script>

9.使用静态资源 CDN 来存储文件如果条件允许,可以利用 CDN 网络加快同一个地理区域内重复静态资源文件的响应下载速度,缩短资源请求时间。

10.使用 CDN Combo 下载传输内容CDN Combo 是在 CDN 服务器端将多个文件请求打包成一个文件的形式来返回的技术,这样可以实现 HTTP 连接传输的一次性复用,减少浏览器的 HTTP 请求数,加快资源下载速度。例如同一个域名 CDN 服务器上的 a.js,b.js,c.js 就可以按如下方式在一个请求中下载。

<script src="//cdn.domain.com/path/a.js,b.js,c.js"></script>

11.使用可缓存的 AJAX对于返回内容相同的请求,没必要每次都直接从服务端拉取,合理使用 AJAX 缓存能加快 AJAX 响应速度并减轻服务器压力。

$.ajax({
    url : url,
    type : 'get',
    cache : true, //推荐使用缓存
    data : {},
    success (){//...},
    error (){//...}
});

12.使用 GET 来完成 AJAX 请求 使用 XMLHttpRequest 时,浏览器中的 POST 方法会发起两次 TCP 数据包传输,首先发送文件头,然后发送 HTTP 正文数据。而使用 GET 时只发送头部,所以在拉取服务端数据时使用 GET 请求效率更高。

$.ajax({
    url : url,
    type : 'get', //推荐使用get完成请求
    data : {},
    success (){//...},
    error(){//...}
});

13.减少 Cookie 的大小并进行 Cookie 隔离HTTP 请求通常默认带上浏览器端的 Cookie 一起发送给服务器,所以在非必要的情况下,要尽量减少 Cookie 来减小 HTTP 请求的大小。对于静态资源,尽量使用不同的域名来存放,因为 Cookie 默认是不能跨域的,这样就做到了不同域名下静态资源请求的 Cookie 隔离。

14.缩小 favicon.ico 并缓存 有利于 favicon.ico 的重复加载,因为一般一个 Web 应用的 favicon.ico 是很少改变的。

15.推荐使用异步 JavaScript 资源 异步的 JavaScript 资源不会阻塞文档解析,所以允许在浏览器中优先渲染页面,延后加载脚本执行。例如 JavaScript 的引用可以如下设置,也可以使用模块化加载机制来实现。

<script src="main.js" defer></script>
<script src="main.js" async></script>

使用 async 时,加载和渲染后续文档元素的过程和 main.js 的加载与执行是并行的。使用 defer 时,加载后续文档元素的过程和 main.js 的加载是并行的,但是 main.js 的执行要在页面所有元素解析完成之后才开始执行。

16.消除阻塞渲染的 CSS 及 JavaScript 对于页面中加载时间过长的 CSS 或 JavaScript 文件,需要进行合理拆分或延后加载,保证关键路径的资源能快速加载完成。

17.避免使用 CSS import 引用加载 CSS CSS 中的 @import 可以从另一个样式文件中引入样式,但应该避免这种用法,因为这样会增加 CSS 资源加载的关键路径长度,带有 @import 的 CSS 样式需要在 CSS 文件串行解析到 @import 时才会加载另外的 CSS 文件,大大延后 CSS 渲染完成的时间。

<!--不推荐-->
<style>
    @import "path/main.css";
</style>
<!--推荐-->
<link rel="stylesheet" href="//cdn1.domain.com/path/main.css" >

移动端网络加载类

移动端浏览器前端优化策略相对于桌面端浏览器,移动端 Web 浏览器上有一些较为明显的特点:设备屏幕较小、新特性兼容性较好、支持一些较新的 HTML5 和 CSS3 特性、需要与 Native 应用交互等。但移动端浏览器可用的 CPU 计算资源和网络资源极为有限,因此要做好移动端 Web 上的优化往往需要做更多的事情。首先,在移动端 Web 的前端页面渲染中,桌面浏览器端上的优化规则同样适用,此外针对移动端也要做一些极致的优化来达到更好的效果。需要注意的是,并不是移动端的优化原则在桌面浏览器端就不适用,而是由于兼容性和差异性的原因,一些优化原则在移动端更具代表性。

1.首屏数据请求提前,避免 JavaScript 文件加载后才请求数据 为了进一步提升页面加载速度,可以考虑将页面的数据请求尽可能提前,避免在 JavaScript 加载完成后才去请求数据。通常数据请求是页面内容渲染中关键路径最长的部分,而且不能并行,所以如果能将数据请求提前,可以极大程度上缩短页面内容的渲染完成时间。

2.首屏加载和按需加载,非首屏内容滚屏加载,保证首屏内容最小化由于移动端网络速度相对较慢,网络资源有限,因此为了尽快完成页面内容的加载,需要保证首屏加载资源最小化,非首屏内容使用滚动的方式异步加载。一般推荐移动端页面首屏数据展示延时最长不超过3秒。目前**联通 3G 的网络速度为 338KB/s(2.71Mb/s),所以推荐首屏所有资源大小不超过 1014KB,即大约不超过 1MB。

3.模块化资源并行下载 在移动端资源加载中,尽量保证 JavaScript 资源并行加载,主要指的是模块化 JavaScript 资源的异步加载,例如AMD的异步模块,使用并行的加载方式能够缩短多个文件资源的加载时间。

4.首屏必备的 CSS 和 JavaScript通常为了在 HTML 加载完成时能使浏览器中有基本的样式,需要将页面渲染时必备的 CSS 和 JavaScript 通过 <script><style> 内联到页面中,避免页面 HTML 载入完成到页面内容展示这段过程中页面出现空白。

<!DOCTYPE html>
<html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>样例</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <style>
    /*必备的首屏CSS*/
    html,body{
        margin:0;
        padding:0;
        background-color:#ccc;
    }
    </style>
</head>
<body>
</body>
</html>

5.meta dns prefetch 设置 DNS 预解析设置文件资源的 DNS 预解析,让浏览器提前解析获取静态资源的主机 IP,避免等到请求时才发起 DNS 解析请求。通常在移动端 HTML 中可以采用如下方式完成。

<!--cdn域名预解析-->
<meta http-equiv="x-dns-prefetch-control" content="on" >
<link rel="dns-prefetch" href="//cdn.domain.com" >

6.资源预加载 对于移动端首屏加载后可能会被使用的资源,需要在首屏完成加载后尽快进行加载,保证在用户需要浏览时已经加载完成,这时候如果再去异步请求就显得很慢。

7.合理利用MTU策略 通常情况下,我们认为 TCP 网络传输的最大传输单元(Maximum Transmission Unit,MTU)为 1500B,即一个RTT(Round-Trip Time,网络请求往返时间)内可以传输的数据量最大为 1500 字节。因此,在前后端分离的开发模式中,尽量保证页面的 HTML 内容在 1KB 以内,这样整个 HTML 的内容请求就可以在一个 RTT 内请求完成,最大限度地提高 HTML 载入速度。

页面渲染类

1.把 CSS 资源引用放到 HTML 文件顶部 一般推荐将所有 CSS 资源尽早指定在 HTML 文档 中,这样浏览器可以优先下载 CSS 并尽早完成页面渲染。

2.JavaScript 资源引用放到 HTML 文件底部 JavaScript 资源放到 HTML 文档底部可以防止 JavaScript 的加载和解析执行对页面渲染造成阻塞。由于 JavaScript 资源默认是解析阻塞的,除非被标记为异步或者通过其他的异步方式加载,否则会阻塞 HTML DOM 解析和 CSS 渲染的过程。

3.尽量预先设定图片等大小 在加载大量的图片元素时,尽量预先限定图片的尺寸大小,否则在图片加载过程中会更新图片的排版信息,产生大量的重排

4.不要在 HTML 中直接缩放图片 在 HTML 中直接缩放图片会导致页面内容的重排重绘,此时可能会使页面中的其他操作产生卡顿,因此要尽量减少在页面中直接进行图片缩放。

5.减少 DOM 元素数量和深度 HTML 中标签元素越多,标签的层级越深,浏览器解析 DOM 并绘制到浏览器中所花的时间就越长,所以应尽可能保持 DOM 元素简洁和层级较少。

<!--不推荐-->
<div>
    <span>
        <a href="javascript:void(0);">
            <img src="./path/photo.jpg" alt="图片">
        </a>
    </span>
</div>
<!--推荐-->
<img src="./path/photo.jpg" alt="图片" >

6.尽量避免在选择器末尾添加通配符 CSS 解析匹配到 渲染树的过程是从右到左的逆向匹配,在选择器末尾添加通配符至少会增加一倍多计算量。

7.减少使用关系型 样式表的写法直接使用唯一的类名即可最大限度的提升渲染引擎绘制渲染树等效率

8.尽量减少使用JS动画 JS 直接操作 DOM 极容易引起页面的重排

9.CSS 动画使用 translate、scale 代替 top、height 尽量使用 CSS3 的 translate、scale 属性代替 top、left 和 height、width,避免大量的重排计算

10.尽量避免使用<table><iframe> 内容的渲染是将 table 的 DOM 渲染树全部生成完并一次性绘制到页面上的,所以在长表格渲染时很耗性能,应该尽量避免使用它,可以考虑使用列表元素代替。尽量使用异步的方式动态添加 iframe,因为 iframe 内资源的下载进程会阻塞父页面静态资源的下载与 CSS 及 HTML DOM 的解析。

11.避免运行耗时的 JavaScript长时间运行 JavaScript 会阻塞浏览器构建 DOM 树、DOM 渲染树、渲染页面。所以,任何与页面初次渲染无关的逻辑功能都应该延迟加载执行,这和 JavaScript 资源的异步加载思路是一致的。

12.避免使用 CSS 表达式或 CSS 滤镜 CSS 表达式或 CSS 滤镜的解析渲染速度是比较慢的,在有其他解决方案的情况下应该尽量避免使用。

//不推荐
.opacity{
    filter : progid : DXImageTransform.Microsoft.Alpha( opacity = 50 );
}

缓存类

1.合理利用浏览器缓存 除了上面说到的使用 Cache-Control、Expires、Etag 和 Last-Modified 来设置 HTTP 缓存外,在移动端还可以使用 localStorage 等来保存 AJAX 返回的数据,或者使用 localStorage 保存 CSS 或 JavaScript 静态资源内容,实现移动端的离线应用,尽可能减少网络请求,保证静态资源内容的快速加载。

2.静态资源离线方案 对于移动端或 Hybrid 应用,可以设置离线文件或离线包机制让静态资源请求从本地读取,加快资源载入速度,并实现离线更新。

3.尝试使用 AMP HTMLAMP HTML 可以作为优化前端页面性能的一个解决方案,使用 AMP Component 中的元素来代替原始的页面元素进行直接渲染。

<!--不推荐-->
<video width="400" height="300" src="http://www.domain.com/videos/myvideo.mp4" 
poster="path/poster.jpg">
    <div fallback>
        <p>Your browser doesn’t support HTML5 video</p>
    </div>
    <source type="video/mp4" src="foo.mp4">
    <source type="video/webm" src="foo.webm">
</video>

<!--推荐-->
<amp-video width="400" height="300" src="http://www.domain.com/videos/myvideo.mp4" 
poster="path/poster.jpg">
    <div fallback>
        <p>Your browser doesn’t support HTML5 video</p>
    </div>
    <source type="video/mp4" src="foo.mp4">
    <source type="video/webm" src="foo.webm">
</amp-video>

4.尝试使用 PWA 模式PWA(Progressive Web Apps)是 Google 提出的用前沿的 Web 技术为网页提供 App 般使用体验的一系列方案。

图片类

1.图片压缩处理 在移动端,通常要保证页面中一切用到的图片都是经过压缩优化处理的,而不是以原图的形式直接使用的,因为那样很消耗流量,而且加载时间更长。

2.使用较小的图片,合理使用 base64 内嵌图片在页面使用的背景图片不多且较小的情况下,可以将图片转化成 base64 编码嵌入到 HTML 页面或 CSS 文件中,这样可以减少页面的 HTTP 请求数。需要注意的是,要保证图片较小,一般图片大小超过 2KB 就不推荐使用 base64 嵌入显示了。

.class-name{
    background-image : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAALCAMAAABxsOwqAAAAYFBMVEWnxwusyQukxQudwQyZvgyhxAyfwgyxzAsUHQGOuA0aJAERGAFIXwSTugyEqgtqhghQZgUwQQIpOQKbuguVtQuKrAuCowp2kQlheghTbQZHWQU7SwVAVgQ6TgQlLwMeKwFOemyQAAAAVElEQVQI1y3JVRaAIAAF0UconXbvf5ei8HfPDIQQhBAAFE10iKig3SLRNN4SP/p+N08VC0YnfIlNWtqIkhg/TPYbCvhqdHAWRXPZSp3g3CWZvVLXC6OJA3ukv0AaAAAAAElFTkSuQmCC');
}

3.使用更高压缩比格式的图片 使用具有较高压缩比格式的图片,如 webp(需要设计降级兼容方案)等。在同等图片画质的情况下,高压缩比格式的图片体积更小,能够更快完成文件传输,节省网络流量。

<img src="//cdn.domain.com/path/photo.webp" alt="webp格式图片" >

4.图片懒加载 为了保证页面内容的最小化,加速页面的渲染,尽可能节省移动端网络流量,页面中的图片资源推荐使用懒加载实现,在页面滚动时动态载入图片。

<img data-src="//cdn.domain.com/path/photo.jpg" alt="懒加载图片" >

5.使用 MediaQuery 或 srcset 根据不同屏幕加载不同大小图片在介绍响应式的章节中我们了解到,针对不同的移动端屏幕尺寸和分辨率,输出不同大小的图片或背景图能保证在用户体验不降低的前提下节省网络流量,加快部分机型的图片加载速度,这在移动端非常值得推荐。

6.使用 iconfont 代替图片 图标在页面中尽可能使用 iconfont 来代替图片图标,这样做的好处有以下几个:
- 使用 iconfont 体积较小,而且是矢量图,因此缩放时不会失真;
- 可以方便地修改图片大小尺寸和呈现颜色。
- 但是需要注意的是,iconfont 引用不同 webfont 格式时的兼容性写法,根据经验推荐尽量按照以下顺序书写,否则不容易兼容到所有的浏览器上。
css @font-face{ font-family:iconfont; src:url("./iconfont.eot"); src:url("./iconfont.eot?#iefix") format("eot"), url("./iconfont.woff") format("woff"), url("./iconfont.ttf") format("truetype"); }

7.定义图片大小限制 加载的单张图片一般建议不超过 30KB,避免大图片加载时间长而阻塞页面其他资源的下载,因此推荐在 10KB 以内。如果用户上传的图片过大,建议设置告警系统,帮助我们观察了解整个网站的图片流量情况,做出进一步的改善。

8.强缓存策略 对于一些「永远」不会变的图片可以使用强缓存的方式缓存在用户的浏览器上。

脚本类

1.尽量使用id选择器 选择页面 DOM 元素时尽量使用 id 选择器,因为 id 选择器速度最快。

2.合理缓存DOM对象 对于需要重复使用的 DOM 对象,要优先设置缓存变量,避免每次使用时都要从整个DOM树中重新查找。

//不推荐
$('#mod.active').remove('active');
$('#mod.not-active').addClass('active');

//推荐
let $mod=$('#mod');
$mod.find('.active').remove('active');
$mod.find('.not-active').addClass('active');

3.页面元素尽量使用事件代理,避免直接事件绑定使用事件代理可以避免对每个元素都进行绑定,并且可以避免出现内存泄露及需要动态添加元素的事件绑定问题,所以尽量不要直接使用事件绑定。

//不推荐
$('.btn').on('click',function(e){
    console.log(this);
});

//推荐
$('body').on('click','.btn',function(e){
    console.log(this);
});

4.使用 touchstart 代替 click由于移动端屏幕的设计, touchstart 事件和 click 事件触发时间之间存在 300 毫秒的延时,所以在页面中没有实现 touchmove 滚动处理的情况下,可以使用 touchstart 事件来代替元素的 click 事件,加快页面点击的响应速度,提高用户体验。但同时我们也要注意页面重叠元素 touch 动作的点击穿透问题

//不推荐
$('body').on('click','.btn',function(e){
    console.log(this);
});

//推荐
$('body').on('touchstart','.btn',function(e){
    console.log(this);
});

5.避免 touchmove、scroll 连续事件处理 需要对 touchmove、scroll 这类可能连续触发回调的事件设置事件节流,例如设置每隔 16ms(60 帧的帧间隔为 16.7ms,因此可以合理地设置为 16ms )才进行一次事件处理,避免频繁的事件调用导致移动端页面卡顿。

//不推荐
$('.scroller').on('touchmove','.btn',function(e){
    console.log(this);
});

//推荐
$('.scroller').on('touchmove','.btn',function(e){
    let self=this;
    setTimeout(function(){
        console.log(self);
    },16);
});

6.避免使用 eval、with,使用 join 代替连接符+,推荐使用 ECMAScript6 的字符串模板这些都是一些基础的安全脚本编写问题,尽可能使用较高效率的特性来完成这些操作,避免不规范或不安全的写法。

7.尽量使用 ECMAScript6+的特性来编程 ECMAScript6+ 一定程度上更加安全高效,而且部分特性执行速度更快,也是未来规范的需要,所以推荐使用 ECMAScript6+ 的新特性来完成后面的开发

渲染类

1.使用 Viewport 固定屏幕渲染,可以加速页面渲染内容 一般认为,在移动端设置 Viewport 可以加速页面的渲染,同时可以避免缩放导致页面重排重绘。在移动端固定 Viewport 设置的方法如下。

<!--设置viewport不缩放-->
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">

2.避免各种形式重排重绘 页面的重排重绘很耗性能,所以一定要尽可能减少页面的重排重绘,例如页面图片大小变化、元素位置变化等这些情况都会导致重排重绘。

3.使用 CSS3 动画,开启GPU加速使用 CSS3 动画时可以设置 transform:translateZ(0) 来开启移动设备浏览器的GPU图形处理加速,让动画过程更加流畅,但需要注意的是,在 Native WebView 下 GPU 加速有几率产生 App Crash。

-webkit-transform:translateZ(0);
-ms-transform:translateZ(0);
-o-transform:translateZ(0);
transform:translateZ(0);

4.合理使用 Canvas 和 requestAnimationFrame选择 Canvas 或 requestAnimationFrame 等更高效的动画实现方式,尽量避免使用 setTimeout、setInterval 等方式来直接处理连续动画。

5.SVG 代替图片 部分情况下可以考虑使用 SVG 代替图片实现动画,因为使用 SVG 格式内容更小,而且 SVG DOM 结构方便调整。

6.不滥用 float 在 DOM 渲染树生成后的布局渲染阶段,使用 float 的元素布局计算比较耗性能,所以尽量减少 float 的使用,推荐使用固定布局或 flex-box 弹性布局的方式来实现页面元素布局。

7.不滥用 web 字体或过多 font-size 声明 过多的 font-size 声明会增加字体的大小计算,而且也没有必要的。

8.做好脚本容错 脚本容错可以避免「非正常环境」的执行错误影响页面的加载和不相关功能的使用

架构协议类

1.尝试使用 SPDY 和 HTTP2 在条件允许的情况下可以考虑使用 SPDY 协议来进行文件资源传输,利用连接复用加快传输过程,缩短资源加载时间。HTTP2 在未来也是可以考虑尝试的。

2.使用后端数据渲染 使用后端数据渲染的方式可以加快页面内容的渲染展示,避免空白页面的出现,同时可以解决移动端页面SEO的问题。如果条件允许,后端数据渲染是一个很不错的实践思路。

3.使用 NativeView 代替 DOM 的性能劣势 可以尝试使用 NativeView 的 MNV* 开发模式来避免 HTML DOM 性能慢的问题,目前使用 MNV* 的开发模式已经可以将页面内容渲染体验做到接近客户端 Native 应用的体验了。但需要避免 js Framework 和 native Framework 的频繁交互。

参考

获取id元素的“又”一种方法

获取id元素的“又”一种方法

今天在偶然看到某大在掘金上面发了一篇文章underscore 系列之如何写自己的 underscore,渣渣的我就好奇的点进去看了起来。。。

在关于 导出 的地方看到了

typeof exports != 'undefined'

这样一句。

纳尼?exports可以直接取到页面中的id为exports的元素。

脑洞巨大的我抛下文章主要内容去查这个问题了。。。

首先自己试验了一下 demo

<div id="exports"></div>
<script>
    alert(window.document.getElementById('exports') == window.exports);
</script>

在ie下下面也能完美运行。。

问题来了,难道大家都不知道这个方法吗?还是这个方法有什么弊端,大家都避而不用?

果然!segmentfault - 疑惑,原生JS中可以直接使用ID名称来获取元素,而不用使用getElementById()方法?

someone say:

这个最初是 IE 里面的,后来 firefox chrome 好像也支持了。
不建议使用,这个不是标准里面的,将来不一定支持。
而且代码容易写混乱了,multiNavItem1【id】 属于全局作用域,而且你可以给他赋值,赋值之后就是那个新的值,不赋值就是那个元素的值,当有些 id 赋了值有些没有,那么有些就是这个 DOM 对象,有些不是,特别容易混乱了。

本来看看v8的源码,发现我还是入门级别的,大家都不推荐看。我还是老老实实的打基础的吧。

水平垂直居中

水平居中

  1. 若是行内元素,给改元素的父级设置text-align:center,即可实现行内元素水平居中。demo

  2. 若是块级元素, 该元素设置margin:0 autodemo

  3. 若子元素包含float:left属性, 为了让子元素水平居中, 则可让父元素宽度设置为fit-content,并且配合margin, 作如下设置:demo

    .fit-content {
        width: -moz-fit-content;
        width: -webkit-fit-content;
        width: fit-content;
        margin: 0 auto;
    }

    目前这个属性只支持Chrome和Firefox浏览器。

  4. 使用flex布局,可以很轻松的实现水平居中:demo

    .parent {
        display: flex;
        justify-content: center;
    }
    .son {
        background-color: red;
        width: 100px;
        height: 20px;
    }

    .son 将会被水平居中

  5. **使用CSS3盒模型,父元素display:box;box-pack:center;

    .parent {
        display: -webkit-box;
        -webkit-box-orient: horizontal;
        -webkit-box-pack: center;
    
        display: -moz-box;
        -moz-box-orient: horizontal;
        -moz-box-pack: center;
    
        display: -o-box;
        -o-box-orient: horizontal;
        -o-box-pack: center;
    
        display: -ms-box;
        -ms-box-orient: horizontal;
        -ms-box-pack: center;
        
        display: box;
        box-orient: horizontal;
        box-pack: center;
    }
    .son {
        width: 100px;
        height: 10px;
        background-color: red;
    }

    没有深入了解。
    基本介绍:display:box;是09年出来的。display: flex;是12年出来的。地址:“Old” Flexbox and “New” Flexbox
    看文章说在手机页面的时候,老机子display:flex会有问题的时候就需要box上场啦。

  6. 通过使用决定对位,以及负值的margin-left来实现:demo

    .parent {
        position: relative;
    }
    .son {
        position: absolute;
        left: 50%;
        margin-left: -0.5 * 当前元素的宽度; 
        width: 100px;
        height: 10px;
        background-color: red;
    }
  7. 使用CSS3中新增的transform属性,以及绝对定位:demo

    .parent {
        position: relative;
    }
    .son {
        position: absolute;
        left: 50%;
        transform: translate(-50%, 0);
    }
  8. 使用绝对定位,以及left:0;right:0;margin:0 auto;demo

    .parent {
        position: relative;
    }
    .son {
        position: absolute;
        left: 0;
        right: 0;
        margin: 0 auto;
        width: 100px;
        height: 10px;
        background-color: red;
    }

垂直居中

  1. 元素是单行文本,设置line-height等于父元素的高度。demo

  2. 元素是行内块级元素, 基本**是使用display: inline-block, vertical-align: middle和一个伪元素让内容块处于容器**。demo

    .parent {
        height: 100px;
    }
    .parent::after, .son{
        display:inline-block;
        vertical-align:middle;
    }
    .parent::after{
        content:'';
        height:100%;
        /*width: 10px;*/
        /*background-color: blue;*/
    }
    .son {
        width: 100px;
        height: 10px;
        background-color: red;
    }

    通过父元素创建一个看不见的伪类(宽度为0),高度为100%,同时设置为inline-blockvertical-align:middle使元素垂直居中。
    这是一种很流行的方法, 也适应IE7。

  3. 可用vertical-align属性,而vertical-align只有在元素为td或者th时,才会生效,对于其他块级元素,例如divp等,默认情况是不支持的。为了使用vertical-align,我们需要设置父元素display:table-cell;vertical-align:middledemo

    .parent {
        height: 100px;
        display: table-cell;
        vertical-align: middle;
    }
    .son {
        width: 100px;
        height: 10px;
        background-color: red;
    }
  4. 使用flex布局,align-items: center;: demo

    .parent {
        height: 100px;
        display: flex;
        align-items: center;
    }
    .son {
        width: 100px;
        height: 10px;
        background-color: red;
    }
  5. 使用CSS3盒模型 demo

    .parent {
        height: 100px;
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-box-pack: center;
        
        display: -moz-box;
        -moz-box-orient: vertical;
        -moz-box-pack: center;
    
        display: box;
        box-orient: vertical;
        box-pack: center;
    }
  6. 通过使用决定对位,以及负值的margin-top来实现:demo

    .parent {
        position: relative;
        height: 100px;
    }
    .son {
        position: absolute;
        top: 50%;
        margin-top: -0.5 * 高度的一半; 
        width: 100px;
        height: 10px;
        background-color: red;
    }
  7. 使用CSS3中新增的transform属性,以及绝对定位:demo

    .parent {
        position: relative;
        height: 100px;
    }
    .son {
        position: absolute;
        top: 50%;
        transform: translate(0, -50%);
        width: 100px;
        height: 10px;
        background-color: red;
    }
  8. 设置父元素相对定位position:relative,子元素如下css样式:demo

    .parent {
        position: relative;
        height: 100px;
    }
    .son {
        position: absolute;
        top: 0;
        bottom: 0;
        margin: auto 0;
        width: 100px;
        height: 10px;
        background-color: red;
    }

水平垂直居中

  1. flex: demo

    .parent {
        height: 100px;
        display: flex;
        justify-content: center;
        align-items: center;
    }
  2. 绝对定位 + margin: demo

    .parent {
        position: relative;
        height: 100px;
    }
    .son {
        position: absolute;
        top: 50%;
        left: 50%;
        margin-left: -0.5 * 宽度;
        margin-top: -0.5 * 高度;
        width: 100px;
        height: 10px;
        background-color: red;
    }
  3. 绝对定位 + transform : demo

    .parent {
        position: relative;
        height: 100px;
    }
    .son {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 100px;
        height: 10px;
        background-color: red;
    }
  4. 绝对定位 + margin: auto : demo

    .parent {
        position: relative;
        height: 100px;
    }
    .son {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        margin: auto;
        width: 100px;
        height: 10px;
        background-color: red;
    }
  5. table + margin:auto : demo

    .ancestor {
        display: table;
        width: 100%;
        border: 1px solid blue;
    }
    .parent {
        height: 100px;
        display: table-cell;
        vertical-align: middle;
        border: 1px solid red;
    }
    .son {
        margin: auto;
        width: 100px;
        height: 10px;
        background-color: red;
    }
  6. display:inline-block;vertical-align:middle; : demo

    .parent {
        height: 100px;
        text-align: center;
    
        border: 1px solid red;
    }
    .parent::after {
        content:'';
        height:100%;
        display:inline-block;
        vertical-align:middle;
    }
    .son {
        display:inline-block;
        vertical-align:middle;
        
        width: 100px;
        height: 10px;
        background-color: red;
    }

分析

  • flex
    • 基本可以完成任何复杂的布局,
    • 兼容性ie11+
    • 不同浏览器需要前缀
    • 渲染的性能
  • 绝对定位
    • + margin 设置可以完美的兼容ie6,缺点是子元素宽高固定。
    • + transform 兼容ie11+,但是自由度上是最佳的。

参考

谈一谈一年来的经历

生活篇

去年的四月底(201604),我和我的室友(我羊),带着一个包和一千块钱去往了宁波到杭州的路途。当时住在我高中同学租的小和山那边的居民房里,那时候手里也比较拮据,生活用品都是两个人一起用的,当时还想着可能是场持久战,看什么时候能找到工作吧。一个星期还是一个月?

每天晚上我们都会花时间在学习今天面试的内容和投简历上,第二天一早我们就会出门,因为面试总是会被排的满满当当的。每天早上从小和山出来的时候,公交车总是异常的挤,想来大城市就是有这么多怀揣这梦想的打工者吧。中午的时候吃饭就是看运气了,得找一家看起来不贵的店进去吃,不然怕是熬不住了。晚上的时候我和我羊要是面试完离得近,我们就会约着见面一起,要么就是回去再吃。我们住的地方附近就有一个大学,附近的垃圾街伙食还是挺实惠的。

找工作期间,志鹏(隔壁班的小伙伴,之前已经在杭州找到工作了)还来找我们一起吃过饭,大家一起聊聊天,感觉又回到了大学读书的时候,没有辛苦,只有梦想。

幸福来的总是很快,第三天晚上的时候,我收到了同花顺的offer,第四天也收到了两个offer。我羊也收到了两三个offer,我们那天晚上还出去吃了一顿杨国福麻辣烫。第一次吃杨国福,点了二十二块,这一碗贼大,吃了一半就吃不下了,这种计价模式真是让人害怕啊!(你得知道你手里有几斤几两 )

找房子的时候和我羊意见不一致,结果就分开住了。现在想来当时真的是非常的不明智啊!那时候每天加班,下班的时候有没有去我那边的公交和班车,每天下班就是骑着公共自行车回去,下雨天就打车回去,感觉得不偿失,心一横,浪费了一个月的押金。搬到了公司附近住,价格和原来的差不多。

之后的生活犹如止水一般,平淡但又充满惊喜,见到了许多宁波的大学同学。毕业散伙饭上,大家各自诉说这个对于我们陌生又好玩的世界的一点理解和抱怨。但我们的心一直在路上...

工作篇

去年五月份入职,在同花顺已经一年多了,到现在差不多也是老员工了(人员流动太大了),通过面试php入职,在10月份正式转了前端,开始了前端填坑之路。

刚转前端的时候,楠姐对我挺不满意的(自知之明还是有的)。啥也不会,就从切图开始一点点开始。之后老贾带着我做了level2首页,那是我第一次接触seajs。学会简单使用后的的我,欣喜诺狂(不知道你能否理解,说多了害羞⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄)。

之后一位我很佩服的同事(国梁兄)离开了,他给了我很多中肯的建议,我愿意学,他愿意传授,多么美好的场景。他走后,我接手了他的任务和芦荟一起合作。哇!require + backbonejs + sass + jade。其实之前,策策和我是两个候选人,我厚着脸皮主动接了。这么一堆高级的东西,让我压力也很大,周末的时候我拼命的看了两天的视频和教程,周一直接开始干,之后芦荟也给了我很大的帮助,一周多点顺利的交付了测试。

在之后的很长的一段时间里面我又学习了gulp,ie6的兼容等,完成了项目。照理来说,我应该很快能成为技术大牛,但是...

我一直得意于有机会参与一些需要类似高端技术的项目,但完成之后,我一直没有总结,或没有深入的了解,学习浅藏辄止。让我以为我已经会了,仅仅是会了。

直到今年三月份的时候,我开始沉下心,进行条理性的学习,从前端的基础(html、css、js)、ps如何切图,一些简单的性能优化等(学习的内容是我去年九月份花了1000块报名的前端微专业,当时觉得特别坑,后来仔细的学习之后还是有很多干货的)。整理成文档传到了github上,之后只要使用任何技术点,基本上都会整理到到这个上面。

去年底的时候来了个新同事,现在算是我比较铁的哥们了。给我的感觉就是靠谱,虽然比我小,但是他的基础很好,平常遇到问题的时候我们经常会讨论。在他身上学会了很多东西,他也会发现我的问题,给我指出来。

六月份的时候,客户端内核升级开始,把所有的项目都迁到chrome下,考虑到以后可以不用兼容。在团队内准备引入vuejs。第一个项目应该是api管理平台,和老贾一起合作的。那时候状态特别好,晚上回去看视频和教程,第二天把学习到的内容运用到项目中,或改进之前的问题。花了两期两周的时间完成。这应该算是正式转向现在技术栈的一次尝试了,之前的工作流都是依赖jQuery的一种工作模式,那时候我们还写了很多组件为了提高工作效率。

八月份的时候,楠姐将离开我们四个月,孕育小宝宝。留下了我们一帮人,但是这段时间里,产品那边需求少了很多,工作安排比以前宽裕了很多,一般八点就能差不多回家了。就我来说,以前基本九点之后才能回家。这段时间我开始加强我的js基础,css动画,svg等方面的技能。同时开始了THink前端平台,现在还未完成。主要是为了前端方面的内部需求,同时也加强了我对于vue的理解。

十月份的时候,开始了金融大师手机app的项目,开始做手机页面,使用reactjs+and,写h5页面也稍有心得。

做前端已经一年整了,现在的我回头看当时的我,走了很多弯路,但是这确实是我想走的路。这是我赖以生存的技能,也是我的爱好,创造一个不一样的世界呈现给众人。接下去的一年将会给我更大的挑战,我也会挑战更大的困难。毕竟我不是一个人了...

vuejs 项目小结(一)

许久没有写vue了,前几天有人问我问题,概念都有些理不清楚了。。
项目快完成,总结一下。从最基础的开始,重现我遇到的问题和一些细节问题。

项目效果图



现实分析:

  1. 上方一个搜索框,输入的时候获取数据。点击加入到右侧的列表中,叠加品种数量+1
  2. 左侧默认有两个树状结构图,点击根展开收起,点击子节点,加入右侧列表。
  3. 右侧点击删除按钮删除选项,选中数量-1
  4. 超过6个的时候显示tip。

实现分析:

  1. 把各个部分拆分成组件。
    1. topbar 表头组件
    2. searchbox 搜索框组件
    3. selectleftbox 左侧页面组件
    4. singletree 单支树状组件
    5. selectrightbox 右侧页面组件
    6. tip 组件
  2. 状态跨多个组件 使用vuex来实现数据统一管理
  3. 不使用图片图标 iconfont上下载svg图标

开始

使用vue-cli创建vuejs目录结构

npm install vue-cli -g
vue init webpack vue-test
cd vue-test
npm install
npm install vuex --save
npm run dev

(一) 项目安装的时候,其实是不用路由的,但是手贱的我一不小心安装了,要如何不显示/#/这些难看的链接hash呢?

  1. 最简单的方式就是去除入口文件man.js 中的router的引入和调用的地方
// import router from './router'

new Vue({
    el: '#app',
    // router,
    store,
    template: '<App/>',
    components: { App }
})
  1. 还有一种也是可以实现的,就是在/router/index.js 中修改路由模式
import Vue from 'vue'
import Router from 'vue-router'
// import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
    mode: 'history',
    routes: [
        {
            path: '/',
            // name: 'HelloWorld',
            // component: HelloWorld
        }
    ]
})

把模式改成mode: 'history' ,在默认首页就不会出现hash值了,但是这可能不像想象中简单,还需要服务端配置。详细:链接
所以还是用第一种吧。 2333

(二)使用svg资源

先去http://www.iconfont.cn/找到类似图标按钮 不在乎大小和颜色。

添加入库。选完后点击购物车按钮,把所有的图标添加到项目中(没有可以新建一个)。到项目页面 点击编辑图标,可以修改图标的位置大小颜色。保存后下载svg。

把svg放置到项目assets文件夹(静态资源)下,组件中使用img标签引入svg文件。

还可以使用background属性引入。(奇怪,我开发的时候明明不能用,/(ㄒoㄒ)/~~ 现在居然可以了,还以为是个bug呢,算了,之后如果遇到再说)

我们引入svg难道就仅仅只是当做背景使用的吗?当然不是!!!

应该还还可以直接直接控制颜色的变化,但是试了半天没效果,发现了其他引入的方式。

// fn1
<object :data="addBtn" type=""></object>

import addBtn from '@/assets/add.svg’

// fn2
<object :data=“require(./assets/add,svg)" type=""></object>

(三)组件的编写

组件是vue的核新内容,vue推崇的是全部使用组件的方式构建页面。
下面是tip组件的基本内容。

<template>
    <div class="tip">
        <img src="../assets/info.svg" alt="info" class="tip-info">
        <span>{{message}}</span>
    </div>
</template>

<script>
import Store from '@/store'

export default {
    props: {
        msg: {
            type: String,
            default: ''
        }
    },
    data () {
        return {
            message: this.msg
        }
    }
}
</script>

<style scoped>
/* 样式 */
</style>

组件基本功能就是传入tip文字,显示文字。就是这么简单,props中定义了传参的参数的类型和默认值,可以直接使用this.参数来调用。但是我们一般不直接使用参数,而是把参数赋值给当前组件的一个变量,因为参数的内容是不可更改的,所以防止出现失误,所以赋值之后,使用被赋值的变量进行操作。

(四)跃动的组件。。

运行实例我们可以发现tip组件的是有动画效果的,从上方落下渐显,过1.5秒后,当前位置落下渐逝,效果是不是很酷。

我们来分析一下:

其实我们主要使用的是vue的内置组件

参数name=“fall” fall是我们自己定义的一个动画的名称。同时我们要在样式中增加,如:

.fall-enter {
    opacity: 0;
    transform: translateY(-50px);
}
.fall-enter-active {
    transition: all .5s;
}
.fall-leave {
}
.fall-leave-active {
    transition: all .5s;
    transform: translateY(50px);
    opacity: 0;
}

.name-enter 代表进入之前的状态
.name-enter-active 代表进入的状态
.name-leave 离开之前的状态
.name-leave-active 离开的状态

借用一张图片说明,这个是一个渐显到渐逝的过程。绝大部分v-enter-active(进入的状态)和 v-leave(离开之前的状态)其实是一样的,所以v-leave就不用写了,只要控制好其他的三个状态就可以了。这里面需要用到transition属性的地方是active(激活)的时候。为什么是这样呢?你可以审查一下元素发现,内置组件<transition>的主要作用就是把这四个状态(类)按照约定好的触发状态添加和删除。至此我们动画就可以动起来了。

拓展(其他参数):

  • name - string,用于自动生成 CSS 过渡类名。例如:name: 'fade' 将自动拓展为.fade-enter,.fade-enter-active等。默认类名为 "v"
  • appear - boolean,是否在初始渲染时使用过渡。默认为 false。
  • css - boolean,是否使用 CSS 过渡类。默认为 true。如果设置为 false,将只通过组件事件触发注册的 JavaScript 钩子。
  • type - string,指定过渡事件类型,侦听过渡何时结束。有效值为 "transition" 和 "animation"。默认 Vue.js 将自动检测出持续时间长的为过渡事件类型。
  • mode - string,控制离开/进入的过渡时间序列。有效的模式有 "out-in" 和 "in-out";默认同时生效。
    还有一些事件,可以在动画发生之前和之后触发,让动画的控制更加细节。

官网详细说明

(五)vuex统一的数据管理

安装完vuex之后,项目比较简单,所以我们在入门文件main.js同级建了一个store.js的文件。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
export default new Vuex.Store({
    state: {
        num:1
    },
    mutations: {
    }
})

main.js 引入和把store中的内容作为实例的参数传入。

import store from './store'
new Vue({
    el: '#app',
    store,
    template: '<App/>',
    components: { App }
})

组件中使用store可以通过

import Store from '@/store'

来使用store中的数据,但这样是有点多余的,因为Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中,可以直接在组件中使用$store.state.num 获取到num的值。

Vuex.store中的:
state 用于数据(状态)的存储。 Vuex 使用单一状态树。我们是不能操作state中的数据的。

mutation 是唯一能操作修改state的方法。我们通过调用我们自定义的mutation方法,修改state。

getter 用于获取数据,虽然state不能修改,但是获取数据state是可以的,getter返回的数据是可以定义一些逻辑在里面的。例如筛选出num大于0的数据。

action 类似于mutation,mutation必须是同步函数,虽说如此但是我tip的显示隐藏状态是放在mutation中设了一个定时器(异步)去设置隐藏状态,也是可以的。在下文的时候修改一下。

Module 是防止store太大,不便管理而设置的。

这次我们拿右侧选择框来做演示。
右侧的选中数据来自左侧选择框中点击添加而来,首先数据被添加到store中,右侧发现数据更新了,立即渲染新的数据。
如何设置呢?

// data
selectList: this.$store.state.selectData,

这样就能拿到数据进行渲染啦。
点击左侧添加到右侧。
同理我们设置了

// data
isShowDelAllBtn: this.$store.state.selectData.length > 0

用于渲染当有数据的时候就显示删除全部的按钮,但是失效了???
渲染的数据一旦被处理之后返回就不再有“数据双向绑定”的特性了,个人猜测。

所以vuex给出一个解决方案:
mapState 辅助函数
当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性
直接贴代码:

import { mapState } from  'vuex'
// ...
computed: mapState({
    isShowDelAllBtn: state => state.selectData.length > 0
})

mapstate中定义的计算属性isShowDelAllBtn直接可以在组件中使用 默认带一个参数state,可以直接使用state中的方法和属性

总结

先分享这么几点,好久没碰了,之后加深理解之后不断优化。加油! happy hacking!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.