0%

传送门 for better UE,浏览器做了如下优化:

  1. 在网络部分,一般使用多个平行进程获取资源,一般为2-6个
  2. 在渲染时,渐进增量的解析和构建Render Tree,逐部分渲染网页
  3. 对于执行到阻塞文档解析的脚本时,主流浏览器通常会开启另一个进程去找出文档中其余脚本文件并异步进行下载,而不影响主进程
  4. 引入脏位系统(dirty bit system),进行局部layout

what? OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。 原理就是USER为TPA授权,有授权之后,TPA获取令牌,进而凭令牌获取部分被保护资源 阮一峰日志 why? 减少用户登录成本,提升UX how?


微信开放平台以授权码模式实现

  • 共经过三次关键交互
    1. 微信用户请求登录TPA,TPA向WeChat Open请求OAUTH2.0登录,WeChat Open返回授权临时票据(code)
    2. TPA根据appid、appsecret和code返回access_token
    3. TPA凭借接口调用凭证access_token获取用户基础信息
  • 网站应用接入形式
    1. 外链式
    2. 内嵌式

微信开放平台传送门

想知道你男/女票拿手机都干了什么

拿起Android手机打开拨号界面并输入以下字符 *#*#4636#*#* 跳出统计界面后点击使用情况统计数据 然后你懂得


微信查询与好友总聊天条数

打开与好友聊天界面并输入以下字符 //checkcount 点击发送 弹出toast

快速从0到1搭建vue工程(不通过cli)

关键链路如下

npm i vue@2.6 -S
npm i vue-template-compiler@2.6 vue-loader webpack@4 wepback-cli@3 webpack-dev-server@3 -D

index.js

import Vue from 'vue';
import App from './App.vue';

new Vue({
  render: h => h(App)
}).$mount('#app');

App.vue

<template>
  <div>
    <h3>计数器</h3>
    <button @click="count++">+</button>
    <span>{ {count}}</span>
    <button @click="count--">-</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  }
}
</script>

webpack.config.js(只有critical配置)

rules: [
    {
        test: /\.vue$/,
        use: 'vue-loader'
    }
]

const VueLoaderPlugin = require('vue-loader/lib/plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
    new HtmlWebpackPlugin({
        template: 'path/to/template.html',
        filename: 'path/to/destination',
        inject: true
    })
    new VueLoaderPlugin()
]

devServer: {
    hot: true
}

package.json

"scripts": {
    "dev": "webpack-dev-server",
    "build": "NODE_ENV=production webpack"
}

Tip:以上就已经完成了vue的所有关键的基础配置。后续建议external掉vue,然后在模板中嵌入vue runtime的scirpt以进一步减少包体积。 Tip:建议自行引入babel-loader

what? web地理位置API how? 判断地理位置API是否可用

if ('geolocation' in navigator) {

} else {

}

获取当前位置

navigator.geolocation.getCurrentPosition(function(position) {
    do_something(position.coords.latitude, position.coords.longitude);
}, function(err){ handle(err) });

监视位置变化或清除变化

var watchID = navigator.geolocation.watchPosition(function(position) {
  do_something(position.coords.latitude, position.coords.longitude);
}, function(err) { handle(error) });
navigator.geolocation.clearWatch(watchID)

可选选项

var geo_options = {
  enableHighAccuracy  : true,
  maximumAge            : 30000,
  timeout                    : 27000
};
var wpid = navigator.geolocation.watchPosition(geo_success, geo_error, geo_options);

what? desktop-notification API why? 原声alert交互体验差 how? 申请notification权限

window.addEventListener('load', function(){
    if (window.Notification && Notification.permission !== 'granted') {
        Notification.requestPermission(function () {
        if (Notification.permission !== status) {
            Notification.perssion = status
        }
        })
    }
})

触发通知

function notify(msg) {
    if (window.Notification && Notification.permission === 'granted') {
        var n = new Notification(msg)
    }
     // 如果用户没有选择是否显示通知
    // 注:因为在 Chrome 中我们无法确定 permission 属性是否有值,因此
    // 检查该属性的值是否是 "default" 是不安全的。
    else if (window.Notification && Notification.permission !== "denied") {
      Notification.requestPermission(function (status) {
        if (Notification.permission !== status) {
          Notification.permission = status
        }

        // 如果用户同意了
        if (status === "granted") {
          var n = new Notification(msg)
        }

        // 否则,我们可以让步的使用常规模态的 alert
        else {
          alert(msg)
        }
      });
    }
    // 用户拒绝通知
    else {
        alert(msg)
    }
}

previously 是否想过未来HTML5新特性可能取代目前火爆的MV*框架 what 监控DOM节点的属性、子抽象节点 how

// Firefox和Chrome早期版本中带有前缀
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver

// 选择目标节点
var target = document.querySelector('#some-id');

// 创建观察者对象
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  });
});

// 配置观察选项:
var config = { attributes: true, childList: true, characterData: true }

// 传入目标节点和观察选项
observer.observe(target, config);

// 随后,你还可以停止观察
observer.disconnect();

属性

描述

childList

如果需要观察目标节点的子节点(新增了某个子节点,或者移除了某个子节点),则设置为true.

attributes

如果需要观察目标节点的属性节点(新增或删除了某个属性,以及某个属性的属性值发生了变化),则设置为true.

characterData

如果目标节点为characterData节点(一种抽象接口,具体可以为文本节点,注释节点,以及处理指令节点)时,也要观察该节点的文本内容是否发生变化,则设置为true.

subtree

除了目标节点,如果还需要观察目标节点的所有后代节点(观察目标节点所包含的整棵DOM树上的上述三种节点变化),则设置为true.

attributeOldValue

在attributes属性已经设为true的前提下,如果需要将发生变化的属性节点之前的属性值记录下来(记录到下面MutationRecord对象的oldValue属性中),则设置为true.

characterDataOldValue

在characterData属性已经设为true的前提下,如果需要将发生变化的characterData节点之前的文本内容记录下来(记录到下面MutationRecord对象的oldValue属性中),则设置为true.

attributeFilter

一个属性名数组(不需要指定命名空间),只有该数组中包含的属性名发生变化时才会被观察到,其他名称的属性发生变化后会被忽略.

  1. 展示页面中所有元素

    [].forEach.call($$(‘‘),function(dom){dom.style.outline=”1px solid #” + (~~(Math.random()(1<<24))).toString(16)})

  1. JS错误处理正确姿势

    try {

    // do something

    } catch (e) {

    window.location.href = "https://stackoverflow.com/search?q=[js]+"+ e.message;

    }

  1. 单行代码写评星组件

    let rate = 1
    “★★★★★☆☆☆☆☆”.slice(5 - rate, 10 - rate)

  1. 如何装逼用代码骂人SB

    (!(+[])+{})[–[+””][+[]][+[]] + ~!+[]]+({}+[])[[~!+[]]~+[]]

  1. 如何用代码优雅的证明自己NB

    ([][[]]+[])[+!![]]+([]+{})[!+[]+!![]]

  1. 如何优雅的取随机数

    Math.random().toString(16).substring(2) // 13位
    Math.random().toString(36).substring(2) // 11位

  1. 如何优雅的取整

    var a = ~~2.332
    var b= 2.33 | 0
    var c= 2.33 >> 0

  1. 如何优雅实现金钱格式化

    var test1 = ‘1234567890’
    var format = test1.replace(/\B(?=(\d{3})+(?!\d))/g, ‘,’)

    console.log(format) // 1,234,567,890

  1. 逗号运算符

    var a = 0;
    var b = ( a++, 99 );
    console.log(a); // 1
    console.log(b); // 99

  1. 标准JSON实现深拷贝(会忽略undefined和function)

    var a = {

    a: '1',
    b: {
        ss: '123'
    }

    }
    var b = JSON.parse(JSON.stringify(a))

  1. parseInt(0.0000008) === 8

  2. 最短的代码实现数组去重

[...new Set([1, "1", 2, 1, 1, 3])]
  1. 用最短的代码实现一个长度为m(6)且值都n(8)的数组

    Array(6).fill(8)

  1. 如何优雅的实现强制参数?

    let mandatory = () => {return new Error(‘Missing Parameter’)}

    let foo = (bar = mandatory()) => {return bar}

  1. 如何优雅的可复用的校验模式?

    let schema = {

    name: {
        required: true
    }

    }

    let validator = (schema, values) => {

    for(let field in schema) {
        if (schema[field].required) {
            if (!values[field]) {
                return false
            }
        }
    }

    }

    // 使用方法
    validator(schema, { name: ‘Cecil’ })// return true

previously 还在用监听scroll事件+getBoundingClientRect()+节流函数实现lazyload么,你已经out了 what? 是浏览器原生的构造函数,该API可以自动”观察”元素是否可见,Chrome 51+ 已经支持。由于可见(visible)的本质是,目标元素与视口产生一个交叉区,所以这个 API 叫做”交叉观察器”。 how?

var io = new IntersectionObserver(callback, option)

// 开始观察
io.observer(document.getElementById('#example'))

// 停止观察
io.unobserver(element)

// 关闭观察器
io.disconnect()

callback一般会触发两次,进入/离开视口。另外回调函数以IntersectionObserverEntry对象作为参数。

{
  time: 3893.92,
  rootBounds: ClientRect {
    bottom: 920,
    height: 1024,
    left: 0,
    right: 1024,
    top: 0,
    width: 920
  },
  boundingClientRect: ClientRect {
     // ...
  },
  intersectionRect: ClientRect {
    // ...
  },
  intersectionRatio: 0.54,
  target: element
}
  • time:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒
  • target:被观察的目标元素,是一个 DOM 节点对象
  • rootBounds:根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null
  • boundingClientRect:目标元素的矩形区域的信息
  • intersectionRect:目标元素与视口(或根元素)的交叉区域的信息
  • intersectionRatio:目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0

Option对象 threshold属性决定了什么时候触发回调函数。它是一个数组,每个成员都是一个门槛值,默认为[0],即交叉比例(intersectionRatio)达到0时触发回调函数。 另外在容器内滚动也会影响目标元素的可见性。root属性决定目标容器所在的容器节点。容器元素必须为目标元素的容器节点。 (不清楚此属性的用法)rootMargin用来定义根元素的margin,用来扩展或缩小rootBounds这个矩形的大小,从而影响intersectionRect交叉区域的大小 notice 规格写明,IntersectionObserver的实现,应该采用requestIdleCallback(),即只有线程空闲下来,才会执行观察器。这意味着,这个观察器的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行。

docker for mac what? 是一种沙盒环境能够隔离运行软件的容器。 - web应用的自动化打包和发布; - 自动化测试和持续集成、发布; - 在服务型环境中部署和调整数据库或其他的后台应用; - 从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。 why? 安全。环境隔离,互不干扰。 以3M的linux内核承载,相比vmware成本较低。 镜像可编辑发布到官网。 how? docker ps docker info docker images docker version docker search tutorial docker pull learn/tutorial docker run learn/tutorial apt-get install -y ping docker ps -l docker commit [CID | 3] [image] docker inspect NAME|ID