evantianx / Bloooooooog

Place to record what I thought and learned
0 stars 0 forks source link

工作杂记 #25

Open evantianx opened 7 years ago

evantianx commented 7 years ago

IDE & 构建工具

PhpStorm

VS Code

BrowserSync

指定入口文件:

browser-sync start --server --index bower.html --files="css/*.css"

Cannot GET/ #699

evantianx commented 7 years ago

['1', '2', '3'].map(parseInt)返回值为?


答案💯 : [1, NaN, NaN]

回顾📖 :

解析✍️ :

'1' 和 0 分别作为字符串和进制数传给parseInt(),此时按照十进制转换 '1',得到数字 1; '2' 和 1 分别作为字符串和进制数传给parseInt(),此时进制数非法,得到 NaN; '3' 和 2 分别作为字符串和进制数传给parseInt(),此时按照二进制转换 '3',无法转换故得到 NaN;

Bonus👏🏻 :

function returnInt (ele) {
  return parseInt(ele, radix)
}

['1', '2', '3'].map(returnInt) // 返回[1, 2, 3]

关于 ES6 模块

ECMAScript 6 入门 #module ECMAScript modules in browsers 待补充

小技巧

About rel=noopener What problems does it solve?

JS 判断是否为 IE 浏览器的方法

方法来源

/**
 * 利用 IE 的注释 hack 判断 IE 浏览器版本号,也可以不传参仅判断是否为 IE
 *
 * @param    {number}  version    要检测的 IE 版本号
 */

var isIE = function(ver){
  var b = document.createElement('b')
  b.innerHTML = '<!--[if IE ' + ver + ']><i></i><![endif]-->'
  return b.getElementsByTagName('i').length === 1
}

Don't use switch

遗漏 break 关键字的时候容易造成不易发现的 bug。

建议写成:

var tokenActions = {
  '{': handleOpen,
  '[': handleOpen,
  ']': handleClose,
  '}': handleClose
};

function processToken(token) {
  if (typeof tokenActions[token] !== 'function') {
    throw new Error('Invalid token.');
  }
  return tokenActions[token](token);
}

Why is getElementsByTagName() faster than querySelectorAll()?

总结下:

getElementsByTagName() 获取到的是 live NodeList;而 querySelectorAll() 获取到的是 static NodeList Static NodeList 比较慢的原因在于它要求获取当前 DOM 的一个快照,找到所有符合要求的元素; 而 live NodeList 则无需这样.

为什么 getElementsByTagName 比 querySelectorAll 方法快 简单讨论 querySelectorAll Vs getElementsByTagName 区别

NPM SCRIPTS: TIPS EVERYONE SHOULD KNOW

关于 npm script 的很多技巧

TEMPORAL DEAD ZONE (TDZ) DEMYSTIFIED

let / const 变量在声明之前不能访问并不是因为两者不存在声明提前,只是 TDZ!

The variables are created when their containing Lexical Environment is instantiated [...] but may not be accessed in any way until the variable’s LexicalBinding is evaluated.

Why Mapping a Constructed Array in JavaScript Doesn’t Work

const arr = Array(100).map((_, i) => i);
console.log(arr[0] === undefined);  // true

solution:

const arr = [...Array(100)].map((_, i) => i);
console.log(arr[0] === 0); // true

sparse array

An adventure in sparse arrays

几个要点:

原型

reduce

重写 reduce

const reduce = (fn, acc, arr) => {
  if (arr.length === 0) return acc
  const [ head, ...tail ] = arr
  return reduce(fn, fn(acc, head), tail)
}

分配数组

将用户中的男性和女性分别放到不同的数组里:

const users = [
  { name: "Adam", age: 30, sex: "male" },
  { name: "Helen", age: 27, sex: "female" },
  { name: "Amy", age: 25, sex: "female" },
  { name: "Anthony", age: 23, sex: "male" },
];
const partition = (arr, isValid) => 
  arr.reduce(([male, female], cur) => 
    isValid(cur) ? [ [ ...male, cur ], female ] : [ male, [...female, cur] ]
  , [])

const isMale = item => item.sex === 'male'

const [ male, female ] = partition(users, isMale) 

cssText

用cssText批量修改样式踩的坑

如何禁止弹出层背景滚动

由弹出层引发对滚动原理的讨论

如何避免条件语句 hell

5 Tips to Write Better Conditionals in JavaScript

Replacing switch statements with Object literals

JavaScript 复杂判断的更优雅写法

const actions = ()=>{
  const functionA = ()=>{/*do sth*/}
  const functionB = ()=>{/*do sth*/}
  const functionC = ()=>{/*send log*/}
  return new Map([
    [/^guest_[1-4]$/,functionA],
    [/^guest_5$/,functionB],
    [/^guest_.*$/,functionC],
    //...
  ])
}

const onButtonClick = (identity,status) => {
  let action = [ ...actions() ].filter(([key,value]) => (key.test(`${identity}_${status}`)))
  action.forEach(([key,value]) => value.call(this))
}

利用 map 正则匹配,实现更好地解耦

可以预测的 JS 对象属性值顺序

Why Facebook's api starts with a for loop

了解所谓的 JSON hijacking

npm

列出项目直接依赖真正版本号(if use semver)

npm list --depth=0 

查看某个包的信息(维护者,依赖项等)

npm view vue 

Tricks of Resting and Spreading JavaScript Objects

evantianx commented 7 years ago

制作一个 iOS 风格的 switch button

demo

今天业务需求制作一个 switch button,把制作思路简单梳理下:

首选标签为<input type="checkbox">,因为我们可以根据:checked伪类来进行 CSS Transition 变换;

其次,选择<label>标签作为主战场,因为点击<label>区域即相当于点击对应的<input>标签。利用伪类:before:after制作切换按钮的两个部分:按钮和内部区域。

有了这个思路就好办了,步骤如下:

  1. 构造基本 HTML 结构
    <div class="switch">
     <input id="btn" type="checkbox">
     <label for="btn"></label>
    </div>
  2. 设置样式使<input>消失,从而不影响后续的样式
    * {
      box-sizing: border-box; /* 方便样式计算 */
    }
    .switch {
      input {
        display: none;
      }
    }
  3. <label>设置基本样式
    .switch {
      input + label {
        display: block;
        position: relative;
        width: 120px;
        height: 60px;
        cursor: pointer;
        outline: none;
        padding: 2px;
        background-color: #ddd;
        border-radius: 60px;
      }
    }
  4. 添加伪类样式
    .switch {
      input + label {
        &:before, &:after {
          content: '';
          position: absolute;
          top: 1px;
          left: 1px;
          bottom: 1px;
        }
        /* <label>内部区域样式 */
        &:before {
          right: 1px; /* 将:before伪类撑满整个<label> */
          background-color: #f1f1f1;
          border-radius: 60px;
          transition: background 0.8s;
        }
        /* 圆形按钮样式 */
        &:after {
          width: 58px;
          background-color: #fff;
          border-radius: 100%;
          box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
          transition: margin 0.4s;
        }
      }
      input:checked + label {
        &:before {
          background-color: #8ce196;
        }
        &:after {
          margin-left: 60px;
        }
      }
    }

    为列表元素添加间距

    通常会使用::not(first-child)之类的选择器来避免首尾元素产生不必要的间距或者其他样式。 而如果使用兄弟选择器则完全可以使得代码更为简洁:

    
    li {
    background: powderblue;
    }

li + li { margin-top: 20px; }

> `former_element + target_element { style properties }`

然而某些需求极为严格,要求在占满一页时最后一个元素不显示 `border-bottom`, 在未占满时最后一个元素显示 `border-bottom`.

```css
/* 假设一页最多可摆放五个列表
    此时 0 1 2 3 序号的元素正常显示底线,>= 5 的不显示 👍
*/
li:nth-child(-n+4) {
  border-bottom: 1px solid blue;
}

position: fixed失效的情况

fixed不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed 属性会创建新的层叠上下文。当元素祖先的 transform 属性非 none 时,容器由视口改为该祖先。

position: fixed失效的奇怪现象

Sticky as a Local Fixed?

制作一个宽高比为固定值的 div

Constant width to height ratio

主要利用 padding-top 和伪元素

Updated:

Keeping aspect-ratio with HTML and no padding tricks

Maintaining Aspect Ratio with CSS Grid

利用 SVG 和 Grid 实现

如何阻止 modal 背后的内容滚动?

Chrome 表单自动填充默认样式修改

Time-saving CSS techniques to create responsive images

evantianx commented 7 years ago

如何用 CSS 隐藏滚动条但保持可滚动状态?

webkit 下只需要为滚动元素添加下列代码:

element::-webkit-scrollbar {
  display: none;
}

其他相关信息参见 Stackoverflow 上一篇回答: Hiding the scrollbar on an HTML page

evantianx commented 7 years ago

CSS 实现文本超出显示省略号

超出某个宽度则显示省略号:

span {
  white-space: nowrap;
  text-overflow: ellipsis;
  width: 100px;
  display: block;
  overflow: hidden;
}

超出某行数则显示省略号:

比较兼容的方法,将高度设置为行高的 n 倍( n 即为你要 n 行后省略),此时开始省略行文末显示为渐变白 + 省略号。

.fade {
  display: block;
  position: relative;
  width: 100px;
  height: 3.6em;
  line-height: 1.2em;
  overflow: hidden;
}
.fade:after {
  content: "...";
  position: absolute;
  bottom: 0;
  right: -6px;
  width: 70%;
  height: 1.2em;
  text-align: center;
  background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 50%);
}

webkit 方法:

<div class="module line-clamp">
  <p>
    <!-- 此处省略一大坨文本 -->
  </p>
</div>
.module {
  border: 1px solid #CCC;
  width: 250px;
  margin: 0 0 1em 0;
  overflow: hidden;
}
/* 必须设置为 0 ,否则会扰乱布局 */
.module p {
  margin: 0;
  padding: 0;
}
.line-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical; 
}

demo by Vesa Piittinen

evantianx commented 7 years ago

面试题

下述 div 高度为多少?

<div></div>
div {
  width: 200px;
  padding-top: 60%;
}

JS

function Foo() {
  getName = function () { alert (1); };
  return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}

//请写出以下输出结果:
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

分析

evantianx commented 7 years ago

移动端

evantianx commented 7 years ago

background-position取不同数值类型时其相对坐标是如何定位的?

闲扯 background-position 的单位属性值

evantianx commented 7 years ago

判断某个元素是否进入可视区域?

evantianx commented 7 years ago

如何实现单行居中,多行靠左显示效果?

<div>
  <p><span>啦啦啦</span></p>
  <p><span>啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦</span></p>
</div>
div {
  width: 200px;
}

p {
  text-align: center;
}
p span {
  display: inline-block;
  text-align: left;
}

整体思路就是父级添加 text-align: center 属性,子级改变 displayinline-block 并且添加 text-align: left 属性。

evantianx commented 7 years ago

font-size:0 来清除 inline-block 间距

inline-block 的元素之间会受空白区域的影响,也就是元素之间差不多会有一个字符的间隙。如果在同一行内有 4 个 25% 相同宽度的元素,会导致最后一个元素掉下来。你可以利用元素浮动 float ,或者压缩html,清除元素间的空格来解决。但最简单有效的方法还是设置父元素的 font-size 属性为 0(在子元素中设置 font-size )

你不知道的 CSS

evantianx commented 7 years ago

maxlength 属性在 <input type="number"> 上不起作用

If the value of the type attribute is text, email, search, password, tel, or url, this attribute(maxlength) specifies the maximum number of characters (in Unicode code points) that the user can enter; for other control types, it is ignored.

所以 type="number" 的输入框会忽视 maxlength 这个属性,可以这样写:

<input type="text" pattern="\d*" maxlength="18">

maxlength ignored for input type=“number” in Chrome

evantianx commented 7 years ago

如何用纯 CSS 构造 skeleton screen ?

作者利用了渐变来创建 skeleton screen 中的局部块,不依赖除父级外 HTML 元素,同时使用 css 自定义属性,代码可读性和重用性很高,赞!

:empty 也是一个亮点

Building Skeleton Screens with CSS Custom Properties Demo

evantianx commented 7 years ago

关于 <input type="date"> 的一系列衍生品

Prefilling a Date Input

evantianx commented 6 years ago

Git

git中利用rebase来压缩多次提交

evantianx commented 5 years ago

Interview

JS

async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
}

async function async2() {
  console.log("async2");
}

console.log("script start");

setTimeout(function() {
  console.log("setTimeout");
}, 0);

async1();

new Promise(function(resolve) {
  console.log("promise1");
  resolve();
}).then(function() {
  console.log("promise2");
});

console.log("script end");

输出顺序为:

script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout