GithubHelp home page GithubHelp logo

blog's People

Contributors

acrens avatar

Watchers

 avatar  avatar  avatar  avatar

blog's Issues

line-height 的取值方式

line-height 取值方式

相信很多前端er都使用过 line-height 来设置行高布局。下面看看官方定义:

On block level elements, the line-height property specifies the minimum height of line boxes within the element.On non-replaced inline elements, line-height specifies the height that is used to calculate line box height.

有时候我们在开发的时候并没有太深入的去了解一个属性,比如:line-height 的不同取值达到的效果并不同,下面依次看看常用的几种取值方式。å


px 单位取值

line-height: 26px 目的就是直接定义目标元素的行高为 26px 的高度。


% 百分比取值

line-height: 150% 一般用该方式定义目标元素的行高会配合 font-size: 14px 属性使用,因为用百分比当前元素的行高为 1.5 * 14px = 21px。且如果其层叠子元素没有定义 line-height 属性,不管有没有定义 font-size 属性,其层叠子元素行高均为 21px(与自身的 font-size 没有任何关系)。


倍数取值

line-height:1.5 用该方式一般也是配合 font:14px 属性使用,但是对层叠子元素的影响效果并不同,如果层叠子元素没有定义 line-height 属性,但是定义了 font-size 属性,那这些层叠子元素的行高为继承过来的 line-height 倍数值乘以自身的 font-size 属性。


总结

一般情况下,为了更加方便及清晰的使用 line-height,使用倍数取值是最佳的设置方式,如:body {font: 12px/1.5 tahoma,arial,"\5b8b\4f53"}。

bootstrap兼容IE8解决方案

背景

很多项目会使用到bootstrap框架,bootstrap可以兼容IE低版本,通过respond.js可以解决IE对bootstrap的兼容问题,但问题来了,一般大型项目都是将前端资源文件和主站服务区分放入不同服务器,资源文件一般通过CDN访问,这个时候如果通过respond.js去解决IE兼容性问题是无效的。

问题

对于一个项目而言,如果前端资源和主站服务不在同一个域名上,则respond.js解决bootstrap兼容性是无效的。

解决方案

假设网站应用域名为example.dxy.com
前端资源服务器域名为static.db.com
首先下载:cross-domain-files

在页面上引入styles、respond.js后面加上下载的三个文件即可以解决IE下respond.js无效问题:
respond.proxy.gif、respond.proxy.js 应该放在example.dxy.com域名任意可访问的目录下;
respond-proxy.html 应该放在前端资源服务器static.dxy.com域名目录下;

如:

<script src="http://example.dxy.com/assets/respond.proxy.js"></script>

回车键导致form提交问题

问题来源

最近在开发项目时,编写一个简单的登录页面,HTML页面上只有一个文本框和一个提交按钮,文本框需要支持Enter按键ajax提交。在这里我就纳闷的出了问题,我编写好了判断是否文Enter按键的JS提交事件,最后实现的效果是每次按下Enter按键,form表单自动提交并刷新页面,我却一直不知道为什么,后来查了资料,就有如下问题。

问题描述

在编写HTML中form表单代码时,这样的页面有时候键盘回车键在文本框中触发时会自动交form表单情况,最终查阅资料发现有如下情况会自动enter按键提交form表单,无需编写JS。这里是示例代码:form-auto-submit

结果

1.如果form表单里有type为submit的按钮存在,一个文本框还是多个文本框都提交生效。

2.如果form表单里面只有一个type="text"的input文本框,不管按钮是什么type,回车键生效。

3.如果按钮不是input,而是用button,并且没有加type,IE下默认为type=button,Chrome默认为type=submit。

4.对于其它表单元素,如textarea、select不影响,radio、checkbox不影响触发规则,但本身在Chrome下会响应回车键,在IE下不响应。

5.最奇怪的是如果有type="image"的input,效果等同于type="submit"。

初探 Promise

初探 Promise


曾经有伟人说过,对于一件新鲜事物,如果需要搞明白他,就会有以下三个步骤:What、How、Why(学习、思维三部曲 或 叫做学习黄金圈);而对于很多人,在学习一门技术时,都停留在 What 阶段,到使用时就不知道如何使用,就算使用了也不知道为什么要用。
黄金圈


What(Promise 是什么)

描述

Promise 是抽象异步处理对象以及对其进行各种操作的组件,而且 Promise 并不是从 JavaScript 中发祥的概念。

状态

Promise 具有三种状态,分别为 pending(执行中)、resolved(被接受)、rejected(被拒绝)。

方法

实例化:

  • var promise = new Promise(function(resolve, reject) {});
  • Promise.resolve() 等方法均可以直接返回一个新创建的 Promise 对象。

静态方法:Promise.all、Promise.race、Promise.resolve、Promise.reject:

  • Promise.all()

    Promise.all 方法为 Promise 组件的静态方法,无需创建 Promise 对象就可以直接使用此方法来并行执行多个 Promise 对象,且在 Promise.all(["Promise1","Promise2", "Promise2"]),如果在 all 方法参数的数组中有一个 Promise 对象执行失败即停止执行,返回结果需要等到数组对象执行完成才返回最后结果,结果为多个 Promise 对象返回值组成的数组。

    代码:
    var p1 = Promise.resolve(1);
    var p2 = Promise.resolve(2);
    var p3 = Promise.resolve(3);
    Promise.all([p1, p2, p3]).then(function(results) {
    console.log(results); // [1, 2, 3]
    });

  • Promise.race()

    Promise.race 方法性质同 Promise.all 方法,使用方式也一样,但是有一点不同是在 Promise.race(["Promise1","Promise2","Promise3"]) 等到数组参数里面第一个 Promise 对象执行完成就返回执行结果(这里说的第一个不是第一个参数,也可能是第二个,是指第一个执行完成的 Promise 对象)。
    代码:Promise.race([new Promise(), new Promise(), new Promise()]);

  • Promise.resolve()

    这是一种直接到达 Promise resolved 状态的快捷方式,并且创建返回一个 Promise 对象。
    代码:
    Promise.resolve("acrens").then(function(name) {
    console.log(name); // acrens
    });

  • Promise.reject()

    同理,这是达到 Promise rejected 状态的快捷方式,并且创建返回一个进行 reject 的新 Promise 对象。如果传入的参数为一个 Promise 对象,则返回的是一个新的 Promise 对象(和 resolve 不同)。
    代码:Promise.reject(new Error("error"));

对象方法:new Promise().then、new Promise().catch:

  • then()

    用于注册 Promise 分别达到 resolved、rejected 状态时的回调函数,如:then(resolve, reject),当达到 resolved 状态时,执行 resolve 方法,否则,执行 reject 方法;reject 函数可以不在此注册,可以使用 catch 注册(这也是注册 reject 方式的语法糖,更方便 Promise 链方法);如果不需要注册 resolved 状态时的回调函数,then 方法第一个参数不可以省略,但是可以 then(undefined, reject) 这样书写。
    代码:
    var promise = new Promise(function(resolve, reject) {
    resolve(2);
    });

    promise.then(function(value) {
    console.info('Task --------- ' + value); // Task --------- 2
    }).catch(function onRejected(error) {
    console.error(error);
    });

  • catch()

    catch 方法在此就不多赘述,其只是注册 rejected 状态回调函数的语法糖。
    代码:(参照上面 then 方法代码示例)。


How(Promise 如何运行)

Promise 从实例化到执行完成可以参照下图并结合上述代码理解(只有认真地去理解这个流程图,才可以看到 Promise 的精髓,坏笑...):
执行流程
注意:fulfill 就相当 resolved 状态。


Why(Promise 为什么会产生)

Promise 需要解决的问题也就是其产生的原因(废话):

  • 异步问题

    用异步的方式来表达异步的代码是艰难的,甚至很难用我们的大脑来理解。(事件轮询、并发模式)

  • 回调地狱

    并不是简单地理解为代码嵌套,编辑器代码缩进空格;还包括代码的控制转移(如在回调之前进行的第三方调用,控制权转交给第三方)。


总结

在项目开发中,时常会使用到异步处理及代码多层嵌套,这对于后期理解和维护代码是一个“坑”,因此可以尝试使用 Promise 方式去解决代码给后期带来的负担。

注:下一篇更新 Promise 扩展阅读版

JS 中 TDZ 的理解

春节快到了,假期也快到了,空闲之余刷个微博,看见 @ruanyf 提出了一个问题与 TDZ 有关,但是貌似阮大当时还没有意识到这个问题,多亏一些其他业内同仁提出了与 TDZ 相关;当然,以阮大的能力这都不是事。由于当时我本身也还不知道 TDZ 这一回事没有看懂,所以就花了一些时间去搞清楚什么是 TDZ 及TDZ会带来一些什么问题,本文主要是用于介绍我对 TDZ 的一些理解,如有问题,多谢指出。

示例

  • 案例一

    1. 代码
    let y = 1;
    function foo(x = y, y) {
        console.log(x);
    }
    foo();  // ReferenceError: y is not defined
    1. 解读
      • 当函数存在默认参数时,且调用方法不传任何参数,会存在三个作用域环境;
      • 全局作用域、参数作用域、函数体作用域;
      • 当执行 foo 函数时,参数作用域在 x = y 之后才定义 let y,注意:let 定义,所以根据 let 定义变量的作用知道 x = y 肯定会报错;
    2. 代码翻译:将以上代码翻译之后可以按下面代码片段阅读更易于理解
    function analysis() {
        "use strict";
        let y = 1;
    
        function foo() {  
            let x = arguments[0] !== (void 0) ? arguments[0] : y;   // y not defined
            let y = arguments[1];
        }
        foo();
    
        return {};
    }
  • 案例二

    1. 代码
    let y = 1;
    function foo(x = function(){console.log(y)}, y = 2) {
        x(); // 2
        y = 3;
        x(); // 3
    }
    foo();
    console.log(y); //1
    1. 解读
      • 当函数存在默认参数时,且调用方法不传任何参数,会存在三个作用域环境;
      • 全局作用域、参数作用域、函数体作用域;
      • 当执行 foo 函数时,x 被申明为匿名函数变量,此时函数并未被执行,所以正常;之后定义 y 值为 2,此时调用 x() 输出的当然是变量 y 的值,之后继续修改 y 的值,再继续调用 x(),输出 y 最新值 3;当执行外部 console.log(y) 时并不能访问内部函数变量,访问的变量是当前域下的 y = 1 的值 1,所以输出 1;
    2. 代码翻译:将以上代码翻译之后可以按下面代码片段阅读更易于理解
    function analysis() {
        "use strict";
        let y = 1;
    
        function foo() {  
            let x = arguments[0] !== (void 0) ? arguments[0] : function() {
                console.log(y);
            };
            let y = arguments[1] !== (void 0) ? arguments[1] : 2;
            x(); // 2
            y = 3;
            x();    // 3
        }
        foo();
        console.log(y); // 1
    
        return {};
    }
  • 案例三

    1. 代码
    let y = 1;
    function foo(x = function(){console.log(y)}) {
        let y = 3;
        x(); // 1
    }
    foo();
    1. 解读
      • 当函数存在默认参数时,且调用方法不传任何参数,会存在三个作用域环境;
      • 全局作用域、参数作用域、函数体作用域;
      • 当执行 foo 函数时,x 被赋值为一个匿名函数的变量,且存在与参数作用域内,let y = 3 会被定义到函数体作用域内,属于参数作用域的内部函数;当 x() 执行时是在函数体作用域定被调用,但是其定义是在参数作用域,所以执行环境是在参数作用域内,此时在参数作用域没有定义 y 变量,也不能访问内部函数 funBody 内部定义的变量 y,此时往上级函数查找是否存在 y 被定义,如果被定义则输出其值,所以输出最外层变量 y 的值 1;
    2. 代码翻译:将以上代码翻译之后可以按下面代码片段阅读更易于理解
    function analysis() {
        "use strict";
        let y = 1;
    
        function foo() {  
            let x = arguments[0] !== (void 0) ? arguments[0] : function() {
                console.log(y);
            };
    
            function funBody() {
                let y = 3;
                x();
            }
            funBody();
        }
        foo();
    
        return {};
    }
  • 案例四

    1. 代码
    function foo(x = function(){console.log(y)}) {
        let y = 3;
        x(); // // ReferenceError: y is not defined
    }
    foo();
    1. 解读
      • 当函数存在默认参数时,且调用方法不传任何参数,会存在三个作用域环境;
      • 全局作用域、参数作用域、函数体作用域;
      • 当执行 foo 函数时,x 被赋值为一个匿名函数的变量,且存在与参数作用域内,let y = 3 会被定义到函数体作用域内,属于参数作用域的内部函数;当 x() 执行时是在函数体作用域定被调用,但是其定义是在参数作用域,所以执行环境是在参数作用域内,此时在参数作用域没有定义 y 变量,也不能访问内部函数 funBody 内部定义的变量 y,此时往上级函数查找是否存在 y 被定义,如果被定义则输出其值,否则报 y 没有被定义错误,此案例只是案例三的一种测试;
    2. 代码翻译:将以上代码翻译之后可以按下面代码片段阅读更易于理解
    function analysis() {
        "use strict";
        function foo() {  
            let x = arguments[0] !== (void 0) ? arguments[0] : function() {
                console.log(y);
            };
    
            function funBody() {
                let y = 3;
                x();
            }
            funBody();
        }
        foo();
    
        return {};
    }

参考

以上核心部分在代码翻译部分,通过配合一下资料及个人的理解,翻译出通俗易懂的代码:

Versions for Mac SVN file locked

问题

Versions for Mac,通过 Versions 管理 SVN 代码,昨晚在更新代码的过程中未更新完成被强制退出,导致项目目录文件被锁(locked),此时如果更新代码会提示工作目录被锁。在网上找了很多种解决方案,有一个方案解决了我的问题:


方案:http://www.jianshu.com/p/9adcc352e3e6


可能涉及知识:
1、显示目录隐藏文件:defaults write com.apple.finder AppleShowAllFiles -bool true;
2、重启 Finder:killall Finder。

2015总结

时光荏苒,犹如白驹过隙。过去的时间不能追回,未来的时间不能逾越,唯有珍惜眼前才是最切实际。

说到2015年,经历了很多事情,因为这也算是“真正的”走出了校门,踏入社会。我也像大多数刚毕业的学生一样,怀有一颗赤子之心,认为社会是多么的美好。也一样怀有自己的梦想,俗话说:梦想是要有得,万一实现了呢?

2015,我就怀着这样一颗心,开始追逐自己的梦想,就在今年4月份,我辞去了母校所在城市的工作,独自来到美丽的杭州。其实在辞去工作这段时间心里还是很不舒服的,第一、有点舍不得从校园一起走出来的同学,第二、对原来公司的意见确实蛮大的(算了,无力吐槽,Too young Too Simple)。这是2015记忆比较深得第一件事。

2015,我初次来到杭州,由于所学专业为互联网相关,自然寻找的是互联网相关工作。相比以前呆的城市,我在杭州寻找工作那段时间,完全体会到了互联网时代优秀人员的缺乏,从某一方面也反应出了学校对于人才培养方式的欠缺。其实,我现在所呆的公司,之前应聘我是被刷的,当然,也有其他创业公司给到offer,薪资也很似诱人,考虑到未来的发展,我也寻求了朋友的意见(这里得感谢@正常人够我富舆论性么 ),我最终选择再次请求@丁香园 给我面试机会。这是2015记忆比较深的第二件事。

2015,工作是找到了,没地方住,还好高中同学@邱望收留了我,一住就是两个月,两个人挤着不到10㎡的房间(反正很小),当时我也是厚着脸皮住了,哈哈哈。那两个月真心的感谢他。

2015,最让我感动的事情就是下面要总结的事情了,女朋友反抗她爸妈对她得叮嘱来到我的身边了,当时来了之后,其实还是蛮感动得。就冲这一点,我是该对她更用心,更好些。看到这里,是不是有些矫情了。这是2015记忆比较深的第三件事。

2015,让我比较不是很满意的就是学习(特别不满意),初定的计划都未能坚持,书籍未看完,视频未看完,该学习的都未学习完成,得反省反省。有时候也开始学着写一些东西分享出去,这一点2015年算是完成了一部分吧,还算满意。

2015,工作上自己还是比较满意,有很好的团队,也有很好的工作提供锻炼,自己也很好的完成了。工作这段时间,自己也干得比较开心,自由让我工作效率更加的好,这也是自己比较喜欢的一种方式。

再见2015,你好2016

致2016的自己:
多看些书,多几次旅行,多看些电影,多打些电话,多交些朋友,多赚些钱......

浅谈网站性能之前端性能优化

浅谈网站性能之前端性能优化

性能优化的目的无非是减少用户流量消耗,提升用户首屏体验,提升用户访问速度,让用户专注内容本身。

前端性能优化

  • 减少 HTTP 请求数量
    基本原理:在浏览器与服务器进行通信时,主要是通过 HTTP 进行通信。浏览器与服务器需要经过三次握手,每次握手需要花费大量时间。而且不同浏览器对资源文件并发请求数量有限(不同浏览器允许并发数),一旦 HTTP 请求数量达到一定数量,资源请求就存在等待状态,这是很致命的,因此减少 HTTP 的请求数量可以很大程度上对网站性能进行优化。
  1. CSS Sprites
    国内俗称 CSS 精灵,这是将多张图片合并成一张图片达到减少 HTTP 请求的一种解决方案,可以通过 CSS background 属性来访问图片内容。这种方案同时还可以减少图片总字节数,节省命名词汇量(由命名多张图片文件变成一张,哈哈哈)。
  2. 合并 CSS 和 JS 文件
    现在前端有很多工程化打包工具,如:grunt、gulp、webpack等。为了减少 HTTP 请求数量,可以通过这些工具再发布前将多个 CSS 或者 多个 JS 合并成一个文件。
  3. 采用 lazyLoad
    俗称懒加载,可以控制网页上的内容在一开始无需加载,不需要发请求,等到用户操作真正需要的时候立即加载出内容。这样就控制了网页资源一次性请求数量。
  • 控制资源文件加载优先级
    基本原理:说到这里就需要知道浏览器加载 HTML 内容的原理,浏览器在加载 HTML 内容时,是将 HTML 内容从上至下依次解析,解析到 link 或者 script 标签就会加载 href 或者 src 对应链接内容,为了第一时间展示页面给用户,就需要将 CSS 提前加载,不要受 JS 加载影响。
  1. 遵循原则:主要文件放在 head 内部,次要文件放在 body 底部。一般情况下都是 CSS 在头部,JS 在底部。
  • 利用浏览器缓存
    基本原理:浏览器缓存分强缓存和协商缓存,他们是将网络资源存储在本地,等待下次请求该资源时,如果命中就不需要到服务器重新请求该资源,直接在本地读取该资源。
  1. 强缓存:在 web 服务器返回的响应中添加 Expires 和 Cache-Control Header。
  2. 协商缓存:通过【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】这两对 Header 分别管理。
  • 使用 CDN
    基本原理:CDN的全称是Content Delivery Network,即内容分发网络
  • 减少重排(Reflow)
    基本原理:重排是 DOM 的变化影响到了元素的几何属性(宽和高),浏览器会重新计算元素的几何属性,会使渲染树中受到影响的部分失效,浏览器会验证 DOM 树上的所有其它结点的 visibility 属性,这也是 Reflow 低效的原因。如果 Reflow 的过于频繁,CPU 使用率就会急剧上升。
  1. 减少 Reflow,如果需要在 DOM 操作时添加样式,尽量使用 增加 class 属性,而不是通过 style 操作样式。
  • 减少 DOM 操作
  • 图标使用 IconFont 替换

花絮

在开始提笔写这篇博客前就遇到了一个很棘手的问题,这篇博客标题叫什么,思考了一会,我心里冒出了三个答案:

  • 浅谈网站性能优化
    第一个标题网站性能优化,一看标题可以理解为是讲网站性能,而且是对网站进行优化,描述的是一种解决方案,然而网站性能包括的太多了,超出了我的知识范畴,所以放弃。

  • 浅谈网站性能之前端性能优化
    第二个标题正适我怀,答题概括了我本期博客内容,既有性能介绍,又有前端性能优化解决方案。

  • 浅谈前端性能优化
    第三个标题前端性能优化,心想这不就是我要写的内容嘛,等我写完内容发现,不对,我写的内容不仅仅是解决方案,好包括的其他内容,所以放弃。

注:原文

以上内容仅为个人理解,如果本内容大家觉得哪里写的不对,望大家指出,供一起讨论。

apache font-face跨域配置方法

问题描述

在大型项目开发中,可能存在这类问题,前端代码和服务器代码分离,前端代码在前端资源服务器通过CDN访问,作为一个前端人员,不管修复BUG还是开发新功能,可能需要把前端资源拉到本地开发,绑定本机测试,这个时候浏览器访问系统会存在font-face跨域加载失败,看上去太怪了。

解决办法

1、mac可以通过 open -a "Google Chrome" --args --disable-web-security 此命令避免问题,如果别人也要绑定你本机访问,再叫别人这样访问,那太 low。

2、本机 apache 配置所有域均可正常访问 font-face
cd /private/etc/apache2/
vim httpd.conf

添加到文件:
<FilesMatch ".(ttf|ttc|otf|eot|woff|font.css)$">

Header set Access-Control-Allow-Origin "_" #_为

找到
添加到其内部:
AddType application/vnd.ms-fontobject .eot
AddType font/ttf .ttf
AddType font/otf .otf
AddType application/x-font-woff woff

mac apache配置其他所有自定义文件类型跨域,比如tpl后缀

打开 httpd.conf ,找到 LoadModule headers_module libexec/apache2/mod_headers.so,去除前面的#;
在同目录 extra 下找到 httpd-vhosts.conf 对应服务虚拟机,如:<VirtualHost *:80> 里面添加 Header set Access-Control-Allow-Origin * 支持所有域名。

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.