├── .gitattributes
├── git-install_images
├── git-install.png
└── git-install1.png
├── backbone_view_images
└── backbone_view.png
├── mysql_character.md
├── jq_framework.md
├── web_browser_loadpage.md
├── js_sliderPhotoPlugin.md
├── 2016_summary.md
├── js_stringOper.md
├── css_position.md
├── mobile_gesture.md
├── css_clear.md
├── js_info_trans.md
├── css_vfm.md
├── html_dbody.md
├── css_formattingContext.md
├── js_compileRun.md
├── web_nwjs.md
├── git.md
├── backbone_01.md
├── html_secure.md
├── README.md
├── git-basic.md
├── js_algorithom.md
├── mobile_viewport.md
├── react_dom.md
├── css_margin_collapse.md
├── html_dtd.md
├── js_object.md
├── css_shadow.md
├── js_domReady.md
├── js_cookie.md
├── framekiller.md
├── html5_canvas_screenclip.md
├── css_line_height.md
├── react_diff.md
├── web_gulp.md
├── js_designpattern.md
├── preview.md
├── git-install.md
├── js_scope.md
├── css_box_model.md
├── expand_more.md
├── css_cascade_style_sheet.md
├── js_executionContext.md
├── js_treeview_plugin.md
├── web_history.md
├── js_arrAlgortithm.md
├── js_moduleManage.md
├── js_closureFunc.md
├── web_lnmp_wordpress.md
├── h5_postMessage.md
├── backbone_events.md
├── js_prototype.md
├── css_transition.md
├── css_visual_formatting_model.md
├── CSS_animation.md
├── css_transform.md
├── html_dom_2.md
├── mobile_touch.md
├── html-css-style-guide.md
├── web_cross_domain.md
└── html_columns.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | *.html linguist-language=JavaScript
3 | *.md linguist-language=JavaScript
4 |
--------------------------------------------------------------------------------
/git-install_images/git-install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emthink/javascript_notes/HEAD/git-install_images/git-install.png
--------------------------------------------------------------------------------
/git-install_images/git-install1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emthink/javascript_notes/HEAD/git-install_images/git-install1.png
--------------------------------------------------------------------------------
/backbone_view_images/backbone_view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emthink/javascript_notes/HEAD/backbone_view_images/backbone_view.png
--------------------------------------------------------------------------------
/mysql_character.md:
--------------------------------------------------------------------------------
1 | # MySQL编码设置
2 | MySQL是使用最多的数据库之一,我们开发使用MySQL数据库时,经常会出现中文乱码的问题,本篇就本人开发实际经验介绍解决方法。MySQL的默认编码是latin1,不支持中文,需要我们手动将其设置为utf-8。
3 |
4 | 
5 |
6 | ## Windows环境
7 |
8 | - 关闭mysql服务
9 |
10 | 通过cd命令进入mysql安装目录下,执行net stop mysql命令:
11 |
12 |
--------------------------------------------------------------------------------
/jq_framework.md:
--------------------------------------------------------------------------------
1 | # jQuery
2 |
3 | jQuery是继prototype之后又一个优秀的Javascript框架。它是轻量级的js库,jQuery使用户能更方便地处理HTML(标准通用标记语言下的一个应用)、events、实现动画效果,并且方便地为网站提供AJAX交互。
4 |
5 | ## jQuery整体架构
6 |
7 | 
8 | *注:此图来自慕课。*
9 |
10 | jQuery从其功能实现上大致可分为五部分:选择器,DOM操作,事件处理,Ajax交互,动画。
11 |
--------------------------------------------------------------------------------
/web_browser_loadpage.md:
--------------------------------------------------------------------------------
1 | # 浏览器页面加载深入学习
2 |
3 | 作为一名前端开发者,我们最常面对的开发环境就是浏览器了,如果我们不了解浏览器是如何加载页面的,是不可能对前端开发及优化有比较深刻的理解及实践的。本篇将深入学习总结浏览器加载页面的过程。
4 |
5 | 当我们在浏览器地址栏输入一个网址url以后,浏览器加载页面的过程大致可分为如下几个步骤:
6 |
7 | ## 解析域名
8 |
9 | 浏览器需要知道我们访问的网站的IP地址,才能与网站进行通信。浏览器根据我们输入的网址url向DNS服务器发送一个包含域名的请求,DNS服务器返回对应的IP地址。
10 |
11 |
12 | ## 发起请求
13 |
14 | 在获取到网站IP后,浏览器将向上一步获取到的IP地址的主机发起TCP连接,发送请求,请求包含网址、浏览器信息、所有的cookie等相关信息。
15 |
16 |
17 | ## 下载响应
18 |
19 | 发起请求后,等待服务器返回响应响应。响应到达后,浏览器将解析HTML并识别出里面包含的相关资源,随后开始获取资源。
20 |
21 | ## 渲染页面
22 |
23 | 下载响应后,浏览器开始渲染页面,一般,在页面中的CSS文件和JavaScript脚本文件加载和解析并执行完脚本后,才渲染页面。
--------------------------------------------------------------------------------
/js_sliderPhotoPlugin.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: New Post
4 | permalink: new-page.html
5 | description: Some Description
6 | date: 2016-01-13 21:39:58 +08:00
7 | tags: "some tags here"
8 | ---
9 | # JavaScript之图片缩略展示sliderPhotoPlugin插件实现
10 |
11 | 本篇为实现一个相册的缩略图展示插件,使用该插件后,可以点击相册任意一张图片进入相册缩略展示,并且初始定位于所选中图片,插件上部为大图展示,下部为小图预览,可点击左右按钮进行图片选择。
12 |
13 | **效果如图:**
14 |
15 | 
16 |
17 | [sliderPhotoPlugin插件演示点此进入](http://jhssdemo.duapp.com/demo/js_sliderphotoplugin/index.html)
18 |
19 | ## API说明
20 |
21 | ```
22 |
23 |
24 | ```
25 |
--------------------------------------------------------------------------------
/2016_summary.md:
--------------------------------------------------------------------------------
1 | # 2016年终总结与2017展望
2 |
3 | 转眼2016即将过去,时光飞快,即将进入毕业后的第二个年头,昨天终于抢到了回家的车票,开心(博主的家在遥远的江西😉),也是时候对2016进行总结并展望2017了。
4 |
5 | ## 回首2016
6 |
7 | 回首2016,5月来到搜狐手搜团队,如今已有大半年,在手搜学到很多,工作状态感觉良好,其他暂且不细数,主要从个人学习,发展方面总结。
8 |
9 | - 1月使用GitPage搭建个人博客;
10 | - 5月,将博客从GitPage迁移部署到个人服务器,博客使用LNMP环境;对Linux系统操作,Ngnix代理配置,有了更多的了解;
11 | - 全年产出博客40余篇,保证每篇都有内容,不曾注水:主要包括从工作,日常学习过程中产生的灵感,深入CSS,JavaScript基础,初步介绍大多数ES6特性,还有Backbone,React两个专题;
12 | - 12月,个人订阅号认证完成,并配置好服务器,使用NodeJs开发服务提供简单的消息处理;
13 | - 搭好webpack + es6 + react开发环境并开始开发微信订阅号内网页;
14 | - 了解前端自动化测试
15 |
16 | ## 展望2017
17 |
18 | 在2017年除了工作上需要实现既定目标,达到一定程度的提升,个人学习和发展主要有以下任务:
19 |
20 | - 博客产出保持现有水平,保证全年产出40篇以上(注水不计入);
21 | - webpack + es6 + react开发微信订阅号内网页;
22 | - 个人订阅号与博客内容共享,实现每日文章推送与订阅号内浏览;
23 | - 产出更多React实践内容;
24 | - 推出一个Git由浅入深专题,对Git进行更深入的学习;
25 | - 深入学习ES6,并投入实践;
26 | - 探索前端自动化测试
27 |
28 | 预祝大家2017工作顺利,新年快乐。
--------------------------------------------------------------------------------
/js_stringOper.md:
--------------------------------------------------------------------------------
1 | # JavaScript之字符串操作
2 | 在各类脚本语言中,对字符串的操作相关的方法都是特别多的,JavaScript也不例外。
3 |
4 | ## 具体操作方法实现
5 | 首先介绍ECMA262v6中计划添加的方法:repeat、startsWith、endsWith、contains。
6 |
7 | - contains:判断一个字符串是否包含另一字符串。
8 |
9 | 正常来说,我们判断一个字符串是否包含另一字符串,可以用正则来实现,但是,如果需要频繁使用该方法,使用正则,性能太差,用字符串原生方法indexOf、search等则效率高很多。
10 |
11 | ```
12 |
13 | function contains(target, str) {
14 | return target.indexOf(str) != -1;
15 | }
16 | ```
17 |
18 | 在实际开发场景中,我们最常见的是判断一个元素的className是否包含某一特定class:
19 |
20 | ```
21 |
22 | function contains(target, str, sep) {
23 | return sep ? (sep + target + sep).indexOf(sep + str + sep) > -1 : target.indexOf(str) > -1;
24 | }
25 | contains('one two three fote', 'three', ' '); //输出true
26 | contains('one two three fote', 'threes', ' '); //输出false
27 | ```
28 | *HTML元素可以同时添加多个class,以空格分开。*
29 |
30 | - startsWith:判断目标字符串是否位于原字符串的开始位置。
--------------------------------------------------------------------------------
/css_position.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: New Post
4 | permalink: new-page.html
5 | description: Some Description
6 | date: 2016-01-19 11:59:16 +08:00
7 | tags: "some tags here"
8 | ---
9 |
10 | # CSS之定位机制
11 | CSS 有三种基本的定位机制:普通文档流、浮动和绝对定位。
12 |
13 | ## 普通文档流
14 | 在普通文档流(即未使用浮动和固定绝对定位时的默认定位方式)中,块级元素一个一个从上到下排列,而行内元素,在一行内,按从左到右排列。
15 |
16 | ## 浮动float
17 | 在浮动定位中,使用float设置标签元素向左或向右浮动,float值有none 或 left 或right:
18 |
19 | 
20 |
21 | ## 绝对定位
22 | 绝对或固定元素会生成一个块级框,而不论该元素本身是什么类型。相对定位元素会相对于它在正常流中的默认位置偏移。
23 |
24 | ### absolute
25 | 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。
26 | 元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行设置,偏移时不影响常规流中的任何元素,z-index可设置其显示层级优先度。
27 | ### fixed
28 | 生成绝对定位的元素,相对于浏览器窗口进行定位。
29 | 元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行设置,偏移时不影响常规流中的任何元素,z-index可设置其显示层级优先度。
30 | ### relative
31 | 生成相对定位的元素,相对于其正常位置进行定位,参照自身在常规流中的位置通过 "left", "top", "right" 以及 "bottom" 属性进行设置。
32 | 因此,"left:120" 会向元素在常规流中的位置 LEFT 添加 120 像素。
33 | ### static
34 | 默认值,没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。
35 | ### inherit
36 | 规定应该从父元素继承 position 属性的值。
--------------------------------------------------------------------------------
/mobile_gesture.md:
--------------------------------------------------------------------------------
1 | # 移动端手势与双指缩放
2 |
3 | 上周遇见一个双指缩放的问题,同时这个双指缩放也比较常见,于是决定对移动端手势做一个学习和总结,并给出一个双指缩放的实例,希望对读者提供一些帮助。
4 | ## 前言
5 |
6 | 当年乔布斯的iphone第一次支持多点触控时,确实惊艳了世人,而现在大部分手机都支持多点触控,这就有了手势这个概念,通过多点触控,形成不同的手势,开发者根据不同手势,提供不同功能,比如双指缩放,是很常见的。
7 |
8 | ### ios的多点触摸
9 |
10 | ios的Safari浏览器是第一个支持多点触摸的浏览器,并提供触摸API供开发者使用,到后来Android 3也开始支持多点触摸,各大浏览器也借鉴Safari提出了触摸API,除了个别硬件支持属性外,大致相同,这是值得庆幸的。
11 |
12 | ### IE10的多点触摸
13 |
14 | 虽然现在市场上WP手机越来越少,但是为了更完整的学习理解手势知识,我们也需要进行学习。IE10支持多点触摸,但是其多点触摸与ios和android不同,ios和android浏览器为多点触摸提供一个包含touches数组的事件,包含所有多点触摸对象,而IE10为多点触摸的每一个触摸点创建一个单独的触摸事件。
15 |
16 | ## 渐进增强与手势
17 |
18 | 我们知道手势很方便,用户也很喜欢手势,但是我们也要明白手势并不总是能使用,有些设备或浏览器还是不支持的,所以我们最合适的是基于普通点击和触摸事件交互的页面,将手势作为增强的交互,这就是通常所说的渐进增强思想。
19 |
20 | ## 触摸事件
21 |
22 | 既然是要渐进增强,那就必须从基础点击和触摸事件说起,点击事件就不再多说,关于触摸事件,之前也有一篇文章介绍过[移动开发之轻触与单击事件](http://blog.codingplayboy.com/2016/07/24/mobile_touch_tap/),关于触摸四种基础事件和事件对象,可以查看该文章,这里就不重复了,这里要对触摸事件的处理进行说明。
23 |
24 | ### 浏览器兼容
25 |
26 | 通常我们在触摸和手势事件处理函数内会添加CSS3动画处理,这个时候需要进行浏览器兼容处理。
27 |
28 | ```
29 |
30 | var TRANSITION = 'transition';
31 | var TRANSITION_END = 'transitionend';
32 | var TRANSFORM = 'transform';
33 |
34 | if (typeof document.body.style.webkitTransform !== undefined) {
35 | TRANSITION = 'webkitTransition';
36 | TRANSITION_END = 'webkitTransitionEnd';
37 | }
38 | ```
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/css_clear.md:
--------------------------------------------------------------------------------
1 | # CSS之清除浮动
2 | 对于CSS中的float属性,想必都很熟悉了,float: left | right;设置元素浮动常用来页面开发布局或定位元素,功能是很强大的,但是在使用过程中也经常会碰到问题,如下这种情况:
3 |
4 | 
5 |
6 | 代码如下:
7 |
8 | ```
9 |
10 |
11 |
12 |
13 |
14 | CSS之清除浮动
15 |
41 |
42 |
43 |
44 |
float: left
45 |
Mid
46 |
47 |
48 |
49 | ```
50 | 如上父容器元素高度未设置,容器中有浮动的子元素,父容器并没有高度自适应以容纳所有子元素,浮动元素溢出从而影响整个布局,这就是浮动溢出问题,而解决问题的方法就是所谓的清除浮动。
51 |
52 | ## 清除浮动
53 | 如何清除浮动,解决方法一大堆,此处就我个人经验及学习总结,大致分为3类:
54 |
55 | - 设置clear: left | both | right;清除浮动
56 |
57 | 主要是给浮动元素后面普通流元素设置clear属性,清除浮动:
58 |
59 | ```
60 |
61 | .mid {
62 | clear: both;
63 | }
64 | ```
65 | 也有人提出在浮动元素后面增加一个空div,设置其clear: both;清除浮动,其实本质上都是一样。
66 |
67 | -
--------------------------------------------------------------------------------
/js_info_trans.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: New Post
4 | permalink: new-page.html
5 | description: Some Description
6 | date: 2016-01-29 11:41:59 +08:00
7 | tags: "some tags here"
8 | ---
9 |
10 | # 原型继承
11 |
12 | 在大部分语言中,存在类和对象。类继承自其他类。
13 | 在JavaScript中,继承则是基于原型的。这意味着在JavaScript里面没有类的概念,其对象继承自其他对象。
14 |
15 | ## 继承之\_\_proto\_\_属性
16 | 假如一个rabbit对象继承自另外的animal对象,在JavaScript里这意味着其特殊属性rabbit.\_\_proto\_\_ = animal.
17 |
18 | 
19 |
20 | 假如一个rabbit属性可访问,并且解释器不能在rabbit对象里查找到它,它循着\_\_proto\_\_指针在animal对象里查找。
21 |
22 | 这个例子使用\_\_proto\_\_只在Chrome和FireFox浏览器起效,这样完全是为了简便,稍后我们会进行跨浏览器处理。
23 |
24 | ```
25 |
26 | var animal = {eats: true};
27 | var rabbit = {jumps: true};
28 | rabbit.__proto__ = animal; //继承
29 | alert(rabbit.eats); //true
30 | ```
31 | eats属性确实来自于animal对象,如下图:
32 |
33 | 
34 |
35 | 如果在rabbit对象上查找到该属性,则不检查\_\_proto\_\_属性。
36 |
37 | 例如,当子对象中存在eats属性,它的父级将被忽略:
38 |
39 | ```
40 |
41 | var animal = {eats: true};
42 | var fedUpRabbit = {eats: false};
43 | fedUpRabbit.__proto__ = animal;
44 | alert(fedUpRabbit.eats); //false
45 | ```
46 | 
47 |
48 | 我们可以在animal对象里设置一个方法随后可以在rabbit对象上访问。
49 |
50 | ```
51 |
52 | var animal = {
53 | eat: function() {
54 | alert("I'm full");
55 | this.full = true;
56 | }
57 | };
58 | var rabbit = {
59 | jump: function() {
60 | //do something
61 | }
62 | };
63 | rabbit.__proto__ = animal;
64 | rabbit.eat();
65 | ```
--------------------------------------------------------------------------------
/css_vfm.md:
--------------------------------------------------------------------------------
1 | # CSS Box Model盒模型
2 |
3 | # Visual Formatting Model
4 |
5 | CSS中的visual formatting model(视觉格式化模型)是一种处理文档并把它显示在可视化媒体上的算法。这是CSS中的一个基础概念。visual formatting model把文档的每一个元素转换成0个,1个或多个符合CSS盒模型的盒子,每个盒子的布局内容包括如下部分:
6 |
7 | - 盒子尺寸:明确指定受限制或不指定
8 | - 盒子类型:行内,行内级,原子行内级,块盒
9 | - 定位方案:包括正常文档流,float或者绝对定位
10 | - 节点树的其他元素:其子元素或兄弟元素
11 | - viewport(视窗)的尺寸和定位
12 | - 内含图片的固有尺寸
13 | - 其他额外信息
14 |
15 | visual formatting model相对于包含块的边界来渲染盒子,通常,一个盒子为它的后代元素建立包含块。然而一个盒子并不受其包含块限制,当一个盒子的内容超出其包含块时,就是我们通常所说的溢出(overflow)。
16 |
17 | ## 盒子的生成
18 |
19 | ----
20 | CSS visual formatting model从文档元素生成盒子,生成的盒子有多种类型,其类型会影响visual formatting model的行为。生成盒子的类型取决于元素CSS属性display的值。
21 |
22 | ### 块级元素和块盒子
23 |
24 | 当元素的CSS属性display计算值是block,list-item或table的时候,这个元素就是块级元素。一个块级元素会被视觉格式化成一个块(block),按照垂直方向排列。
25 |
26 | #### 主要块级盒(principal block-level box)
27 |
28 | 每个块级盒子都参与Block Formatting Context(块级格式化上下文)。每个块级元素(block-level element)至少生成一个块级盒子,即主要块级盒,大多数元素只生成一个主要块级盒,而有一些元素,如li列表,则会生成多个盒子,包括主要块级盒及描述排版信息或项目符号的其他盒子。
29 |
30 | 主要块级盒包括包括后代元素生成的盒子及生成的内容,我们可以使用之前谈到的定位方案定位该盒子。
31 |
32 | #### 块容器盒(block container box)
33 |
34 | 块容器盒只包含其他块级盒或生成一个行内格式化上下文,即只包含行内盒。我们必须明白块级盒和块容器盒两个概念不冲突。块级盒描述盒子与它的父级和兄弟元素之间的行为,块容器盒描述它与其后代元素之间如何相互作用。块级盒也可能是一个块容器盒。一些块级盒,比如表格,不是块级容器盒;相反地,一些块级容器盒,比如非置换行内块和非置换表格单元格也不是块级盒。
35 |
36 | #### 块盒
37 |
38 | 块级盒中也是块容器盒的盒子,是块盒(block box)。
39 |
40 | #### 匿名块盒
41 |
42 | 在某些情况下,visual formatting model 需要添加一些辅助性盒子,但是CSS选择器不能选中这些盒子,这些盒子叫做匿名盒子(anonymous box).
43 |
44 | 不能使用CSS选择器选择匿名盒子,说明不能给他们定义样式,这意味着所有可继承属性都继承自父元素,所有不可继承属性都是其初始值。
45 |
46 | ##### 匿名块盒实例
47 |
48 | 块容器盒只能包含块级盒或行内级盒,但是,通常在一个文档中,包含这两种类型盒子,此时,在行内级盒子前后创建匿名块盒。
49 |
50 | ```
51 |
52 | 我是第一个匿名块盒的内容
我是块级盒子的内容
我是第二个匿名块盒的内容
53 | ```
54 |
55 | 如上HTML代码,效果如下:
56 |
57 | ![匿名块盒]()
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/html_dbody.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: New Post
4 | permalink: new-page.html
5 | description: Some Description
6 | date: 2016-01-25 15:03:48 +08:00
7 | tags: "some tags here"
8 | ---
9 | # 漫谈document.documentElement与document.body
10 |
11 | 在前端开发中,我们经常需要获取网页中滚动条滚过的长度,获取该值的方式一般通过scrollTop属性,如:document.body.scrollTop,是不是还经常看见document.documentElement.scrollTop,这两者都是经常用来获取文档滚动条滚过长度值的方式,他们又有什么区别呢?待下文,细细道来:
12 |
13 | ## DTD
14 | DTD告诉浏览器当前文档用的是什么标记语言,然后浏览器才能正确的根据W3C标准解析文档代码。目前htmlDTD有三种类型:
15 |
16 | - Strict DTD:严格的文档类型定义
17 |
18 |
19 | 不能包含已过时的元素(或属性)和框架元素。
20 |
21 | - Transitional DTD:过渡的文档类型定义
22 |
23 | 能包含已过时的元素和属性但不能包含框架元素。
24 |
25 | - Frameset DTD: 框架集文档类型定义
26 |
27 | 能包含已过时的元素和框架元素。
28 |
29 |
30 | 在html文档中定义DTD就是通过!doctype定义,如下,是一个html4.0的过渡DTDhtml文档:
31 | ```
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | ```
44 | 或在html5中:
45 |
46 | ```
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | ```
57 |
58 | ## document.documentElement与document.body
59 |
60 | - document代表的是整个文档(对于一个网页来说包括整个网页结构),document.documentElement是整个文档节点树的根节点,在网页中即html标签;
61 | - document.body是整个文档DOM节点树里的body节点,网页中即为body标签元素。
62 |
63 | 我们常看见如下这种写法获取页面滚动条滚过的长度:
64 |
65 | ```
66 |
67 | var top = document.documentElement.scrollTop || document.body.scrollTop;
68 | 或
69 | var top = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
70 | ```
71 | 在文档使用了DTD时,document.body.scrollTop的值为0,此时需要使用document.documentElement.scrollTop来获取滚动条滚过的长度;在未使用DTD定义文档时,使用document.body.scrollTop获取值。
--------------------------------------------------------------------------------
/css_formattingContext.md:
--------------------------------------------------------------------------------
1 | # CSS之formatting context
2 |
3 | 格式化上下文,是CSS视觉渲染过程的一个概念,它主要影响盒子的布局。普通流中的每一个CSS盒子,都会属于一个格式化上下文,是块格式化上下文(block formatting context)和行内格式化上下文(inline formatting context)中的一种。块级盒子参与块格式化上下文,行内级盒子参与行内格式化上下文。
4 |
5 | ## 块格式化上下文
6 |
7 | 块格式化上下文,即block formatting context,简称BFC,可由如下元素创建:
8 |
9 | - 根元素
10 | - float浮动定位元素
11 | - 绝对定位元素
12 | - display为inline-block或table-cell或tabel-caption的元素
13 | - overflow值不为visible的元素
14 | - flex弹性盒子(display为flex或inline-flex)
15 |
16 | ### 特性
17 |
18 | - 独立性
19 |
20 | 块格式化上下文包含创建它的元素和它的所有不创建新的块格式化上下文的子元素,即块格式化是相互独立的,其只影响上下文内部的元素。
21 |
22 | - 排列
23 |
24 | 在块格式化上下文中,盒子按垂直方向,从包含块的顶部开始一个接一个地放置。
25 |
26 | - 崩塌(collapse)
27 |
28 | 两个相邻盒子的垂直距离由margin属性值决定。一个块级格式化上下文中的相邻块级盒子之间的垂直margin会发生崩塌(collapse)。
29 |
30 | - 边界
31 |
32 | 一个块格式化上下文中,每个盒子的左外边界碰触包含块的左边界(从右到左方向的格式化上下文,则是右边界碰触),即使某盒子是浮动定位,此特性依然成立,除非该盒子创建一个新的格式化上下文,此时该盒子会变窄。
33 |
34 | - 浮动
35 |
36 | 浮动定位只影响同一块格式化上下文中的元素布局,清除浮动只能清除同一块格式化上下文中它前面元素的浮动。
37 |
38 | ## 行内格式化上下文
39 |
40 | 行内格式化上下文,即inline formatting contex,简称IFC,和块格式化上下文一样,它是页面进行CSS视觉渲染时的一个概念。通常由display属性计算值是inline或inline-block或inline-table的元素创建。
41 |
42 | ### 特性
43 |
44 | - 排列
45 |
46 | 在一个行内格式化上下文中,盒子按水平方向,从包含块的顶部开始一个接一个地放置。
47 |
48 | - 间距与边界
49 |
50 | 水平margin,边界(bordr),padding,在盒子间依然保留。
51 |
52 | - 垂直对齐方式
53 |
54 | 这些盒子垂直方向对齐方式可以有多种:按顶部或底部对齐;按文本基线对齐等。
55 |
56 | - 行盒
57 |
58 | 通常我们把占据一行的整个矩形区域,叫做行盒,其包含了许多盒子。
59 |
60 | - 行盒的宽高
61 |
62 | 行盒(line box)的宽度由包含块和浮动绝对,高度是由其line-height计算规则决定。
63 |
64 | 一个行盒的高度总是足够容纳其包含盒,甚至大于包含盒中最高值,比如按基线对齐的盒子,[可以参见我的另一篇博客:两端对齐布局与text-align:justify](http://blog.codingplayboy.com/2016/10/01/justify_layout/)。
65 |
66 | - vertical-align
67 |
68 | 在行盒中,当其包含的某一盒子(命名a)的高度小于其高度时,这个a盒子在行盒内的的垂直方向对齐值由vertical-align属性值决定。
69 |
70 | - 拆分
71 |
72 | 当一个行盒不能容纳多个行内级盒子时,它们会被拆分成两个或多个垂直堆积的行盒,比如段落,一个段落是多个行盒的垂直堆积,行盒在垂直方向没有间距也不重叠地堆积。
73 |
74 | 本篇主要讲了一个CSS视觉渲染过程中的一个概念,它可以帮助我们理解很多CSS渲染出的结果,比如块格式化上下文中margin的崩塌,行内格式化上下文中垂直方向如何居中对齐等等,此篇篇幅不长,是下一篇要讲述的CSS之视觉格式化模型的引导篇。
75 |
76 |
--------------------------------------------------------------------------------
/js_compileRun.md:
--------------------------------------------------------------------------------
1 |
2 | #JavaScript之解释与执行机制
3 |
4 | 不同于其他的编译性语言如Java、C等,运行前需要将其编译为机器语言的文件,JavaScript在运行程序的时候才翻译,即JavaScript是一门解释性脚本语言.
5 |
6 | > 解释型语言:程序不需要编译,程序在运行时才**翻译**成机器语言,每执行一次都要翻译一次。
7 |
8 | > 编译型语言:程序在执行之前需要一个专门的**编译**过程,把程序编译成 为机器语言的文件,运行时不需要重新翻译,直接使用编译的结果。
9 |
10 | *JavaScript翻译过程又做解释过程。*
11 |
12 | ##JavaScript解释与执行
13 |
14 | JavaScript按照代码块来进行解释和执行,代码块间相互独立,但变量和方法共享。
15 |
16 | > JavaScript中的代码块是指由``标签分割的代码段。
17 |
18 | ###解释
19 |
20 | JavaScript代码块在执行时先由解释器进行解释,主要过程是声明所有var变量(并未初始化赋值,当前值为undefined)、解析**声明式**函数语句,而且是先预定义变量再预定义函数。
21 |
22 |
23 | > JavaScript中函数定义主要主要有两种:声明式与函数表达式。
24 |
25 | ```
26 |
27 | //声明式函数
28 | function test() {
29 | //...
30 | }
31 | //函数表达式
32 | var test = function() {
33 | //...
34 | }
35 | ```
36 |
37 | ###代码分析
38 |
39 | 1. **试分析以下代码:**
40 |
41 | ```
42 |
43 | alert(a);
44 | alert('ok');
45 | var a = 1;
46 | ```
47 | 弹出undefined和ok。因为执行时先解释:1.定义var变量,并未初始化赋值,当前值为undefined。
48 |
49 | 2. **请君细看**
50 |
51 | ```
52 |
53 | alert(a);
54 | alert('ok');
55 | a = 1;
56 | ```
57 | 会发现报错了,因为a未定义,解释时定义var变量,并不会定义此处的a。
58 |
59 | 到这里我们又发现了一个值得关注的问题--定义变量的方式。
60 | > JavaScript变量分两种:全局变量和局部变量。像a = 1;这种定义默认是创建全局变量,其实就相当于window.a = 1;而var a = 1;这种格式是定义一个当前作用域下的变量。解释时只会定义var格式的变量。
61 |
62 | 3.**函数相关**
63 |
64 | ```
65 |
66 |
73 |
80 | ```
81 | 结果如何呢?运行上述代码你会发现弹出了“声明式函数”和“ok2”。
82 | 为什么呢,这里就涉及到前面所说的**代码块之间是相互独立的**,故前面的a()虽然报错了,阻塞了ok1弹出;但是第二段script代码并不受影响。
83 |
84 | 第一段代码缘何报错?因为代码执行时先解释声明式函数而不会解释函数表达式,此时只是定义了a变量,未初始化,其值为undefined,不是函数。
85 |
86 | 总结:到此时对JavaScript的解释与执行机制、顺序也算有初步的认识了。
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/web_nwjs.md:
--------------------------------------------------------------------------------
1 | # 初识Node-Webkit之桌面应用程序开发
2 |
3 | 近期要开发一个桌面客户端类型的项目,调研发现了NW.js,即node-webkit,融合了 Node.js 和 Webkit HTML 渲染器来运行本地应用,是一个Chromium和node.js上的结合体。本篇通过一个案例,简单熟悉一下NW.js。
4 |
5 | ## NW.js
6 |
7 | 在[NW.js官网](http://nwjs.io/)([http://nwjs.io/](http://nwjs.io/))下载node-webkit包, 选择与平台相对应的版本,下载并安装即可。以windows版本为例,解压后目录结构如下:
8 |
9 | 
10 |
11 | ## Hello World
12 |
13 | ### 初始化项目
14 | 在任一目录下,新建index.html和package.json文件:
15 |
16 | 
17 |
18 | package.json为NW项目的配置入口:
19 |
20 | ```
21 |
22 | {
23 | "title": "Hello World",
24 | "name": "app",
25 | "main": "index.html", //项目入口窗口所在文件
26 | "window": {
27 | "toolbar": false, //工具条
28 | "frame": false, //边框,与transparent联合使用,控制窗口边框显示
29 | "transparent": true
30 | }
31 | }
32 | ```
33 | [更多信息可参见文档](https://github.com/nwjs/nw.js/wiki/Manifest-Format)
34 |
35 | ### 打包
36 | 新建zip压缩包,包名自定义,建议与package.json文件中name属性保持一致,本文以app.zip为例,然后将以上index.html和package.json文件放入,如下:
37 |
38 | 
39 |
40 | *注:项目文件必须在压缩包根目录下,即通过鼠标右键新建ZIP压缩文件生成压缩包,然后将文件移入压缩包。*
41 |
42 | 随后将该app.zip包修改后缀为.nw,即:
43 |
44 | 
45 |
46 | 将该nw包拖放到解压后的nw环境包中的nw.exe,即启动运行,:
47 |
48 | 
49 |
50 | ### 生成exe文件
51 |
52 | 如上已经生成一个可运行的项目文件,但是否感觉运行比较麻烦?接下来我们可以进一步生成.exe文件,就像普通exe文件一样点击即可运行。
53 |
54 | 
55 |
56 | 进入对应目录,执行copy /b app.nw+nw.exe app.exe命令,即生成可执行app.exe文件,双击即可运行,运行结果与上文一样。
57 |
58 |
59 | ## 优缺点思考
60 |
61 | - 优点
62 | * 提高UI开发效率与视觉效果,使用HTML5和CSS3可以极大提高UI开发效率并提升传统桌面客户端视觉效果
63 | * 容易实现跨平台:Windows、Linux、Mac OS X
64 | * 方便开发人员调试
65 |
66 | - 缺点
67 | * 程序体积变大,就如上文的一个简单地示例程序,都大于20M
68 | * 使用Js使用API操作客户端,安全性需要保证
69 |
70 |
71 | 对node-webkit的初步认识就到这里,其他使用web技术开发桌面程序的还有Electron、hex等,若感兴趣可以学习一下,希望能有所得。
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/git.md:
--------------------------------------------------------------------------------
1 | # Git由浅入深之版本控制系统
2 |
3 | 现在最高效的版本控制工具是什么?你最喜欢使用的版本控制工具是什么?
4 |
5 | 毫无疑问,Git是首选。本人从15年开始,无论是工作还是日常使用,均已全面转向Git。
6 |
7 | ## 前言
8 |
9 | 版本控制系统(Version Control System)是一个可以记录单个或一系列文件在不同时间发生的变化的系统,版本控制系统操作的文件可以是计算机上任意文件。
10 |
11 | 通过该系统,我们可以在之后将文件恢复到发生某次改变前的状态;可以找回删除的文件;可以比较不同时间文件的差别;可以查看每一次修改的相关信息。
12 |
13 | ## 历史
14 |
15 | ### 原始的版本控制
16 |
17 | 版本控制的需求一直存在,在版本控制工具出现之前,人们通常通过将文件拷贝到另外的目录进行版本备份,这是最简单但也是很不稳定的方法,比如,我们有可能忘记或者修改错误文件,这时候是无法找回之前文件的;而且不定时的拷贝文件是件极其乏味的事情,同时随着文件越来越多,其拷贝一次的耗费时间也越来越长。
18 |
19 | ### 本地版本控制(Local Version Control System)
20 |
21 | 为了解决原始的版本控制诸多问题,程序员们在很久以前就开发了一个本地版本控制系统,该系统使用一个小型数据库保存所有的文件变化。
22 |
23 | 
24 |
25 |
26 |
27 | ### 集中版本控制系统(Centralized Version Control System)
28 |
29 | 使用版本控制系统的遇到的一个主要问题是如何与其他开发者合作。为了解决这个问题,开发者们开发了集中版本控制系统(CVCS)。
30 |
31 | 这类版本控制系统,如CVS,Subversion和Perforce使用一个单独的服务器,保存所有的文件版本,所有的客户端都从这里检出(check out)文件。
32 |
33 | 这种方式流行了很多年,至今还是有很多个人或企业使用。
34 |
35 | 
36 |
37 |
38 |
39 | 这类系统对比本地版本控制系统有很多优势,诸如:
40 |
41 | - 开发者之间可以了解不同的开发进度;
42 | - 管理员可以细粒度的控制哪些开发者可以拥有哪些权限;
43 | - 相对于在每个客户端都安装配置本地数据库,只需要集中管理一个控制中心。
44 |
45 | 当然,没有什么是绝对完美的,CVCS也有很多问题,
46 |
47 | - 最突出的问题就是,由于集中控制,一旦控制中心瘫痪,所有开发者开发进程都会受影响;
48 | - 一旦控制中心服务器文件丢失,且没有备份,我们无法找回(除非在某客户端本地恰好还保存着未删除);
49 |
50 | 针对这类问题,后来有了分布式版本控制系统。
51 |
52 | ### 分布式版本控制系统(Distributed Version Control System)
53 |
54 | 对于分布式版本控制系统(DVCS),如Git,Mercurial,Darcs,客户端不是只从服务器检出(check out)最新版本文件,而是克隆出整个代码库,即使服务器出问题了,我们也能从客户端找回文件,而且每个客户端依然可以在本地进行版本控制,等待服务器修复后,再上传。
55 |
56 | 
57 |
58 | 实践证明,DVCS在处理不同开发者同时合作一个或多个项目时表现很好,最典型的就是Git了。
59 |
60 | ## Git
61 |
62 | 自诞生以来,引起过很多争议,但这并不影响开发者们对Git的青睐,一个好的分布式版本控制系统优化方向主要从以下几点着手,就像Git一样:
63 |
64 | - 速度(Speed)
65 | - 简单 (Simple Design)
66 | - 平行式开发(parallel development)
67 | - 完全分布式(Fully distributed)
68 | - 稳定高效(efficient)
69 |
70 | 自从2005年推出以来,Git已经成长为一个简单易用,稳定高效(尤其在处理大型项目上的表现),支持多分支平行开发的版本控制系统。
71 |
72 | 关于版本控制系统及Git的特性,已经略有所知,接下来是时候进入主题:Git由浅入深。
73 |
74 | **图片来源git-scm**
75 | [更多请查阅https://git-scm.com/doc](https://git-scm.com/doc)
76 |
--------------------------------------------------------------------------------
/backbone_01.md:
--------------------------------------------------------------------------------
1 | # Backbone.js入门
2 | 基于对Backbone.js的学习与几个项目实践,从本篇开始介绍Backbone.js,希望给看官提供一些帮助,同时巩固、提升已有知识。经过这些年的发展,前端MVC、MV*模式框架都得到了巨大的发展,如Backbone.js、AngularJs。在介绍Backbone之前有必要先了解一下MVC。
3 |
4 | # MVC
5 | MVC,即Model-View-Controller,是一种架构设计模式,强调通过分离关注点以改进程序的组织结构,通过将业务数据与用户界面分离、由另外的组件控制逻辑、用户输入、模型与视图的交互实现关注点分离。
6 |
7 | # Backbone
8 | 经过不断发展与尝试,JavaScript开发人员将MVC模式融进了前端开发,并提出了多个使用MVC的JavaScript框架,如接下来要介绍的Backbone。
9 |
10 | ## 模型
11 | 不同框架中模型功能多少会有些不同,但一般都会有表示模型数据的属性。
12 |
13 | - Backbone模型是一种持久化模型,允许对保存的模型进行修改,更新,常见的是在浏览器localStorage保存或与数据库同步。
14 | - Backbone通常将模型进行分类分组,在分组中管理具有同一类特征的模型,这些分组就是集合,集合可以对模型进行许多操作。
15 | - Backbone中通常有一个或多个视图观察同一模型,模型更新时,视图获得通知,进行视图更新
16 |
17 | ## 集合
18 | 集合是模型的有序组合,一般通过对同一性质或类型模型进行分组归入不同集合以集中管理模型,但集合并不是必须的。
19 |
20 | - 集合可以很方便的添加和删除、更新模型,检索模型,并能对模型进行批量管理。
21 | - 集合通过绑定change事件可以监听到集合中模型的变化,并执行相应监听函数。
22 |
23 | ## 视图
24 | 在程序中,用户一般只与用户界面(即视图)交互,用户通过视图对模型进行操作。
25 |
26 | - Backbone在视图中定义render()方法,一般使用JavaScript模板引擎渲染模型内容,生成视图。
27 | - Backbone模型构造函数(initialize()方法)中添加render()回调方法,在模型内容变更时触发更新视图。
28 | - Backbone视图中events对象采用事件委托形式为视图元素绑定监听事件回调函数。
29 |
30 | ## 模板
31 | 相对于最初通过字符串拼接,在内存中创建大量HTML标记,然后便利数据插入,耗费大量成本的这种不明智方式,JavaScript模板库通常将视图模板定义为包含模板变量的HTML标记。模板可以保存在script标签或外部文件模板中,变量通过变量语法分隔;以多种格式接收数据,常见的是JSON格式。
32 |
33 | 如Underscore.js模板:
34 |
35 | ```
36 |
37 |
38 |
<%= title %>
39 |
<%= description %>
40 |
<%= price %>
41 |
42 |
43 | ```
44 |
45 | ## 事件Event
46 | Backbone事件Event,将事件触发后要执行的函数注册成事件处理句柄,事件发生便触发执行该函数。
47 |
48 | - 可以将业务逻辑与用户界面关注点分离,即业务逻辑不需要知道界面工作流程。
49 | - Backbone.Events对象混入Backbone模型、集合、路由、视图等诸多对象中。
50 | - Backbone.Events可以让任何对象具有绑定和触发事件的能力。
51 |
52 | ```
53 |
54 | //引入underscore.js...
55 | var obj = {};
56 | _.extend(obj, Backbone.Events);
57 |
58 | obj.on('eat', function(msg) {
59 | console.log(msg);
60 | });
61 | obj.trigger('eat', 'eat food');
62 | ```
63 |
64 | ## 路由
65 | 严格来说,Backbone中并没有MVC中的控制器,通常在视图中包含控制器逻辑,而使用路由管理应用程序状态,在不刷新页面的同时通过监听文档url的hash片段变化,导向不同的视图和模型。
66 |
67 | - Backbone支持动态路由选择,允许定义带参数的路由,可以根据参数在路由回调函数中进行不同处理。
68 | - Backbone以Backbone.history作为路由的入口,无论是点击浏览器前进后退按钮还是手动使用navigate导航,都是从history入口,根据定义好的路由匹配规则进入路由回调函数,实现功能。
69 |
70 | 本篇主要介绍了一下Backbone.js的主要特征及主要模块,对Backbone有一个综合的了解,下篇开始学习Backbone具体模块。
--------------------------------------------------------------------------------
/html_secure.md:
--------------------------------------------------------------------------------
1 | # HTML应用安全
2 |
3 | 通常,我们使用HTML来创建交互网站,我们不能保证网络上每一个用户都是正直,友好的,为了大部分友好用户的体验和安全,我们需要关注网站的脆弱性,防止攻击者通过这些弱点进行攻击,窃取用户信息。本篇关注应用程序的安全性及应用程序开发过程中易犯的错误,主要介绍跨站脚本(XSS)和跨站请求伪造(CSRF)。
4 |
5 | 网络上大部分安全问题都是源于“origin”(源或域)这一概念,主要的攻击都涉及到跨域行为。
6 |
7 | ## XSS (Cross-site scripting)
8 |
9 | XSS,跨域脚本攻击,是当前比较常见的一种网络攻击。
10 |
11 | ### SQL注入(SQL injection)
12 |
13 | 在接受不确定输入内容(如第三方站点消息,URL参数,用户创建的文本批注等)时,在使用前对数据进行验证并且在展示时进行适当的编码是必不可少的,否则,可能会有恶意用户对网站进行攻击,轻者只是传递不规范的数据,严重的可能攻击服务器,扰乱网站正常运行,如,注入SQL脚本清除服务器上所有数据等。
14 |
15 | 通常编写过滤器验证用户输入时,过滤器应该是基于白名单(已知的安全结构)配置编写,允许白名单通过,不允许其他输入;而基于黑名单(已知的不安全结构)配置编写,即允许除了黑名单之外的所有输入,是不安全的,因为还有许多未知的不安全事物。
16 |
17 | ### JavaScript脚本注入
18 |
19 | 通常我们根绝URL中的指定参数,返回给用户不同页面,提供给用户如下导航:
20 |
21 | ```
22 |
23 |
28 | ```
29 |
30 | 如上,若以上URL没有编码直接展示给用户,恶意攻击者可以截断URL并插入一个script元素:
31 |
32 | ```
33 |
34 | http://blog.jhss.com/?id=%3Cscript%3Ealert%28%27Oh%20no%21%27%29%3C/script%3E
35 | ```
36 |
37 | 若其他用户访问这个URL页面,则会执行注入的script标签内的任意脚本,恶意者可以指定恶意代码,窃取用户信息。
38 |
39 | 还有很多方式被用来欺骗站点执行注入的代码,如下是我们应该考虑的方面:
40 |
41 | - 1.当时用看似无害的元素时,应该限制其可以使用的属性。如,```
```元素,如果允许使用onload属性,则攻击者可以使用onload属性添加回调函数执行任意指定代码。
42 | - 2.当允许插入``````元素时,意味着当前页面所有```
33 | ```
34 |
35 | ### 方法二
36 |
37 | 另一个方法是允许用户检测是否启用framekiller:
38 |
39 | ```
40 |
41 | var framekiller = false;
42 | window.onbeforeunload = function() {
43 | if(framekiller) {
44 | return ''; // any message that helps user to make decision
45 | }
46 | };
47 | ```
48 |
49 | 在添加iframe后,应该加入如下代码:
50 |
51 | ```
52 |
53 | // 实际frame元素的ID
54 | var frmaeId = 'my-frame';
55 | document.getElementById(frameId).onload = function() {
56 | framekiller = true;
57 | };
58 | ```
59 |
60 | ## Anti-Framekiller与sandbox
61 |
62 | html5给iframe新增了一个sandbox属性,通过设置该属性值,可以为iframe内容设置不同的权限。
63 |
64 | ### iframe
65 |
66 | > The HTML Inline Frame Element (iframe) represents a nested browsing context.
67 |
68 | > iframe表示一个嵌套浏览上下文,即在当前页面插入另一个HTML页面。
69 |
70 | 每个浏览上下文都有各自的会话历史信息和document,包含嵌入内容的浏览上下文称为父级浏览上下文,顶级浏览上下文,通常就是浏览器窗口环境。
71 |
72 | 在HTML5以后,应尽可能少用iframe,以下情况除外:
73 |
74 | - 1.跨域通信
75 | - 2.引用第三方内容
76 | - 3.独立的子窗口应用
77 | - 4.在移动端用于从网页调起客户端应用
78 | - 5.沙箱隔离:
79 |
80 | ### 沙箱隔离
81 |
82 | 所谓的沙箱隔离,就是将当前页与iframe内容页分隔开来,形成两个相对独立的部分,即通过添加iframe的sandbox属性。
83 |
84 | #### sandbox
85 |
86 | 其值可以为空字符串或以空格分隔的多个字符串。
87 |
88 | 若指定为空字符串,则使用所有限制条件,其属性值有很多,主要的有以下几种:
89 |
90 | - allow-forms:允许iframe内表单提交
91 | - allow-scripts:允许iframe内脚本执行
92 | - allow-same-origin:允许iframe内容被当作与包含文档同源,否则是跨域
93 | - allow-top-navigation:允许嵌入浏览上下文导航(加载)内容到包含文档或完成页面跳转
94 | - allow-modals:允许嵌入上下文打开模态窗口
95 | - allow-popups:允许嵌入上下文弹出窗口
96 | - allow-orientation-lock:允许嵌入上下文取消锁定屏幕方向
97 | - allow-pointer-lock:允许锁定鼠标
98 |
99 | 如:
100 |
101 | 主页面代码:
102 |
103 | ```
104 |
105 |
106 |
107 |
108 | ```
109 |
110 | iframe页面内容:
111 |
112 | ```
113 |
114 |
115 | Iframe Sandbox
116 |
121 |
128 |
129 | ```
130 |
131 |
132 | **链接:[iframe sandbox](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox) [framekiller](https://en.wikipedia.org/wiki/Framekiller)**
--------------------------------------------------------------------------------
/html5_canvas_screenclip.md:
--------------------------------------------------------------------------------
1 | # HTML5 canvas截图
2 |
3 | 上周遇到一个问题,是前端如何实现页面截图,第一反应就是响起了canvas,经过试验和总结,发现使用canvas可以实现屏幕截图,但是其实用性尚有局限,现进行阐述。
4 |
5 | ## 前言
6 |
7 | 要使用canvas实现页面截图,首先,我们需要在canvas内描画DOM内容,先来看个实例:
8 |
9 | [canvas实现页面截图](http://demo.codingplayboy.com/demo/canvas_clip/index.html)
10 |
11 | ## 在canvas内描画DOM内容
12 |
13 | 目前,是无法在canvas内直接描画DOM内容,而是必须使用SVG图片包含需要渲染的内容,在SVG中使用``````元素包含HTML结构,然后调用canvas API中drawImage()方法将SVG图片描画到canvas内。
14 |
15 | ### 创建SVG图片
16 |
17 | 首先创建一个SVG图片,我们需要创建一个包含SVG相关的XML信息(该SVG必须是有效的XML),然后构建一个Blob对象:
18 |
19 | ```
20 |
21 | var data = '';
28 | var DOMURL = window.URL || window.webkitURL || window;
29 | var img = new Image();
30 | var svg = new Blob([data], {type: 'image/svg+xml'});
31 | var url = DOMURL.createObjectURL(svg);
32 |
33 | img.onload = function () {
34 | //canvas.width = window.innerWidth;
35 | //canvas.height = window.innerHeight;
36 | //ctx.drawImage(img, 0, 0);
37 | //DOMURL.revokeObjectURL(url); // 回收URL
38 | //canvas.style.display = 'block';
39 | }
40 | img.src = url;
41 |
42 | ```
43 |
44 | 如上,首先创建一个svg字符串,该字符串中包含``````元素,该元素内容即为需要canvas渲染的DOM内容;然后使用Blob构造函数创建一个MIME类型为image/svg+xml的Blob实例;随后调用window的URL对象的createObjectURL()方法创建一个HTML文档内联URL对象实例;然后通过```new Image()```创建了一个HTML```
```元素,并将URL对象数据添加至该图像(设置其srcs属性)。
45 |
46 | ## canvas绘图
47 |
48 | 将上文创建的HTML```
```元素内容绘制到canvas内:
49 |
50 | ```
51 |
52 | var canvas = document.getElementById('canvas');
53 | var ctx = canvas.getContext('2d');
54 |
55 | img.onload = function () {
56 | canvas.width = window.innerWidth; // 设置canvas宽高
57 | canvas.height = window.innerHeight;
58 | ctx.drawImage(img, 0, 0); // 绘制图片
59 | DOMURL.revokeObjectURL(url); // 回收URL
60 | canvas.style.display = 'block';
61 | };
62 | ```
63 |
64 | 如上使用canvas API的drawImage()方法将img图片绘制至canvas。
65 |
66 | ## 获取DOM内容
67 |
68 | 上文提到,svg中``````元素内包含的是需要渲染的DOM内容,DOM内容的根元素必须设置xmlns属性,如:
69 |
70 | ```
71 |
72 | xmlns="http://www.w3.org/1999/xhtml"
73 | ```
74 |
75 | 如下是获取当前文档HTML DOM内容:
76 |
77 | ```
78 |
79 | var _html = document.documentElement.innerHTML;
80 | var doc = document.implementation.createHTMLDocument("");
81 |
82 | // You must manually set the xmlns if you intend to immediately serialize
83 | // the HTML document to a string as opposed to appending it to a
84 | // in the DOM
85 | doc.documentElement.setAttribute("xmlns", doc.documentElement.namespaceURI);
86 | doc.documentElement.innerHTML = _html;
87 |
88 | // Get well-formed markup
89 | var html = (new XMLSerializer).serializeToString(doc.documentElement);
90 | ```
91 |
92 | ## 效果
93 |
94 | 在这个例子中,我们首先隐藏了canvas元素,随后绘制好DOM内容,然后显示canvas查看截图:
95 |
96 | ```
97 |
98 | canvas.style.display = 'block';
99 | ```
100 |
101 | 效果如图:
102 |
103 | 
104 |
105 | ## 限制
106 |
107 | - 我们发现通过外链引入的CSS样式是无法通过canvas截图复制的,只有内联或行内样式才能复制显示在canvas内。
108 | - 由于安全原因,无法直接下载保存图片,但是可以通过别的方式获取图片数据,下篇详细介绍。
109 |
110 | 本篇相关完整代码查看[html5 canvas页面截图https://github.com/codingplayboy/web_demo/blob/master/html5/canvas_clip/canvasScreenClip.html](https://github.com/codingplayboy/web_demo/blob/master/html5/canvas_clip/canvasScreenClip.html),之后将继续介绍如何将该图片保存或传送至服务器。
111 |
112 |
113 |
--------------------------------------------------------------------------------
/css_line_height.md:
--------------------------------------------------------------------------------
1 | # CSS基础line-height和vertical-align属性
2 |
3 | 对于line-height属性,作为一个前端开发人员,肯定都不陌生,天天都在使用的一个CSS属性,但是这也是一个很考验一个前端开发者CSS基础功力的知识点,本篇就对line-height进行详细学习。
4 |
5 | 关于本篇中涉及到的行盒盒模型相关概念可以查看[CSS盒模型(BOX Model)](http://blog.codingplayboy.com/2016/11/26/css_box_model/)。
6 |
7 | ## 认识line-height
8 |
9 | 若对基础概念不感兴趣,可以直接查看实例和总结。
10 |
11 | line-height,顾名思义,是定义某元素行高的,即,行与行之间的间距。我们知道HTML中元素分为块级与行内元素,行内元素又分为置换行内元素和非置换行内元素,对于不同类型元素,line-height作用并不相同:
12 |
13 | 1. 块级元素: 对于块级元素,line-height属性定义了该元素内部所有line boxes(独占一行的盒子,即行盒模型)的最小高度。
14 | 2. 非置换行内元素(non-replaced inline element): 对于非置换行内元素,如,span,line-height属性定义行盒(line box)的高度。
15 | 3. 置换行内元素(replaced inline element): 对于置换行内元素,如img,button,a等,line-height属性不影响其行高。
16 |
17 | ## 行内元素
18 |
19 | 块级元素与行内元素的区别,相信大家都知道,块级元素,单独成行展示,行内元素则是在同一行内并列展示。但行内元素又分为置换行内元素和非置换行内元素,大家可能对这两个概念不太清楚,这里进行展开阐述:
20 |
21 | ### 置换与非置换行内元素
22 |
23 | > There are two types of inline elements: replaced inline elements and non-replaced inline elements. In general, non-replaced elements are those whose content is contained in the document, whereas replaced-elements are those whose content is outside of the document,such as an image, embedded document, or applet.
24 | However, as far as the inline box model is concerned, the definitions are as described above except that elements with display types inline-table and inline-block (the latter is a proposed type for CSS3 to accommodate form elements) are considered replaced elements.
25 |
26 | > 行内元素可以分为两种类型:置换行内元素和非置换行内元素。通常,非置换元素的内容直接包含在当前文档内,而置换元素的内容则来自文档外,比如`
`,潜入文档或者小应用。但是,例外的是,涉及到行内盒模型时,display属性为inline-table和inline-block(CSS3中推荐form元素使用此类型)的元素都被当作置换元素。
27 |
28 | ## line-height属性值
29 |
30 | line-height属性值是可继承的,除了设置inherit关键字外,其值有多种,包括normal数值,百分比,特定长度:
31 |
32 | ### normal
33 |
34 | normal是line-height属性初始值,其用于计算样式时的具体值通常由用户代理决定,许多桌面浏览器通常初始该值为1.2,但这个值这也取决于元素的font-family值,其效果与设置数字值相同。
35 |
36 | ### 数字值
37 |
38 | line-height属性值可以是一个不带单位的number数字,计算的值是该属性值乘以元素的字体大小(font-size)。这种类型的值也是通常建议使用的方式,后代元素继承该line-height数字值,并与自己font-size相乘得到计算值。
39 |
40 | ### 百分比
41 |
42 | line-height属性值也可以是百分比形式,与当前元素的字体大小有关,计算的值是元素的计算字体乘以该百分比值,后代元素line-height直接继承该计算后的值。
43 |
44 | ### 长度
45 |
46 | line-height属性值还可以设定特定长度值,该指定的值用于计算line box的高度,后代元素会直接继承该计算后的值。
47 |
48 | ## 实例
49 |
50 | 首先看个实例,[点击传送到实例](http://demo.codingplayboy.com/demo/smallcase/htc/line-height.html)
51 |
52 | 点此查看完整代码 [https://github.com/codingplayboy/web_demo/blob/master/css/line-height.html](https://github.com/codingplayboy/web_demo/blob/master/css/line-height.html)
53 |
54 | 效果如图:
55 |
56 | 
57 |
58 | 可以看到:
59 |
60 | 1. 当line-height值使用长度值时,当前元素内的行盒行高是该值,其后代元素均继承该值,行高不会随自身字体尺寸变换而变换;
61 | 1. 当line-height值使用百分比时,当前元素内的行盒行高是百分比乘以其font-size值,其后代元素继承的则是这个计算后的值,行高也不会随自身字体尺寸变换而变换;
62 | 1. 当line-height值使用数字值时,后代元素继承该数字值,行高是各自font-size值乘以该数值,行高与字体尺寸相适应。
63 |
64 | **由此得出,我们推荐line-height属性值使用数字值。**
65 |
66 | ## vertical-align
67 |
68 | vertical-align属性指定行内元素或表格单元格元素在垂直方向的对齐方式,其值主要有baseline
69 | ,middle,top,bottom等,
70 |
71 | 为如下值时,相对于其父元素对齐:
72 |
73 | 1. baseline:将此元素与其父元素按基线对齐
74 | 1. 基线,一个元素的基线是指正常流中其包含的最后一个行内元素的基线。可以查看[使用text-align实现两端对齐布局实例中使用vertical-allign使其垂直方向对齐](http://blog.codingplayboy.com/2016/10/01/justify_layout/);
75 | 1. 若元素没有基线(如,没有正常流中的行内元素或其overflow属性不为visible),则将其外间距的下边界当作基线
76 | 1. middle:将行内盒中线与父元素基线加上父元素中x字母尺寸的一半高度对齐 ;
77 | 1. sub:将此元素基线与父元素的下标基线对齐;
78 | 1. super:将此元素基线与父元素的上标基线对齐;
79 | 1. text-top:将此元素的顶部和父元素的内容区域顶部对齐;
80 | 1. text-bottom:将此元素的顶部和父元素的内容区域底部对齐;
81 | 1. 百分比:在基线对齐的基础上,将此元素的基线(也等同于整个行内盒)提高或降低一个高度值,此高度值为百分比乘以其自身line-height计算值(正值为提高,负值时降低),值为0%时,等同于baseline;
82 | - 长度值:在基线对齐的基础上,将此元素的基线(也等同于整个行内盒)提高或降低一个高度值,值为0px时,等同于baseline;
83 |
84 | 为如下值时,相对于整行(所在行盒)对齐:
85 |
86 | 1. top:将当前元素及其后代元素的顶部与行盒顶部对齐;
87 | 1. bottom:将当前元素及其后代元素的顶部与行盒顶部对齐
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/react_diff.md:
--------------------------------------------------------------------------------
1 | # 认识React的diff算法
2 |
3 | React提供一种声明式API,使得我们不需要了解在每次更新时具体改变了什么。这使得开发应用很简单,但是React如何实现这一点并不明显。本篇文章介绍React的diff算法为何在满足高性能应用要求时,React组件的更新是可预测的。
4 |
5 | ## 前言
6 |
7 | 在使用React时,我们首先思考创建React节点树的render()方法,在下一次state或props更新时,render()方法将返回另一个React元素树,随后React比较两颗不同的React节点树,并据此更新页面视图。
8 |
9 | 已经有一些基本方案解决在最小化操作下比较一颗React节点树到新的React节点树之间的不同。但是,最先进的算法时间复杂度也是O(n^3),n是节点树的元素数量。
10 |
11 | ## diff算法
12 |
13 | 如果在React中使用这些算法,展示1000个元素将要进行10亿次比较,这个性能太低;React实现了一个时间复杂度为O(n)的探索式算法,该算法基于两点假设:
14 |
15 | - 1.不同类型的元素生成不同的节点树
16 | - 2.开发者通过key属性的不同表现指出哪个子元素更稳定。
17 |
18 | 实际上,这两点假设对于大多数实践是有效的。
19 |
20 | 在比较两个React节点树时,React首先比较根元素,随后的行为取决于根元素类型。
21 |
22 | ### 根节点不同类型
23 |
24 | 只要根节点类型不同,React就会销毁旧节点树,创建新节点树。
25 |
26 | - 在销毁节点树时,旧的DOM节点会被销毁,React组件实例触发componentWillUnmount()方法。
27 | - 在创建新节点树时,新的DOM节点被插入DOM树,React组件实例依次触发componentWillMount()方法和componentDidMount()方法。
28 |
29 | 根节点类型不同,根节点下任何组件或元素节点都会被卸载,并且把其state销毁,比如如下两棵节点树,diff后,卸载旧的Home组件,挂载一个新的Home组件实例:
30 |
31 | ```
32 |
33 |
34 |
35 | ```
36 | ## 节点同类型
37 |
38 | 当比较两个相同类型的React节点(包括组件和html元素)时(包括所有节点,根节点和所有子节点),React比较两者的属性,不改变DOM节点,只更新当前节点需要改变的属性,如:
39 |
40 | ```
41 |
42 |
43 |
44 | ```
45 | 对于如上两个元素,React仅会改变当前节点需要改变的className属性。
46 |
47 | ### 样式更新
48 |
49 | 如果节点需要更新样式属性,React仅会更新当前节点需要改变的样式属性,如:
50 |
51 | ```
52 |
53 |
54 |
55 | ```
56 |
57 | React仅会更新当前节点的font-size属性值。
58 |
59 | React重复以上步骤,递归比较处理两棵React节点树.
60 |
61 | ### 组件节点同类型
62 |
63 | 前面的diff比较都是以html元素为例,但是对于组件,前文的理论依然适用,只是关于组件的比较,我们还需要了解更多内容:当某一组件更新了,组件实例还没有改变,其组件状态是通过渲染维护的。React更新当前组件实例的(props)属性以匹配新元素,并且调用当前实例的componentWillReceiveProps()方法和componentWillUpdate()方法;然后调用render()方法并且使用diff算法递归比较已经更新的节点树和新返回的节点树。
64 |
65 | ## 递归比较子节点
66 |
67 | 默认地,在递归比较DOM节点的子节点时,React同时遍历两个子节点列表,当发现不同时,立即做出改变。
68 |
69 | 比如,需要在一个节点的子节点后插入一个子节点,性能是很好的,比较如下两棵节点树:
70 |
71 | ```
72 |
73 |
74 | - first
75 | - second
76 |
77 |
78 |
79 | - first
80 | - second
81 | - third
82 |
83 | ```
84 |
85 | React匹配ul节点的子节点列表,依次比较```first和second```,直到发现当前元素缺少子节点```third```,就立即插入一个```third```节点。
86 |
87 | 但是如果不是在末尾插入新的子节点,而是在头部插入:
88 |
89 |
90 | ```
91 |
92 |
93 | - first
94 | - second
95 |
96 |
97 |
98 | - third
99 | - first
100 | - second
101 |
102 | ```
103 |
104 | React比较第一个子节点时,就发现不同,立马改变该节点,随后全部子节点都需要改变,这样的性能表现很不好。
105 |
106 | ## key属性
107 |
108 | 为了解决上面提到子节点比较的问题,React提供了key属性,如果某子节点拥有key属性,React会在原始子节点树里使用key值来比较该子节点,比如,对于如上实例,使用key属性:
109 |
110 | ```
111 |
112 |
113 | - first
114 | - second
115 |
116 |
117 |
118 | - third
119 | - first
120 | - second
121 |
122 | ```
123 | 对于如上这种结构,React会创建key值为3的节点,而只是移动key值为1和2的节点。
124 |
125 | ### key属性值与唯一性
126 |
127 | 既然通过key值比较子节点,那么很明显,至少在子节点树里,每个key值必须是唯一的,但是并不需要保证key值是全局唯一的。
128 |
129 | **通常我们可以使用服务端返回的列表项数据中的id或index当key值。**
130 |
131 | ## diff算法的不足
132 |
133 | 我们必须明白,React diff算法决定如何重新渲染组件,但这只是一个细节实现,React可以对每一个action行为都重新渲染整个应用,最后的视图都是一样的,我们在不断地精炼探索式算法以提高应用性能。
134 |
135 | 目前的实现方式中,如前文的实例,我们知道在子节点间是可以不被重新渲染而只发生移动的,但是除此之外,子节点并不能被重用,算法将会重新渲染整个子节点树。
136 |
137 | 前文提到,React的diff算法是探索式的,基于两点假设,如果这两点假设不满足,性能就会降低:
138 |
139 | - 1.算法不会比较不同组件类型的子节点
140 | - 2.key值应该是稳定的,可预测的,唯一的。不稳定的key值会产生很多不必要的重绘和子组件状态的丢失。
141 |
142 |
--------------------------------------------------------------------------------
/web_gulp.md:
--------------------------------------------------------------------------------
1 | # Grunt与Gulp
2 | 对于我们前端开发者,目前使用最多的自动化管理工具应该是Grunt--在Gruntfile.js文件中使用JavaScript定义各种任务。
3 |
4 | ## Gulp
5 | 基于Node.js流,配置简单,易于学习,使用方便。在guplfile.js里按定义好的规则执行构建任务。学习Gulp之前先来了解一下Vinyl和Orchestrator
6 |
7 | ### Vinyl
8 | Vinyl是一种虚拟文件格式,是一种简单的描述文件的元数据对象。主要有path和contents两个属性。
9 |
10 | #### Vinyl adpter
11 | Vinyl对文件进行了描述,而Vinyl adpter通过提供src和dest方法支持我们对文件进行访问。
12 |
13 | ```
14 |
15 | var map = require('map-stream');
16 | var vfs = require('vinyl-fs');
17 |
18 | var log = function(file, cb) {
19 | console.log(file.path);
20 | console.log(file.contents);
21 | cb(null, file);
22 | };
23 | vfs.src(['./js/**/*.js', '!./js/except/*.js'])
24 | .pipe(map(log))
25 | .pipe(vfs.dest('./output'));
26 | ```
27 |
28 | ### Orchestrator
29 |
30 | 一个指定任务和依赖的关系与处理,然后并发执行任务的模块。
31 |
32 | ```
33 |
34 | var Orchestrator = require('orchestrator');
35 | var orchestrator = new Orchestrator();
36 | orchestrator.add('thing1', function(){
37 | // do stuff
38 | });
39 | orchestrator.add('thing2', function(){
40 | // do stuff
41 | });
42 | orchestrator.add('thing3', ['thing2'], function(){
43 | // do stuff
44 | });
45 | orchestrator.start('thing1', 'thing3', function (err) {
46 | // all done
47 | });
48 | ```
49 |
50 | ### Gulp五个API
51 |
52 | - gulp.src()
53 |
54 | 接受一个匹配模式或一个匹配模式数组,返回对应的Viny files流,可以当作其他插件的输入。
55 |
56 | ```
57 |
58 | var gulp = require('gulp')
59 | , jshint = require('gulp-jshint')
60 | , concat = require('gulp-concat')
61 | , uglify = require('gulp-uglify')
62 | , rename = require('gulp-rename');
63 | gulp.src(['./app/src/js/**/*.js', '!./app/src/js/**/*.min.js'])
64 | .pipe(rename({suffix: '.min'}))
65 | .pipe(uglify())
66 | .pipe(gulp.dest('./app/build/js'));
67 | ```
68 |
69 | - gulp.dest()
70 |
71 | 接收一个路径参数(可以由函数返回一个路径),,输出数据,写入文件。
72 |
73 | - gulp.task()
74 |
75 | 定义gulp任务,并制定任务依赖及执行规则。Gulp的任务操作继承自Orchestrator。
76 |
77 | ```
78 |
79 | //gulp source code
80 | var util = require('util');
81 | var Orchestrator = require('orchestrator');
82 | function Gulp() {
83 | Orchestrator.call(this);
84 | }
85 | util.inherits(Gulp, Orchestrator);
86 | Gulp.prototype.task = Gulp.prototype.add;
87 | ```
88 |
89 | 简单声明依赖后,任务函数依顺序执行:
90 | ```
91 |
92 | gulp.task('compileLESS', ['clean'], function(){
93 | //compile LESS file...
94 | });
95 | gulp.task('clean', function(){
96 | gulp.src('sample.css', { read:false })
97 | .pipe(clean());
98 | });
99 | ```
100 |
101 | 保证任务顺序执行(返回流):
102 | ```
103 |
104 | gulp.task('compileLESS', ['clean'], function(){
105 | //compile LESS file...
106 | });
107 | gulp.task('clean', function(){
108 | return gulp.src('sample.css', { read:false })
109 | .pipe(clean());
110 | });
111 | ```
112 |
113 | - gulp.run()
114 |
115 | 接收一个任务名,执行该任务。
116 |
117 | - gulp.watch()
118 |
119 | 接收一个匹配模式或匹配模式数组,可选的传入一个回调函数,返回一个EventEmitter发送change事件;监听匹配文件的变化,一旦文件发生变化就促发回调。
120 |
121 | ```
122 |
123 | var watcher = gulp.watch('js/**/*.js', ['uglify','reload']);
124 | watcher.on('change', function(event) {
125 | console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
126 | });
127 | ```
128 |
129 | ```
130 |
131 | gulp.watch('./app/src/js/**/*.js', function() {
132 | gulp.run('lint', 'scripts');
133 | });
134 | ```
135 |
136 | ### Grunt VS Gulp
137 |
138 | 无论grunt还是gulp亦或是webpack,npm scripts,它们都只是一个工具,让我们更专注在代码上,而不应该是迷失在众多工具中。尽管如此,在个人使用中,grunt与gulp还是有差别,主要从两方面简要说明:
139 |
140 | - 配置和使用
141 |
142 | - gulp基于CommonJs规范,gulpfile.js配置更简单、代码更适于维护。
143 | - gulp的五个API清晰简单,使用更简单。
144 | - grunt插件更丰富、功能更全面。
145 |
146 | - 底层文件操作
147 |
148 | - grunt以临时文件的形式,从源文件,生成多个临时文件,根据不同任务进行多次读写,最后生成目标文件,I/O操作较频繁。
149 | - gulp以流的形式,从源文件一次读操作,通过管道方式使用内存中的文件流在不同任务间传递,最后写入目标文件I/O操作较少,
--------------------------------------------------------------------------------
/js_designpattern.md:
--------------------------------------------------------------------------------
1 | # 设计模式
2 | 设计模式是在开发过程不断地总结出的对于某类场景的通用解决方案或思路。
3 |
4 | ## 单例模式
5 | 保证仅有一个实例,并提供全局访问。
6 |
7 | ```
8 |
9 | function Single(name) {
10 | this.name= name;
11 | this.instance = null;
12 | }
13 | Single.init = function(name){
14 | if (!this.instance) {
15 | this.instance = new Single(name);
16 | }
17 | return this.instance;
18 | }
19 | var a = Single.init("惊鸿");
20 | ```
21 |
22 | ```
23 |
24 | var Single = (function () {
25 | var instance = null;
26 | function Single(name) {
27 | if (!instance) {
28 | this.name = name;
29 | instance = this;
30 | }
31 | return instance;
32 | }
33 | return Single;
34 | })();
35 | var a = new Single("惊鸿");
36 | var b = new Single("君彦");
37 | console.log(a === b);
38 | ```
39 | 违反单一职责原则,创建对象和管理实例逻辑在一起。
40 |
41 | - 惰性单例
42 |
43 | 在需要的时候才创建对象实例。
44 |
45 | ```
46 |
47 | var single = function(fn) {
48 | var instance = null;
49 | return function() {
50 | return result || (result = fn .apply(this, arguments));
51 | };
52 | };
53 | function createObj(name) {
54 | return {
55 | name: name
56 | };
57 | }
58 | single(createObj)("惊鸿");
59 | ```
60 |
61 | ## 策略模式
62 |
63 | 定义一系列算法,将他们封装,使其可以相互替换。
64 |
65 | ```
66 |
67 | var strategy = function(level) {
68 | if (level === 'top') {
69 | console.log('great');
70 | }
71 | if (level === 'middle') {
72 | console.log('good');
73 | }
74 | };
75 | ```
76 |
77 | > 策略模式的目的是将算法的使用与实现分离开来。策略模式一般把程序分为两部分:策略类,封装具体的算法实现;环境类,接收请求,将请求委托给某一策略类。
78 |
79 | ```
80 |
81 | //策略
82 | var strategy = {
83 | "top": function(name) {
84 | console.log("great " + name);
85 | },
86 | "middle": function(name) {
87 | console.log("good " + name);
88 | }
89 | };
90 |
91 | //环境
92 | var exec = function(level, name) {
93 | return strategy[level](name);
94 | };
95 | exec('top', '惊鸿'); //great 惊鸿
96 | exec('middle', '君彦'); //good 君彦
97 | ```
98 |
99 | ## 代理模式
100 |
101 | 代理和本地都显式地实现同一个接口。
102 |
103 | 图片预加载:
104 | ```
105 |
106 | var myImage = (function() {
107 | var imgNode = document.createElement('img');
108 | document.body.appendChild(imgNode);
109 | return {
110 | setSrc: function(src) {
111 | imgNode.src = src;
112 | }
113 | }
114 | })();
115 | var proxyImage = (function() {
116 | var img = new Image;
117 | img.onload = function() {
118 | myImage.setSrc(this.src);
119 | };
120 | return {
121 | setSrc: function(src) {
122 | myImage.setSrc('file:///C:/Users/loading.gif');
123 | img.src = src;
124 | }
125 | }
126 | })();
127 | proxyImage.setSrc('http://imgcache.qq.com/music/photo/k/000GGDys0yA0NK.jpg');
128 | ```
129 | 没有改变myImage的接口,通过代理对象,给系统添加新行为;给img节点设置src和图片预加载两个功能隔离在两个对象,互不影响。
130 | 单一职责原则,一个接口应该仅有一个引起它变化的原因。
131 | 开发-封闭原则,对调用开放,对修改封闭。
132 |
133 |
134 | 缓存代理:
135 | ```
136 |
137 | var mult = function() {
138 | var res = 1;
139 | for (var i = 0, l = arguments.length; i < l; i++) {
140 | res = res * arguments[i];
141 | }
142 | return res;
143 | };
144 | var plus = function() {
145 | var res = 0;
146 | for (var i = 0, l = arguments.length; i < l; i++) {
147 | res = res + arguments[i];
148 | }
149 | return res;
150 | };
151 |
152 | var proxyFactory = function(fn) {
153 | var cache = {};
154 | return function() {
155 | var args = Array.prototype.join.call(arguments, ',');
156 | if (args in cache) {
157 | return cache[args];
158 | }
159 | return cache[args] = fn.apply(this, arguments);
160 | };
161 | };
162 |
163 | var proxyMult = proxyFactory(mult);
164 | var proxyPlus = proxyFactory(plus);
165 | ```
166 | 还可以缓存ajax异步请求数据
167 |
168 | ## 享元模式
169 | 享元模式分离内部状态和外部状态;
170 | 对象池
171 |
172 | ## 发布-订阅模式
173 | var Event = {
174 | listen: fn,
175 | trigger: fn
176 | }
177 |
178 | ## 适配器模式
179 | 添加适配接口
180 |
181 | ## 装饰者模式
182 |
183 | ## 状态模式
184 | 允许对象在内部状态改变时改变其行为
--------------------------------------------------------------------------------
/preview.md:
--------------------------------------------------------------------------------
1 | # React入门与进阶之路由
2 |
3 | 在传统的网页应用中,一般是根据用户的操作指向不同的url,然后服务器渲染出不同的html代码,后来有了ajax,在同一页面里,可以为不同操作,指定处理器函数,在不刷新页面的情况下更新局部视图,但是局限依然较大,一旦跳转了URL,依然需要服务器渲染模板返回;而在Backbone,Angular,React出现以后,在单页面应用中,我们可以给不同URL指定处理器函数,保持URL与视图的同步,渲染模板的功能已经转移到客户端进行,与服务器的交互只涉及到数据,这就是路由的功能。
4 |
5 | ## React中的路由
6 |
7 | React是一个用户界面类库,仅相当于MVC模式中的V-view视图,其本身并不包含路由功能,但是它以模块的方式提供了路由功能,可以很好的与React进行协作开发,当然这也并不是必须使用的。现在很多单页应用框架都实现了各自的路由模块,如Backbone,Angular等。而这其中很多路由模块也能与React搭配使用。本文将介绍本人使用过的两种:Backbone.Router和react-router。
8 |
9 | 不使用路由模块,我们需要处理一个展示笔记列表和展示特定笔记对应不同视图时,React处理视图更新的方式大致如此:
10 |
11 | ```
12 |
13 | // 状态变量
14 | var NOTINGSTATUS = {
15 | SHOW: 0,
16 | EDIT: 1
17 | };
18 |
19 | // 模拟数据
20 | var notings ={
21 | 10001: {
22 | id: 10001,
23 | title: 'React',
24 | content: 'React Router',
25 | status: NOTINGSTATUS.SHOW
26 | },
27 | 10002: {
28 | id: 10002,
29 | title: 'Backbone',
30 | content: 'Backbone Router',
31 | status: NOTINGSTATUS.EDIT
32 | }
33 | };
34 |
35 | // 展示列表组件
36 | var NotingList = React.createClass({
37 | getInitialState: function() {
38 | return {
39 | notings: this.props.notings
40 | };
41 | },
42 | render: function() {
43 | var notings = this.state.notings;
44 | var _notingList = [];
45 |
46 | for (var key in notings) {
47 | _notingList.push();
48 | }
49 | return (
50 |
53 | );
54 | }
55 | });
56 | // 展示特定项组件
57 | var NotingItem = React.createClass({
58 | getInitialState: function() {
59 | return {
60 | noting: this.props.noting,
61 | status: this.props.noting.status
62 | };
63 | },
64 | editNote: function() {
65 | this.setState({
66 | status: NOTINGSTATUS.EDIT;
67 | });
68 | },
69 | render: function() {
70 | var status = this.state.status;
71 | var noting = this.state.noting;
72 |
73 | if (status === NOTINGSTATUS.EDIT) {
74 | return (
75 |
76 |
77 |
78 | );
79 | }else if (status === NOTINGSTATUS.SHOW) {
80 | return (
81 |
82 | {noting.title}
83 |
84 | );
85 | }
86 | }
87 | });
88 |
89 | React.render(
90 | ,
91 | document.querySelector('body')
92 | );
93 | ```
94 |
95 | 如上,没有路由模块管理,只是通过返回的组件状态变更,更新对应视图,随着应用越来越大处理会越发繁琐,接下来我们通过使用路由管理URL和视图的同步的方式来达到相同目的。
96 |
97 | ## Backbone.Router
98 |
99 | Backbone是一种MVC(Model-View-Controller)模式的框架,其路由模块属于Controller层,独立于其他模块,可以很好的与React搭配使用,之前的例子使用Backbone.Router实现后如下:
100 |
101 | ```
102 |
103 | var NOTINGSTATUS = {
104 | SHOW: 0,
105 | EDIT: 1
106 | };
107 |
108 | var NootingItemRouter = Backbone.Router.extend({
109 | routes; {
110 | 'notings': 'showNotings',
111 | 'notings/:id': 'showNoting'
112 | },
113 | render: function(status) {
114 | if (!status || status === NOTINGSTATUS.SHOW) {
115 | React.render()
116 | }
117 | },
118 | showNoting: function() {
119 | this.render()
120 | }
121 | });
122 | ```
123 |
124 |
125 |
--------------------------------------------------------------------------------
/git-install.md:
--------------------------------------------------------------------------------
1 | # Git由浅入深之安装与配置
2 |
3 | 上一篇介绍了版本控制系统相关知识,本篇主题是如何安装和配置Git。
4 |
5 | ## 使用
6 |
7 | 使用方式主要分为两种:
8 |
9 | - 原始命令行方式(使用命令行工具)
10 | - 图形界面方式(使用客户端)
11 |
12 | 目前有很多客户端工具可以使用如,但是大多数都只支持一些基本的操作,
13 |
14 | 为了更全面的学习和深入理解Git,我们主要介绍命令行方式,这才是合理打开Git方式。
15 |
16 | ## 安装
17 |
18 | [各安装包下载地址](https://git-scm.com/downloads)
19 |
20 | #### Linux
21 |
22 | ```
23 |
24 | sudo yum install git-all
25 | or for Ubuntu
26 | sudo apt-get install git-all
27 | ```
28 |
29 | [了解Linux更多类型安装方式](https://git-scm.com/download/linux)
30 |
31 | #### Mac
32 |
33 | Mac下可以有以下两种方式安装:
34 |
35 | - 安装Xcode命令行工具
36 | - [下载安装包](https://git-scm.com/download/mac)
37 |
38 | #### Windows
39 |
40 | Windows下安装方式主要有以下两种:
41 |
42 | - [下载安装包安装](http://git-scm.com/download/win)
43 | - [安装Github,Github安装包,既包含命令行,也包含GUI(即其客户端)](http://windows.github.com).
44 |
45 | 另外,还可以通过源码方式安装,但是比较麻烦,且对于学习和使用Git并无多大帮助,所以不做介绍,有兴趣可以搜索了解。
46 |
47 | ## 配置
48 |
49 | 当你看到这里时,我相信你的笔记本已经安装好了Git,直接进入本节主题:Git的自定义配置。
50 |
51 | > Git支持我们设置配置变量来对Git的外观和操作等诸多方面进行配置,而且配置会持久保存,你也可以随时更改配置。
52 |
53 | #### git config
54 |
55 | Git提供```git config```工具支持我们获取或设置Git配置变量,这些配置变量保存在三个不同地方:
56 |
57 | - /etc/gitconfig文件
58 |
59 | - 该文件包含系统上的每一个用户及其所有项目仓库的配置变量;
60 | - 使用```git config --system```时,读写的是此文件中的配置变量。
61 |
62 | - ~/.gitconfig 或 ~/.config/git/config文件
63 |
64 | - 特定用户的全局配置变量文件;
65 | - 使用```git config --global```时,读写此文件中配置变量;
66 | - 在Windows系统上,该文件在Git安装时指定的安装目录下,默认是在系统环境变量$HOME目录下,如C:\Users\$USER
67 |
68 | - .git/config文件
69 |
70 | - 特定项目仓库的配置文件
71 | - 存放在当前用户的Git目录中,Git目录在上一节中讲到。
72 |
73 | 以上三层配置优先级由低到高,即当前项目的配置优先于其他配置。
74 |
75 | #### 查看配置
76 |
77 | 我们可以查看Git当前配置列表,输入如下指令:
78 |
79 | ```
80 |
81 | git config --list
82 | ```
83 |
84 | 如图:
85 |
86 | 
87 |
88 | 当然,也可以查看知道配置项,如查看用户名称:
89 |
90 | ```
91 |
92 | git config user.name
93 | ```
94 |
95 | 
96 |
97 | #### 配置项
98 |
99 | 所有的配置都有两种方式设置,可自由选择:
100 |
101 | - 直接修改上文提到的配置文件;
102 | - 通过命令行进行设置
103 |
104 | 以下所有操作均通过命令行设置。
105 |
106 | ##### 用户信息配置
107 |
108 | 在使用Git前我们应该配置一下用户名和邮箱:
109 |
110 | ```
111 |
112 | git config --global user.name "惊鸿"
113 | git config --global user.email "jinghong@example.com"
114 | ```
115 |
116 | 这里使用了```--global```参数,是针对此计算机上用户的全局配置,如果我们希望在不同项目使用不同身份信息,则直接在该项目下配置:
117 |
118 | ```
119 |
120 | git config user.name "jh"
121 | git config user.email jh@example.com
122 | ```
123 |
124 | ##### 配置别名
125 |
126 | 有时候我们也许会觉得重复输入一些长指令,比较费劲,Git支持我们为其设置别名,需要使用```alias```指令,如:
127 |
128 | ```
129 |
130 | git config --global alias.co checkout
131 | ```
132 |
133 | 如上配置,是将Git的检出指令(checkout)命名别名为co,配置后,如下两个指令是等效的:
134 |
135 | ```
136 |
137 | git co xxx
138 | git checkout xxx
139 | ```
140 |
141 | 当然,我们不只是能对单个指令指定别名,还可以为复合指令指定别名,如:
142 |
143 | ```
144 |
145 | git config alias.acm '!'"git add . && git commit"
146 | ```
147 |
148 | 配置后```git acm```等效于如下两条指令:
149 |
150 | ```
151 |
152 | git add .
153 | git commit
154 | ```
155 |
156 | ##### 编辑器
157 |
158 | 我们也可以指定我们在Git编辑文本时使用的默认编辑器,如果不指定,则会使用系统的默认文本编辑器。
159 |
160 | 比如配置为notepad++,只需如下配置:
161 |
162 | ```
163 |
164 | git config --global core.editor "'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -nosession"
165 | ```
166 |
167 | **注意:需包围应用程序路径的单引号,以及windows默认的路径分隔符 \有转义的含义,所以要改成 / 。**
168 |
169 | 当然,我推荐你使用vim编辑,这样不需要考虑跨平台使用:
170 |
171 | ```
172 |
173 | git config --global core.editor vim
174 | ```
175 |
176 | 如上文所述,你还可以通过文件直接设置,如打开.git/config文件,在core中添加 editor=vim,查看.git/config文件:
177 |
178 | 
179 |
180 | ##### 帮助
181 |
182 | 可以使用Git帮助工具,查看某指令信息:
183 |
184 | ```
185 |
186 | git help
187 | or
188 | git --help
189 | or
190 | man git-
191 | ```
192 |
193 | 本篇介绍了不同环境下Git的安装及安装后的Git自定义配置,下一篇将会介绍Git的基础工作理论,敬请关注。
194 |
--------------------------------------------------------------------------------
/js_scope.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Scope
4 | permalink: js_scope.md
5 | description: introduce the JavaScript Scope
6 | date: 2016-01-01 09:55:23 +08:00
7 | tags: "share javascript notes"
8 | ---
9 |
10 | #JavaScript之作用域与作用域链
11 | 今天是2016的第一天,我们得扬帆起航踏上新的征程了。此篇阐述JavaScript中很重要的几个概念:作用域与作用域链及相关知识点。
12 |
13 | 我们先从变量与作用域的行为关系开始讨论。
14 |
15 | ##变量作用域
16 | JavaScript中,变量有全局变量及局部变量之分,而能定义变量作用域的语块只有函数。与局部变量有关的一种有趣特性,在此处不得不谈--变量提升。
17 |
18 | ###变量提升
19 | 变量提升为何物?
20 |
21 | > JavaScript的变量声明会被提升到它们所在函数的顶部,而初始化仍旧在原来的地方。JavaScript引擎并没有重写代码:每次调用函数时,声明都会重新提升。
22 |
23 |
24 | ```
25 |
26 | var name = 'Jog'; //全局变量
27 | function prison() {
28 | console.log(a); //输出undefined
29 | var a = 1;//局部变量
30 | console.log(a); //输出1
31 | console.log(name); //输出Jog
32 | }
33 | prison();
34 | ```
35 |
36 | ```
37 |
38 | var name = 'Jog';
39 | function prison() {
40 | console.log(name); //输出undefined
41 | var name = 'Hans';
42 | }
43 | prison();
44 | ```
45 | **此处name的声明被提升到函数的顶部,变量查找时先从局部作用域开始,未找到则由内而外最后到全局作用域。**
46 |
47 | 接下来我们详细分析一下JavaScript的提升方式。
48 |
49 | ###变量提升与执行环境对象
50 | 学习任何一门语言,都像学习魔术一样,初时引人迷惑,惊叹;然而当秘密被揭开时几乎令人失望,JavaScript不外如是。
51 |
52 | * 1. 提升
53 |
54 | 执行某代码块时,JavaScript引擎先解释,再运行。解释过程主要几个过程:
55 |
56 | - (1) 声明该作用域内var变量
57 | - (2) 声明并初始化函数参数
58 | - (3) 声明并初始化声明式函数
59 |
60 | *[详细可查看本系列笔记JavaScript之解释与执行机制](https://github.com/codingplayboy/javascript_notes/blob/master/js_compileRun.md)*
61 |
62 | * 2. 执行环境与执行环境对象
63 |
64 | **执行环境(execution context)**是一种概念,每当函数被调用都会产生一个新的执行环境。
65 |
66 | > **执行环境**定义了变量或函数有权访问的其他数据,决定了它们各自的行为。
67 |
68 | - 1. 每个函数都有自己的执行环境。 当执行流进入一个函数时,执行环境就被推入一个环境栈中;函数执行之后,栈将其执行环境弹出,控制权返回到之前的执行环境。
69 | - 2. 如果变量在当前执行环境内可访问,则该变量在当前作用域内。
70 | - 3. JavaScript访问变量,其实就是访问该执行环境对象(变量对象)中的属性。
71 | - 4. 全局执行环境是最外围的一个执行环境。
72 |
73 | > **执行环境对象**--每个执行环境都有一个与之对应的**变量对象**,执行环境中定义的所有变量和函数都保存在这个对象中。
74 |
75 | ```
76 |
77 | function fn(arg) {
78 | var name = 'Far';
79 | inner();
80 | function inner() {
81 | console.log('inner');
82 | }
83 | }
84 | fn('test');
85 | ```
86 | 在调用fn时,其过程如下
87 |
88 | - 1. 创建一个空执行环境对象;
89 | - 2. 声明参数并赋值;{arg: 1}
90 | - 3. 声明局部变量;{arg:1, name: undefined}
91 | - 4. 预定义声明式函数;{arg:1, name: undefined, inner: function(){console.log('inner');}}
92 | - 5. 代码执行时,局部变量被赋值;{...name: 'Far'...}
93 | - 6. 执行环境对象上变量和函数属性保持不变,调用inner函数时,其内部会创建一个新的执行环境对象,依此可递归形成一条作用域链。
94 |
95 | ##作用域与作用域链
96 |
97 | > 当一个变量在某执行回家内可以被访问,我们称该变量在当前**作用域**内。
98 |
99 | 代码某一执行环境中执行时,会创建该**执行环境对应的变量对象**的一个作用域链。
100 |
101 | > JavaScript引擎在执行环境对象中查找作用域内的变量或函数,其查找顺序由内而外向上直到全局执行环境对象,这个顺序就形成**作用域链**。
102 |
103 | 作用域链的**前端**,始终是当前执行环境对应的变量对象。若此执行环境是函数,则将其活动对象作为变量对象。作用域链中的**下一个**变量对象来自于当前变量对象的包含(外部)执行环境,如此一直到全局执行环境;全局执行环境的变量对象始终是作用域链中的**最后**一个变量对象。
104 |
105 | ```
106 |
107 | var age = 22;
108 | var country = 'China';
109 | var name = 'Java';
110 | var job = 'Web';
111 | function outer() {
112 | console.log(age); //输出22
113 | console.log(country); //输出undefined
114 | var country = 'Union';
115 | var name = 'Python';
116 | inner();
117 | function inner() {
118 | console.log(name); //输出Python
119 | console.log(job); //输出Web
120 | }
121 | }
122 | outer();
123 | ```
124 | 代码输出结果如上:
125 |
126 | - 1. outer函数执行时,首先在outer执行环境对象中查找age和country变量结果country存在但并未初始化赋值,输出undefined;而age未找到于是沿着作用域链向上到全局执行环境,在其变量对象中存在age属性,于是输出其值22.
127 | - 2. inner函数执行时创建自己的执行环境对象,其并没有定义name和job等变量,于是沿着作用域链向上到达outer函数的执行环境,在其变量对象中存在name于是输出其值Python;而未找到job于是继续向上直到全局执行环境,找到并输出其值,结束;若依然未找到,则会报错,停止运行。
128 |
129 | **注:函数参数亦被当作变量对待,故其访问规则与普通变量相同。**
130 |
131 | ###延长作用域链
132 |
133 | 某些语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行结束后移除。常见如:
134 |
135 | * try-catch语句;
136 | catch语句会创建一个新变量对象,包含被抛出的错误对象的声明。
137 | * with语句;
138 | with语句会创建一个包含语句接收对象的所有属性和方法的变量对象。
139 |
140 | ```
141 |
142 | function getAttr(data) {
143 | var obj = data;
144 | with(obj) {
145 | var o = location;
146 | }
147 | console.log(o);
148 | }
149 | getAttr(window);
150 | ```
151 | 上面with语句接收window对象,其创建的变量对象就包含了window对象所有属性和方法,于是可以在其执行环节直接访问location变量,也就是正常的window.location。
152 |
153 | *强烈建议不要使用with语句。*
154 |
155 | 本篇笔记阐述JavaScript执行环境与执行环境对象,变量对象,作用域与作用域链,耗时四小时,还有诸多不足之处待日后补充改进。
--------------------------------------------------------------------------------
/css_box_model.md:
--------------------------------------------------------------------------------
1 | # CSS盒模型(BOX Model)
2 |
3 | CSS盒模型描述的是为文档树中的元素创建并根据[CSS视觉格式化模型(visual formatting model)](http://blog.codingplayboy.com/2016/11/06/css_visual_formatting_model/)布局的矩形盒子。
4 |
5 | ## 盒子尺寸(dimensions)
6 |
7 | 每个盒子有一个内容区域(content area),如,文本,图片等,还包括可选的四周内间距,边框,外间距区域。每个区域的尺寸结构如下图(盗个图先):
8 |
9 | 
10 |
11 | 如上图,外间距,边框,内间距都被拆分成上下左右四部分。
12 |
13 | ## 边界
14 |
15 | 内容,内间距,边框,外间距四个区域都有四个边界(edge),分别是上右下左边界。
16 |
17 | ### 内容边界(content edge or inner edge)
18 |
19 | 内容边界围绕由盒子宽高占据的矩形,这通常由元素的渲染内容(rendered content)决定,四个内容边界定义了这个盒子的内容盒(content box)。
20 |
21 | #### 渲染内容(Rendered content)
22 |
23 | > The content of an element after the rendering that applies to it according to the relevant style sheets has been applied.
24 | How a replaced element's content is rendered is not defined by this specification.
25 | Rendered content may also be alternate text for an element (e.g., the value of the XHTML "alt" attribute), and may include items inserted implicitly or explicitly by the style sheet, such as bullets, numbering, etc.
26 |
27 | > 所谓渲染内容,就是对某个元素的内容根据相关样式表进行渲染。对于置换元素内容其渲染内容则有些不同,如```
```元素,若其图片加载失败,则渲染内容会被替换成其alt属性值,当然渲染内容也可能包含其他通过样式表插入的内容,如:after等伪元素插入的额外内容。
28 |
29 |
30 | ### 内间距边界(padding edge)
31 |
32 | 内间距边界围绕盒子的内间距,如果padding值为0,则内间距边界和内容边界重合,四个内间距边界定义了这个盒子的内间距盒(padding box)。
33 |
34 | ### 边框边界(border edge)
35 |
36 | 边框边界围绕盒子的边框,如果border宽度值为0,则边框边界与内间距边界重合,四个边框边界定义了这个盒子的边框盒(border box)。
37 |
38 | ### 外间距边界(margin edge or outer edge)
39 |
40 | 外间距边界围绕盒子的外间距,如果margin宽度为0,则外间距边界与边框边界重合,四个外间距边界定义了这个盒子的外间距盒(margin box)。
41 |
42 |
43 | ## 区域尺寸
44 |
45 | 一个盒子的内容区域尺寸,即内容宽度和高度,由以下因素决定:
46 |
47 | - 1.创建这个盒子的元素是否设置width和height属性
48 | - 2.这个盒子是否包含文本或其他盒子
49 | - 3.这个盒子是否是表格
50 |
51 | 内容,内间距和边框区域的背景样式由创建盒子的元素的background属性值决定,而外间距的背景总是透明的。
52 |
53 | ### margin
54 |
55 | margin属性定义一个盒子的外间距区域的宽度,分为margin-top, margin-right, margin-bottom, margin-left四部分,其值可以是一个固定长度也可以是百分比值或auto,允许负值。
56 |
57 | - 长度
58 |
59 | 一个固定长度值,如10px
60 |
61 | - 百分比
62 |
63 | 可以定义一个百分比值,这个百分比是相对于这个盒子的包含块的宽度。
64 |
65 | - auto
66 |
67 | 自动计算
68 |
69 | 该属性值对非置换行内元素无效。
70 |
71 | - 用法:
72 |
73 | 属性值如果是一个值,适用于上右下左四部分;如果是两个值,则第一个值是上下的值,第二个是左右的值;如果是三个值,则第一个为上值,第二个为左右值,第三个为下值;如果是四个值,则依次为上右下左值。
74 |
75 | #### 折叠(collapse)margin
76 |
77 | CSS中,两个或多个相邻的外间距,之间会发生崩塌,形成一个单一的最大外间距,这就是折叠(collapse)。详见[CSS格式化上下文](http://blog.codingplayboy.com/2016/11/05/css_formattingcontext/)。
78 |
79 | ### padding
80 |
81 | padding属性定义一个盒子的内间距区域的宽度,分为padding-top,padding-right,padding-bottom,padding-left四部分。其值可以是一个固定长度也可以是百分比值,不允许负值。
82 |
83 | - 长度
84 |
85 | 一个固定长度值,如10px
86 |
87 | - 百分比
88 |
89 | 可以定义一个百分比值,这个百分比是相对于这个盒子的包含块的宽度。
90 |
91 | ### border
92 |
93 | border属性定义一个盒子的边框区域的宽度(border-width),颜色(border-color),风格样式(border-style),border属性是这三个属性的简写,分为border-top,border-right,border-bottom,border-left四部分。
94 |
95 | #### border-width
96 |
97 | 定义边框宽度,其值可以为thin或medium或thick或一个长度值,不允许负值。该属性包括border-top-width, border-right-width, border-bottom-width, border-left-width四部分,如:
98 |
99 | ```
100 |
101 | div { border-width: thin } /* thin thin thin thin */
102 | div { border-width: thin thick } /* thin thick thin thick */
103 | div { border-width: thin thick medium } /* thin thick medium thick */
104 | ```
105 |
106 | #### border-color
107 |
108 | 定义边框颜色,其值可以为一个color值或transparent
109 |
110 | - color
111 |
112 | 可以为十六进制颜色值或rgb,rgba,hsl,hsla等值。
113 |
114 | - transparent
115 |
116 | 该值表明边框为透明的。
117 |
118 | - border-style
119 |
120 | - none
121 |
122 | 无边框,边框宽度的计算值为0。
123 |
124 | - hidden
125 |
126 | 同 'none'。
127 |
128 | - dotted
129 |
130 | 点边框
131 |
132 | - dashed
133 |
134 | 虚线边框
135 |
136 | - solid
137 |
138 | 单实线边框
139 |
140 | - double
141 |
142 | 双实线边框
143 |
144 | - inset
145 |
146 | 内嵌
147 |
148 | - outset
149 |
150 | 和'inset'相反: 外散边框
151 |
152 | ## 行内元素的盒模型
153 |
154 | 在每一个行盒中,用户代理(如浏览器)必须为每个元素创建行内盒并且按照视觉顺序渲染盒子的外间距,边框和内间距。
155 |
156 | ### direction
157 |
158 | 当元素的direction属性为ltr时,第一个行盒创建的最左边的盒子拥有左外间距,左边框,左内间距,最后一个行盒的最右的的盒子拥有右外间距,右边框,右内间距;
159 |
160 | - 当元素direction属性值为rtl时,第一个行盒创建的最右边的盒子拥有右外间距,右边框,右内间距,
161 | - 最后一个行盒的最左的的盒子拥有左外间距,左边框,左内间距。
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/expand_more.md:
--------------------------------------------------------------------------------
1 | # 优雅的使用Js或CSS处理文本的截断与展示
2 |
3 | 之前遇见一个问题,就是处理文本截断,然后可以手动切换文本是全展示和手动展示,因为这个问题比较常见,而且其实现方式有多种,于是决定总结一下,与读者分享。
4 |
5 | ## 前言
6 |
7 | 首先,我们看这样一个场景:
8 |
9 | 
10 |
11 | 其html 结构如下:
12 |
13 | ```
14 |
15 |
16 | 郑成月的经历就是一部中国社会历史!很有价值的!不管是社会研究还是真心纠错,都是非常好的案例。历史就是用各种个人经历写成的,那样就很有实在感。作家们没有素材?都在书写歌功颂德之文?想要把自己的作品流传后世,这就是最好的素材
17 |
18 |
19 | ```
20 |
21 | 样式如下:
22 |
23 | ```
24 |
25 | .text-slice {
26 | display: -webkit-box;
27 | -webkit-box-orient: vertical;
28 | -webkit-line-clamp: 3;
29 | overflow: hidden;
30 | text-overflow: ellipsis;
31 | }
32 | ```
33 |
34 | 如图,我们对文字默认展示内容有限制:限制默认最多显示三行,未超出三行时不需要展示更多按钮;超出内容被截断时,可以点击更多,展示全部内容,此时更多文字变成取消,再次点击的时候文字收起。
35 |
36 | 实现上述功能,常见的是使用JavaScript,本文将介绍使用JavaScript和CSS共三种方式实现:
37 |
38 | - Js实现
39 | - CSS :target伪类 实现
40 | - CSS :checked伪类 + ~(临近兄弟节点选择符)实现
41 |
42 | ## Js实现
43 |
44 | 先从最常见的Js实现,通常我们绑定点击事件实现切换文本截断与展示全部:
45 |
46 | [点击查看效果](http://demo.codingplayboy.com/demo/smallcase/expand_more/expand-js.html)
47 |
48 | ```
49 |
50 |
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 | .fake-content {
92 | position: absolute;
93 | z-index: -1; /* 隐藏 */
94 | opacity: 0; /* 透明 */
95 | pointer-events: none; /*元素不可交互/点击*/
96 | }
97 | ```
98 |
99 | 然后比较此元素在设置截断样式和不设置截断样式时高度,相等即不会发生截断,不相等即发生截断:
100 |
101 | ```
102 |
103 | // 文本是否发生截断
104 | function hasTextSliced($ele) {
105 | var initHeight = $ele.height();
106 | var height;
107 | $ele.removeClass('text-slice'); // 删除截断样式
108 | height = $ele.height();
109 |
110 | if (initHeight < height) {
111 | // 发生截断
112 | return true;
113 | }
114 |
115 | return false;
116 | }
117 | ```
118 |
119 | 如上,在删除截断样式后,若高度变大,则说明发生文本截断,否则不发生截断。
120 |
121 | ## CSS实现
122 |
123 | CSS可以有两种方式实现:
124 |
125 | - :target伪类 实现
126 | - :checked伪类 + ~(临近兄弟节点选择符)实现
127 |
128 | [点击查看实例](http://demo.codingplayboy.com/demo/smallcase/expand_more/expand-js.html)
129 |
130 | ### :target伪类
131 |
132 | 我们知道HTML中,a链接可以设置锚点,点击后该锚点可以使用```:target```伪类选择获取,于是可以为其设置文字不截断样式:
133 |
134 | ```
135 |
136 | #content:target {
137 | overflow: auto;
138 | display: block;
139 | }
140 | ```
141 |
142 | 其html结构如下:
143 |
144 | ```
145 |
146 |
147 | ...
148 |
149 |
150 | ...
151 |
152 | 更多
153 | ```
154 |
155 | ## :checked伪类 + ~选择符
156 |
157 | 此种方式原理是,选择框可以使用CSS伪类```:checked```获取,然后通过```~```选择符給元素设置样式不截断文本:
158 |
159 | ```
160 |
161 | #expand-check:checked ~ .content {
162 | overflow: auto;
163 | display: block;
164 | }
165 | ```
166 |
167 | html结构如:
168 |
169 | ```
170 |
171 |
172 |
173 | ...
174 |
175 |
176 | ...
177 |
178 |
179 | ```
180 |
181 | 如上,通过在文本前面添加一个隐藏的·```元素```,在更多按钮中使用label的for属性,通过设置```