zhehua's note


  • 首页

  • 时光

  • 分类

  • 标签

  • 作品

  • 站点

  • 随想

  • 关于

Javascript原生释疑

发表于 2018-07-10 | 分类于 JAVASCRIPT

1.ES基础知识

  1. JS的基本数据类型

    • Boolean

    • String

    • Number

    • Null

    • Undefined

    • Symbol(ES6)

      注:原始类型不包含Object

      typeof

      1
      2
      3
      4
      5
      6
      typeof xxx;
      //返回:undefined boolean number string object function、symbol 只比基本类型多了object和function
      //注意点:
      //1.typeof null结果是object
      //2.typeof [1, 2]结果是object typeof 没有array类型 引用类型只有function和object
      //3.typeof Symbol() 用typeof获取symbol类型的值得到的是symbo

      instanceof

      1
      xxx instanceof Array //true or false

      instanceof和typeof的细节,可以移步这里

1. offsetWidth、clientWidth、scrollWidth、width的区别

属性值 说明
offsetWidth 真实的width+padding+border
clientWidth 真实的width+padding
style.width 返回DOM真实的width
scrollWidth 返回元素的宽度(包括元素宽度、内边距和溢出尺寸,不包括边框和外边距),无溢出的情况,与clientWidth相同

MVC,MVP,MVVM的区别

发表于 2018-07-04 | 分类于 架构

今天看到一篇关于探讨MVC,MVP,MVVM的文章,我觉得讲的还是蛮透彻的,值得收藏,下面是我对它的一些摘抄,和自己的一些小小见解。

前端MVC和后端MVC

前端MVC和后端MVC

该图摘自文章,我觉得很清晰明了,讲清楚了前后端的mvc具体指的什么,不过需要指出的是,后端的MVC中的V目前很少使用了,因为逻辑的复杂性,统一交给前端的MVC去处理,而后端主要使用Model和Controller层,最后以Restful API的形式提供给前端,特别是目前的微服务概念很火,前后分离成为必然。

注:Restful只是实现的一种形式,当然以nodejs把前端在服务端进行渲染(SSR),能够提高页面的性能,这时后端的V就变得厚重的多了。

前端MVC,MVP和MVVM的区别

前端MVC,MVP和MVVM

MVC,MVP,MVVM的区别

MVC架构

MVC

  • View,对外暴露函用户事件监听的接口,并监听Model的数据改变事件,依赖于Model
  • Controller,不对外暴露任何接口,监听View的用户事件,并对Model的接口了如指掌,依赖于Model和View
  • Model,对外暴露函数调用接口和事件监听接口,不依赖Controller和View

MVC中之间的耦合性相对较高,比如在Controller层直接操纵View层过多,Controller层就变的难为维护了,所以在Model层和View层中定义接口进行交互,便于维护,这一层就是Presenter层,也就是MVP架构。

MVP架构

MVP

  • Model,对外暴露函数调用接口和事件监听接口,对Presenter和View的存在一无所知,所以不依赖Presenter和View
  • View,对外暴露函数调用接口和事件监听接口,对Presenter和Model的存在一无所知,所以不依赖Presenter和View
  • Presenter,不对外暴露任何接口,监听View和Model的事件,并对它们的接口了如指掌,所以依赖于Model和View

一旦接口过多,也是相当复杂,如果Model层中的模型变动,View层能够相应的自动发生变动该多好?所以产生了MVVM。

MVVM架构

MVVM架构

  • Model,对外暴露函数调用接口和事件监听接口,不依赖ViewModel和View
  • ViewModel,监听Model的事件,并对Model的接口了如指掌,依赖于Model。同时向View暴露响应逻辑的调用接口,以及所有的状态数据,并不依赖于View
  • View,监听用户交互事件,然后调用ViewModel的响应逻辑,同时将自己的显示状态与ViewModel的状态数据绑定在一起,所以依赖于ViewModel

在其文中举了一个例子相当生动:

  1. View获取下拉事件,通知Controller

  2. Controller向后台Model发起请求,请求内容为下拉刷新

  3. Model获得10条新闻数据,传递给Controller

  4. Controller拿到10条新闻数据,可能做一些数据处理,然后拿处理好的数据渲染View

    MVC: 拿到UI节点,渲染10条新闻

    MVP: 通过View提供的接口渲染10条新闻

    MVVM: 无需操作,只要VM的数据变化,通过数据双向绑定,View直接变化

同步异步,阻塞和非阻塞

发表于 2018-06-29 | 分类于 通信机制

同步和异步,阻塞和非阻塞,根据字面意思也能够分出差别,但是同步,异步与阻塞,非阻塞很容易混淆,那么同步是不是就是阻塞,异步是不是就是非阻塞?

答案是否定的,虽然同步意味着阻塞,异步意味着不阻塞,但是面对的对象不同,下面是摘自博客园其中一篇博客对同步、异步,阻塞、非阻塞的定义:

同步、异步:

  • 概念:消息的通知机制
  • 解释:涉及到IO通知机制;所谓同步,就是发起调用后,被调用者处理消息,必须等处理完才直接返回结果,没处理完之前是不返回的,调用者主动等待结果;所谓异步,就是发起调用后,被调用者直接返回,但是并没有返回结果,等处理完消息后,通过状态、通知或者回调函数来通知调用者,调用者被动接收结果。阻塞、非阻塞:

阻塞、非阻塞

  • 概念:程序等待调用结果时的状态
  • 解释:涉及到CPU线程调度;所谓阻塞,就是调用结果返回之前,该执行线程会被挂起,不释放CPU执行权,线程不能做其它事情,只能等待,只有等到调用结果返回了,才能接着往下执行;所谓非阻塞,就是在没有获取调用结果时,不是一直等待,线程可以往下执行,如果是同步的,通过轮询的方式检查有没有调用结果返回,如果是异步的,会通知回调。

根据概念,他们讲的就不是同一件事情。

同步和异步是用来形容消息的通知机制,通信机制就是一个Rule,一个规则,同步就是严格按照先后顺序去做事情,比如有时候我们的事情必须一件一件去做,我先开发原型界面,再前后端联调——也就是说我的开发流程这个Rule,我在没有开发完原型界面之前是不会跟后端去联调的,这就是同步;而异步在生活中就很多了,我在家里放了一只老鼠夹,我不可能在旁边看着老鼠上钩,我可以去做其他的事情,直到有一天,老鼠夹发出警报了(这是一个连着app的老鼠夹23333),我发现有老鼠上钩了,这个就是异步。所以它们针对的是Rule,前端开发流程,老鼠夹夹老鼠,这个都是一种Rule,通信机制。

阻塞和非阻塞是用来形容通信一方的状态,比如我打滴滴,师傅接单了,1分钟就到,我站在路边,时刻关注着手机,我的这个状态就是阻塞状态,而如果要10分钟才到,这个时候外面又很热,那我先去买个可乐喝一下,时不时的看一下手机,看看是不是师傅快到了,这个就是非阻塞。

那么为什么会出现阻塞和非阻塞呢?就是因为同步机制造成的,如果是异步,最后事情好了,通知我一声,good!!!我阻塞在那里干嘛,我该干嘛干嘛。但是同步的话我就没办法了,只能等呗,时间少一点无所谓的,那时间一长呢?做点其他的事情呗,时不时的看看后续情况,提高效率。

所以同步都伴随着阻塞和非阻塞,以后再也不要把同步异步,阻塞、非阻塞搞混了。

抛砖引玉,望提出宝贵意见。

勤能补拙

发表于 2018-06-27 | 分类于 工作漫谈

1530114837431

针对于程序员平时有的坏习惯,包括我也是很多都占了,针对于这些问题进行总结

克服上述的几个不良习惯,一定会跟别人产生不一样的差距,时刻勉励自己,事在人为。

JavaScript 与 CSS 滚动实现最新指南

发表于 2018-06-09 | 分类于 CSS

一些(网站)滚动的效果是如此令人着迷但你却不知该如何实现,本文将为你揭开它们的神秘面纱。我们将基于最新的技术与规范为你介绍最新的 JavaScript 与 CSS 特性,(当你付诸实践时)将使你的页面滚动更平滑、美观且性能更好。

大多数的网页的内容都无法在一屏内全部展现,因而(页面)滚动对于用户而言是必不可少的。对于前端工程师与 UX 设计师而言,跨浏览器提供良好的滚动体验,同时符合设计(要求),无疑是一个挑战。尽管 web 标准的发展速度远超从前,但代码的实现往往是落后的。下文将为你介绍一些常见的关于滚动的案例,检查一下你所用的解决方案是否被更优雅的方案所代替。

消逝的滚动条

在过去的三十年里,滚动条的外观不断改变以符合设计的趋势,设计师们为(滚动条的)颜色、阴影、上下箭头的形状与边框的圆角实验了多种风格。以下是 Windows 上的变化历程:

1528535978470

Windows 上的滚动条

在2011年,苹果设计师从 ios 上获得灵感,为如何定义“美观的”滚动条确定了方向。所有滚动条均从 Mac 电脑中消失,不再占据任何页面空间,只有在用户触发滚动时(滚动条)才会重新出现(有些用户会设置不隐藏滚动条)。

1528536021999

Mac 上的滚动条

滚动条安静地消逝并未引起苹果粉丝的不满,已经习惯了 iPhone 与 iPad 上滚动方式的用户很快地习惯了这一设计。大多数开发人员与设计师都认为这是一个“好消息”,因为计算滚动条的宽度可真是件苦差事。

然而,我们生活在一个拥有众多操作系统与浏览器的世界中,它们(对于滚动)的实现各不相同。如果你和我们一样是一名 Web 开发者,你可不能把“滚动条问题”置之不理。

以下将为你介绍一些小技巧,使你的用户在滚动时有更好的体验。

隐藏但可滚动

先来看看一个关于模态框的经典例子。当它被打开的时候,主页面应该停止滚动。在 CSS 中有如下的快捷实现方式:

1
2
3
body {
overflow: hidden;
}

但上述代码会带来一点不良的副作用:

img

注意红色箭头

在这个示例中,为了演示目的,我们在 Mac 系统中设置了强制显示滚动条,因而用户体验与 Windows 用户相似。

我们该如何解决这个问题呢?如果我们知道滚动条的宽度,每次当模态框出现时,可在主页面的右边设置一点边距。

由于不同的操作系统与浏览器对滚动条的宽度不一,因而获取它的宽度并不容易。在Mac 系统中,无论任何浏览器(滚动条)都是统一15px,然而 Windows 系统可会令开发者发狂:

1528536193127

“百花齐放”的宽度

注意,以上仅是 Windows 系统下基于当前最新版浏览器(测试所得)的结果。以前的(浏览器)版本(宽度)可能有所不同,也没人知道未来(滚动条的宽度)会如何变化。

不同于猜测(滚动条的宽度),你可以通过 JavaScript 计算它的宽度(译者注:实测以下代码仅能测出原始的宽度,通过 CSS 改变了滚动条宽度后,以下代码也无法测出实际宽度):

1
2
3
4
5
6
7
8
9
10
11
12
13
const outer = document.createElement('div');

const inner = document.createElement('div');

outer.style.overflow = 'scroll';

document.body.appendChild(outer);

outer.appendChild(inner);

const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;

document.body.removeChild(outer);

尽管仅仅七行代码(就能测出滚动条的宽度),但有数行代码是操作 DOM 的。(为性能起见,)如非必要,尽量避免进行 DOM 操作。

解决这个问题的另一个方法是在模态框出现时仍保留滚动条,以下是基于这思路的纯 CSS 实现:

1
2
3
html {
overflow-y: scroll;
}

尽管“模态框抖动”问题解决了,但整体的外观却被一个无法使用的滚动条影响了,这无疑是设计中的硬伤。

在我们看来,更好的解决方案是完全地隐藏滚动条。纯粹用 CSS 也是可以实现的。该方法(达到的效果)和 macOS 的表现并不是完全一致,(当用户)滚动时滚动条仍然是不可见的。滚动条总是处于不可见状态,然而页面是可被滚动的。对于Chrome,Safari 和 Opera 而言,可以使用以下的 CSS:

1
2
3
.container::-webkit-scrollbar {
display: none;
}

IE 或 Edge 可用以下代码:

1
2
3
.container {
-ms-overflow-style: none;
}

至于 Firefox,很不幸,没有任何办法隐藏滚动条。

正如你所见,并没有任何银弹。任何解决方案都有它的优点与缺点,应根据你项目的需要选择最合适的。

外观争议

需要承认的是,滚动条的样子在部分操作系统上并不好看。一些设计师喜欢完全掌控他们(所设计)应用的样式,任何一丝细节也不放过。在 GitHub 上有上百个库借助 JavaScript 取代系统滚动条的默认实现,以达到自定义的效果。

但如果你想根据现有的浏览器定制一个滚动条呢?(很遗憾,)并没有通用的 API,每个浏览器都有其独特的代码实现。

尽管5.5版本以后的 IE 浏览器允许你修改滚动条的样式,但它只允许你修改滚动条的颜色。以下是如何重新绘制(滚动条)拖动部分与箭头的代码:

1
2
3
4
5
body {

scrollbar-face-color: blue;

}

但只改变颜色对提高用户体验而言帮助不大。据此,WebKit 的开发者在2009年提出了(修改滚动条)样式的方案。以下是使用 -webkit 前缀在支持相关样式的浏览器中模拟 macOS 滚动条样式的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
::-webkit-scrollbar {

width: 8px;

}

::-webkit-scrollbar-thumb {

background-color: #c1c1c1;

border-radius: 4px;

}

Chrome、Safari、Opera 甚至于 UC 浏览器或者三星自带的桌面浏览器都支持(上述 CSS)。Edge 也有计划实现它们。但三年过去了,该计划仍在中等优先级中(而尚未被实现)。

当我们讨论滚动条的定制时,Mozilla 基金会基本上是无视了设计师的需求。(有开发者在)17年前就已经提出了一个希望修改滚动条样式的请求。而就在几个月前,Jeff Griffiths(Firefox 浏览器总监)终于为这个问题作出了回答:

除非团队中有人对此有兴趣,否则我对此毫不关心。

公平地说,从 W3C 的角度看来,尽管 WebKit 的实现得到广泛的支持,但它仍然不是标准。现有的为滚动条修改样式的草案,是基于 IE 的:仅能修改它的颜色。

伴随着请求如同 WebKit 一样支持滚动条样式修改 issue 的提交,争议仍在继续。如果你想影响 CSS 工作小组,是时候参与讨论了。也许这不是优先级最高的问题,但(如同 WebKit 一样修改滚动条样式)得到标准化后,能使很多前端工程师与设计师轻松很多。

流畅的操作体验

对于滚动而言,最常见的任务是登录页的导航(跳转)。通常,它是通过锚点链接来完成的。只需要知道元素的 id 即可:

1
<a href="#section">Section</a>

点击该链接会 跳 到(该锚点对应的)区块上,(然而) UX 设计师一般会坚持认为该过程应是平滑地运动的。GitHub 上有大量造好的轮子(帮你解决这个问题),然而它们或多或少都用到 JavaScript。(其实)只用一行代码也能实现同样的效果,最近DOM API 中的 Element.scrollIntoView() 可以通过传入配置对象来实现平滑滚动:

1
2
3
4
5
elem.scrollIntoView({

behavior: 'smooth'

});

然而该属性兼容性较差且仍是通过脚本(来控制样式)。如有可能,应尽量少用额外的脚本。

幸运的是,有一个全新的 CSS 属性(仍在工作草案中),可以用简单的一行代码改变整个页面滚动的行为。

1
2
3
4
5
html {

scroll-behavior: smooth;

}

结果如下:

img

(从一个区块跳到另一个)

img

(平滑地滚动)

你可以在 codepen (链接https://codepen.io/askd/full/WdXOYW)上试验这个属性。在撰写本文时,`scroll-behavior` 仅在 Chrome、 Firefox 与 Opera 上被支持,但我们希望它能被广泛支持,因为使用 CSS (比使用 JavaScript)在解决页面滚动问题时优雅得多,并更符合“渐进增强”的模式。

粘性 CSS

另一个常见的需求是根据滚动方向动态地定住元素,即有名的“粘性(即 CSS 中的position: sticky)”效应。

img

一个粘性元素

在以前的日子里,要实现一个“粘性”元素需要编写复杂的滚动处理函数去计算元素的大小。(然而)该函数较难处理元素在“黏住”与“不黏住”之间微小的延迟,(通常会)导致(元素)抖动的出现。通过 JavaScript 来实行(“粘性”元素)也有性能上的问题,特别是在(需要)调用 [Element.getBoundingClientRect() ]时(https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect)。

不久之前,CSS 实现了 position: sticky 属性。只需通过指定(某方向上的)偏移量即可实现我们想要的效果。

1
2
3
4
5
6
7
.element {

position: sticky;

top: 50px;

}

(编写上述代码后)剩下的就交由浏览器实现即可。你可以在 codepen 上试验一下。撰写本文之时,position: sticky 在各式浏览器(包括移动端浏览器)上支持良好,所以如果你还在使用 JavaScript 去解决这个问题的话,是时候换成纯 CSS 的实现了。

全面使用函数节流

从浏览器的角度看来,滚动是一个事件,因此在 JavaScript 中是使用一个标准化的事件监听器 addEventListener 去处理它:

1
2
3
4
5
6
7
window.addEventListener('scroll', () => {

const scrollTop = window.scrollY;

/* doSomething with scrollTop */

});

用户往往高频率地滚动(页面),但如果滚动事件触发太频繁的话,会导致性能上的问题,可以通过使用函数节流这一技巧去优化它。

1
2
3
4
5
6
7
window.addEventListener('scroll', throttle(() => {

const scrollTop = window.scrollY;

/* doSomething with scrollTop */

}));

你需要定义一个节流函数包装原来的事件监听函数,(节流函数是)减少被包装函数的执行次数,只允许它在固定的时间间隔之内执行一次:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function throttle(action, wait = 1000) {

let time = Date.now();

return function() {

if ((time + wait - Date.now()) < 0) {

action();

time = Date.now();

}

}

}

为了使(节流后的)滚动更平滑,你可以通过使用window.requestAnimationFrame() 来实现函数节流:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function throttle(action) {

let isRunning = false;

return function() {

if (isRunning) return;

isRunning = true;

window.requestAnimationFrame(() => {

action();

isRunning = false;

});

}

}

当然,你可以通过现有的开源轮子来实现,就像 Lodash 一样。你可以访问 codepen 来看看上述解决方案与 Lodash 中的 _.throttle 之间的区别。

使用哪个(开源库)并不重要,重要的是在需要的时候,记得优化你(页面中的)滚动处理函数。

在视窗中显示

当你需要实现图片懒加载或者无限滚动时,需要确定元素是否出现在视窗中。这可以在事件监听器中处理,最常见的解决方案是使用 lement.getBoundingClientRect() :

1
2
3
4
5
6
7
8
9
10
11
window.addEventListener('scroll', () => {

const rect = elem.getBoundingClientRect();

const inViewport = rect.bottom > 0 && rect.right > 0 &&

rect.left < window.innerWidth &&

rect.top < window.innerHeight;

});

上述代码的问题在于每次调用 getBoundingClientRect 时都会触发回流,严重地影响了性能。在事件处理函数中调用( getBoundingClientRect )尤为糟糕,就算使用了函数节流(的技巧)也可能对性能没多大帮助。 (回流是指浏览器为局部或整体地重绘某个元素,需要重新计算该元素在文档中的位置与形状。)

在2016年后,可以通过使用 Intersection Observer 这一 API 来解决问题。它允许你追踪目标元素与其祖先元素或视窗的交叉状态。此外,尽管只有一部分元素出现在视窗中,哪怕只有一像素,也可以选择触发回调函数:

const observer = new IntersectionObserver(callback, options);

observer.observe(element);

(点击https://gist.github.com/paulirish/5d52fb081b3570c81e3a,查看触发回流的 DOM 属性和方法。)

此 API 被广泛地支持,但仍有一些浏览器需要 polyfill。尽管如此,它仍是目前最好的解决方案。

滚动边界问题

如果你的弹框或下拉列表是可滚动的,那你务必要了解连锁滚动相关的问题:当用户滚动到(弹框或下拉列表)末尾(后再继续滚动时),整个页面都会开始滚动。

img

连锁滚动的表现

当滚动元素到达底部时,你可以通过(改变)页面的 overflow 属性或在滚动元素的滚动事件处理函数中取消默认行为来解决这问题。

如果你选择使用 JavaScript (来处理),请记住要处理的不是“scroll(事件)”,而是每当用户使用鼠标滚轮或触摸板时触发的“wheel(事件)”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function handleOverscroll(event) {
const delta = -event.deltaY;
if (delta< 0 && elem.scrollHeight - elem.scrollTop) {
elem.scrollTop = elem.scrollHeight;
event.preventDefault();
return false;
}
if (delta > elem.scrollTop) {
elem.scrollTop = 0;
event.preventDefault();
return false;
}
return true;
}

不幸的是,这个解决方案不太可靠。同时可能对(页面)性能产生负面影响。

过度滚动对移动端的影响尤为严重。Loren Brichter 在 iOS 的 Tweetie 应用上创造了一个“下拉刷新”的新手势,这在 UX 社区中引起了轰动:包括 Twitter 与 Facebook 在内的各大应用纷纷采用了(相同的手势)。

当这个特性出现在安卓端的 Chrome 浏览器中时,问题出现了:它会刷新整个页面而不是加载更多的内容,成为开发者在他们的应用中实现“下拉刷新”时的麻烦。

CSS 通过 overscroll-behavior 这个新属性解决问题。它通过控制元素滚动到尽头时的行为来解决下拉刷新与连锁滚动所带来的问题,(它的属性值中)也包含针对不同平台特殊值:安卓的 glow 与 苹果系统中的 rubber band。

现在,上面 GIF 中的问题,在 Chrome、Opera 或 Firefox 中可以通过以下一行代码来解决:

1
2
3
4
5
.element {

overscroll-behavior: contain;

}

公平地说,IE 与 Edge 实现了(它独有的) -ms-scroll-chaining 属性来控制连锁滚动,但它并不能处理所有的情况。幸运的是,根据这消息,微软的浏览器已经准备实现 overscroll-behavior 这一属性了。

触屏之后

触屏设备上的滚动(体验)是一个很大的话题,深入讨论需要另开一篇文章。然而,由于很多开发者忽略了这方面的内容,这里需要提及一下。

(滚动手势无处不在,令人沉迷,以至于想出了如此疯狂的主意去解决“滚动上瘾”的问题。)

周围的人在智能手机屏幕上上下移动他们的手指的频率是多少呢?经常这样对吧,当你阅读本文时,你很可能就在这么做。

当你的手指在屏幕上移动时,你期待的是:页面内容平滑且流畅地移动。

苹果公司开创了“惯性”滚动并拥有它的专利 。它讯速地成为了用户交互的标准并且我们对此已习以为常。

但你也许已经注意到了,尽管移动端系统会为你实现页面上的惯性滚动,但当页面内某个元素发生滚动时,即使用户同样期待惯性滚动,但它并不会出现,这令人沮丧。

这里有一个 CSS 的解决方案,但看起来更像是个 hack:

1
2
3
4
5
.element {

-webkit-overflow-scrolling: touch;

}

为什么这是个 hack 呢?首先,它只能在支持(webkit)前缀的浏览器上才能工作。其次,它只适用于触屏设备。最后,如果浏览器不支持的话,你就这样置之不理吗?但无论如何,这总归是一个解决方案,你可以试着使用它。

在触屏设备上,另一个需要考虑的问题是开发者如何处理 touchstart与 touchmove事件触发时可能存在的性能问题,它对用户滚动体验的影响非常大。这里详细描述了整个问题。简单来说,现代的浏览器虽然知道如何使得滚动变得平滑,但为确认(滚动)事件处理函数中是否执行了Event.preventDefault()以取消默认行为,有时仍可能需要花费500毫秒来等待事件处理函数执行完毕。

即使是一个空的事件监听器,从不取消任何行为,鉴于浏览器仍会期待preventDefault的调用,也会对性能造成负面影响。

为了准确地告诉浏览器不必担心(事件处理函数中)取消了默认行为,在 WHATWG 的 DOM 标准中存在着一个不太显眼的特性(能解决这问题)。(它就是)Passive event listeners,浏览器对它的支持还是不错的。事件监听函数新接受一个可选的对象作为参数,告诉浏览器当事件触发时,事件处理函数永远不会取消默认行为。(当然,添加此参数后,)在事件处理函数中调用 preventDefault 将不再产生效果。

element.addEventListener(‘touchstart’, e => {

/ doSomething /

}, { passive: true });

针对不支持该参数的浏览器,这里也有一个 polyfill 。这视频清晰地展示了此改进带来的影响。

旧技术运行良好,为何还要改动?

在现代互联网中,过渡地依赖 JavaScript 在各浏览器上实现相同的交互效果不再是合理的,“跨浏览器兼容性”已经成为过去式,更多的 CSS 属性与 DOM API 方法正逐步被各大浏览器所支持。

在我们看来,当你的项目中,有特别酷炫的滚动效果时,渐进增强是最好的做法。

你应该提供(给用户)所有(你能提供的)基础用户体验,并逐步在更先进的浏览器上提供更好的体验。

必要时使用 polyfill,它们不会产生(不必要的)依赖,一旦(某个 polyfill 所支持的属性)得到广泛地支持,你就可以轻松地将它删掉。

六个月之前,在本文尚未成文之时,之前我们描述的属性只被少量的浏览器所支持。而到了本文发表之时,这些属性已被广泛地支持。

也许到了现在,当你上下翻阅本文之时,(之前不支持某些属性的)浏览器已经支持了该属性,这使得你编程更容易,并使你的应用打包出来体积更小。

感谢阅读至此!查阅浏览器的更新日志,积极参与讨论,有助于 web 标准驶向正确的方向。祝大家一帆风顺,顺利滑(滚)向未来!

本文转自如下:

原文作者:Evil Martians 译者:sea_ljf

文章出处:众成翻译

Merge Two Sorted Arrays

发表于 2018-06-07 | 分类于 Algothrim-LintCode

Merge Two Sorted Arrays

Merge two given sorted integer array A and B into a new sorted integer array.

Example

A=[1,2,3,4]

B=[2,4,5,6]

return [1,2,2,3,4,4,5,6]

Challenge

How can you optimize your algorithm if one array is very large and the other is very small?

Answer

  1. 先合并,在排序
  1. one array is very large and the other is very small?说明两个数很有可能最后pk只剩下大数组,那么就将剩余的大数组直接复制即可

CSS疑难总结

发表于 2018-06-07 | 分类于 CSS

写在前面

本文主要用于项目中碰到的关于css的疑难点或者易忘点的总结。

布局篇

  1. flex布局

    Flex布局以后,子元素的float、clear和vertical-align属性将失效。

    img

    flex布局示意图

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    .container {
    display:-webkit-flex; //与flex一起写,是一个好习惯 ???什么是webkit内核
    display: flex;
    flex-flow: row | row-reverse | column | column-reverse [nowrap|wrap|wrap-reverse];//前半部分为伸缩项目的伸缩方向 后半部分为是否另起一行
    justify-content: flex-start | flex-end | center | space-between | space-around; //伸缩项目的对齐方式
    align-items: flex-start | flex-end | center | baseline | stretch; //上下对齐
    align-content: flex-start | flex-end | center | space-between | space-around | stretch; //多根轴线的对齐方式
    }
    .tems {
    flex:none | <' flex-grow '> <' flex-shrink >'? || <' flex-basis '>
    order: <integer>; //数值越小越靠前
    align-self: auto | flex-start | flex-end | center | baseline | stretch; //单个项目可以自定义伸缩
    }

对于flex属性的参数解析可以参考CSS手册:

<’ flex-grow ‘>:

用来指定扩展比率,即剩余空间是正值时此「flex子项」相对于「flex容器」里其他「flex子项」能分配到空间比例。
在「flex」属性中该值如果被省略则默认为「1」

<’ flex-shrink ‘>:

用来指定收缩比率,即剩余空间是负值时此「flex子项」相对于「flex容器」里其他「flex子项」能收缩的空间比例。
在收缩的时候收缩比率会以伸缩基准值加权
在「flex」属性中该值如果被省略则默认为「1」

<’ flex-basis ‘>:

用来指定伸缩基准值,即在根据伸缩比率计算出剩余空间的分布之前,「flex子项」长度的起始数值。
在「flex」属性中该值如果被省略则默认为「0%」
在「flex」属性中该值如果被指定为「auto」,则伸缩基准值的计算值是自身的 <’ width ‘> 设置,如果自身的宽度没有定义,则长度取决于内容。

1528387809078

例子说明flex-grow,flex-shrink ,flex-basis之间的关系

  1. Position中Absolute和Relative
  1. BOM篇

  2. 关于浏览器内核和Javascript引擎之间的关系

  1. 论浏览器中的scroll
  1. CSS属性

CSS Overlay技巧

发表于 2018-06-07 | 分类于 CSS

引子

  对于模态框,一般都不陌生,在面试中,总会被问到有没有自己写过控件,那么模态框的实现原理是什么呢?模态框的一个特点就是在弹出框时,用户不能编辑除了模态框以外的区域。今天主要列举使用CSS实现遮罩层的方式,比较优劣,最后总结最优的一种方式(并非绝对最优,仅供参考)。

1528215690199

bootstrap的模态框

正文

1.使用“子绝父相”进行定位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<html>
<head>
<style>
html,
body {
min-height: 100%;
}
body {
position: relative;margin: 0px;
background: #ddd;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
opacity:1;
}
</style>
</head>

<body>
<a href="https://www.baidu.com">百度</a>
<div class="overlay"></div>
</body>
<html>

1528216778635

.overlay为一层透明的遮罩层,这个时候用户点击百度是没有反应的,模态框的信息可以显示在overlay的遮罩层中,且z-index高于overlay

但是overlay必须是body的子元素,秉承“子绝父相”的原则。

2.Fixed定位解决问题

1
2
3
4
5
6
7
8
9
.overlay {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 10;
opacity:1;
}

效果由于第1种方法,Bootstrap的modal就是使用的此方法,如下图所示:

1528217329330

在大漠的文章中还提及了outline和box-shadow,但是经过试验发现不能达到模态框的要求。

所以使用第二种的方式来制作遮罩层,比较适合。

参考文献:

  1. http://www.w3cplus.com/css/css-overlay-techniques.html

#

A + B Problem

发表于 2018-06-06 | 分类于 Algothrim-LintCode

A + B Problem

Write a function that add two numbers A and B. You should not use + or any arithmetic operators.

Example

Given a=1 and b=2 return 3.

Answer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Solution {
/**
* @param a: An integer
* @param b: An integer
* @return: The sum of a and b
*/
public int aplusb(int a, int b) {
//两个数异或:相当于每一位相加,而不考虑进位;
//如果两个数的二进制每一位都不一样 比如01和10,那么x=11;
//那么如果有进位呢?比如01和01,那么应该是满2进1,如何做(a&b)<<1=10
//那么a&0等于a本身,那么当b=0时,a就是两个数的和
//两个数相与,并左移一位:相当于求得进位;
int x = a^b;
int y = a&b;
if(y==0){
return x;
}else{
return aplusb(x,y<<1);
}
}
}

关于JAVASCRIPT中 typeof 和 instanceof

发表于 2018-06-06 | 分类于 JAVASCRIPT

关于上次我总结了typeof 和 instanceof 的区别,今天在前端早读课读到对于typeof和instanceof的原理解析,故在深入学习一下。

typeof和instanceof的主要区别是typeof用于判断number, string, object, boolean, function, undefined,symbol7种基本数据类型,而instanceof用于检测Object对象的引用类型,是对typeof的补充。

在typeof和instanceof的原理解析的文章中对于typeof的本质摘抄如下:

1528286996138

null的低1-3位也是000,所以type of null也是object

而instanceof的原理可以看如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
function new_instance_of(leftVaule, rightVaule) { 
let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
while (true) {
if (leftVaule === null) {
return false;
}
if (leftVaule === rightProto) {
return true;
}
leftVaule = leftVaule.__proto__
}
}

rightVaule与rightProto的原型链中的所有对象进行比较,如果相等就返回true。

也可以使用如下方法可以判断所有类型

1
2
3
4
5
6
7
8
9
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('hi') // "[object String]"
Object.prototype.toString.call({a:'hi'}) // "[object Object]"
Object.prototype.toString.call([1,'a']) // "[object Array]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(() => {}) // "[object Function]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"

2018年5月8号

今天看了一道JS的基础面试题:

问题:如何准确判断一个变量是数组类型
答案:

1
2
3
4
var arr1 = [];  
console.log(arr1 instanceof Array); //打印结果:true。
console.log(typeof arr1); //打印结果:object.
提示:typeof 方法无法判断是否为数组

从中引出了typeof 和 instanceof 的区别和联系
查看了MDN的官方手册对于两者的用法如下:

  1. typeof操作符返回一个字符串,表示未经计算的操作数的类型。

用法:

1
2
3
typeof operand
or
typeof (operand)

typeof有如下返回值:

类型 结果
Undefined “undefined”
Null “object”(见下文)
Boolean “boolean”
Number “number”
String “string”
Symbol (ECMAScript 6 新增) “symbol”
宿主对象(由JS环境提供) Implementation-dependent
函数对象([[Call]] 在ECMA-262条款中实现了) “function”
任何其他对象 “object”

从上图可以反映出:typeof operand返回的结果为基本类型,对于引用类型其都返回object,所以var a = [];console.log(a);返回object。

注: 使用typeof操作符的时候,如果检测对象是函数,那么操作符返回"function" ,如果检测对象是正则表达式的时候,在Safari和Chrome中使用typeof的时候会错误的返回"function"。

  1. instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。

    用法:

1
2
3
4
5
6
object instanceof constructor

//object
//要检测的对象.
//constructor
//某个构造函数

如下是官方例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 定义构造函数
function C(){}
function D(){}

var o = new C();


o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype


o instanceof D; // false,因为 D.prototype不在o的原型链上

o instanceof Object; // true,因为Object.prototype.isPrototypeOf(o)返回true
C.prototype instanceof Object // true,同上

C.prototype = {};
var o2 = new C();

o2 instanceof C; // true

o instanceof C; // false,C.prototype指向了一个空对象,这个空对象不在o的原型链上.

D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true

注:如果表达式 obj instanceof Foo 返回true,则并不意味着该表达式会永远返回true,因为Foo.prototype属性的值有可能会改变,改变之后的值很有可能不存在于obj的原型链上,这时原表达式的值就会成为false。另外一种情况下,原表达式的值也会改变,就是改变对象obj的原型链的情况,虽然在目前的ES规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的proto魔法属性,是可以实现的。比如执行obj.proto = {}之后,obj instanceof Foo就会返回false了。
所以对于typeof和instanceof的用法——typeof一般是检测的是基本数据类型,instanceof主要检测的是引用类型!

1234
ZheHuaXuan

ZheHuaXuan

知足.感恩.幸运

31 日志
19 分类
45 标签
GitHub E-Mail
© 2019 ZheHuaXuan
由 Hexo 个人专属
|
主题 — NexT.Gemini v5.1.3