Front-End basics

浏览器的解析原理是怎样的?

浏览器的文档流 –> HTML DOM 结构 –> CSS 结合 –> 布局 –> 绘制页面。

从服务端传过来的 text/html 是如何被绘制成页面的?

  1. 服务端返回 text/html 格式的文档流, HTML 字符串描述了一个页面的结构,浏览器会把 HTML 字符串解析成 DOM 树形结构。

  1. CSS 样式可以在 WEB 页面里映射成 CSSOM(CSS对象模型),它和 DOM 结构比较像, 不是增量模式,而是组合模式。

  1. CSSOM 树和 DOM 树合并成渲染树

  1. 完整 DOM 结构。DOM 结构有两个规则:一个是 HTML 文档对象,一个是通过接口获取 DOM 元素。通过 document.getElementById() 以获取元素节点。

性能优化策略

简要介绍预加载


<head>
  <meta charset="utf-8">
  <title>JS and CSS preload example</title>

  <link rel="preload" href="style.css" as="style">
  <link rel="preload" href="main.js" as="script">

  <link rel="stylesheet" href="style.css">
</head>

<body>
  <h1>bouncing balls</h1>
  <canvas></canvas>

  <script src="main.js"></script>
</body>

CSS像素

CSS像素分为了 物理像素(physical pixel) 和 设备独立(逻辑)像素(density-independent pixel)。

设备像素比(devicePixelRatio) = 物理像素 / 设备独立像素。

CSS布局

Web中主流的两种布局方式:Flexbox布局 和 CSS Grid布局。

Flex布局 旨在提供一个更加有效的方式制定、调整和分布一个容器里的项目布局,即使他们的大小是未知或者是动态的。

在Flexbox布局中有主轴(Main Axis)和侧轴(Cross Axis)两个概念

实现水平垂直居中


<div class="container">
  <div class="block"></div>
</div>

.container {
  display: flex;  // 默认为水平布局,主轴线为水平
  justify-content: center; // 水平居中
  align-items: center;    // 垂直居中
}

.block {
  height: 100px;
  width: 100px;
}

CSS Grid布局(又名"网格”),是一个基于二维网格布局的系统,主要目的是改变我们基于网格设计的用户接口方式。

三种回调比较 JS Callback VS Promise VS Async await

JS Callback : 产生地狱般的回调嵌套,一旦嵌套次数过多,就很容易使我们的代码难以理解和维护。

Promise: 通过 链式调用的方法 去解决回调嵌套的问题,使我们的代码更容易理解和维护,同时 Promise 还增加了许多有用的特性,让我们处理异步编程得心应手。

Async await: 是 ES7 引入的新的异步代码规范,它提供了一种新的编写异步代码的方式,这种方式在语法层面提供了一种形式上非常接近于同步代码的异步非阻塞代码风格。

实现一个基于 XMLHttpRequest 对象实现一个 Promise 的 Ajax 方法封装(面试专用考题),再对比 Promise 和 Async Await的差异,以及他们的优缺点。


/**
* 请求服务
* @param {Object} param
* @param {String} param.url    请求URL
* @param {String} param.type   默认 'GET'
* 
* @return new Promise
*/

function fetchRequest (param) {
  const type = param.type || 'GET',
  const url = param.url;
  if (!url) {
      new TypeError('param url must be set...')
  }
  return new Promise( (resolve, reject) => {
      let xhr = new XMLHttpRequest();
      xhr.open(type, url, true);
      // 1. 监听状态
      xhr.onreadystatechange = function () {
          // 2. readyState = 4, status = 200 是请求成功的标识
          if (xhr.readyState === 4) {
              if (xhr.status === 200) {
                  resolve(xhr.responseText, xhr);
              } else {
                  reject({
                      code: xhr.status, 
                      message: xhr.response 
                  }, xhr);
              }
          }
      }
      xhr.send();
  })
}

异步调用的最大问题是不能 Catch 到错误信息,同时编码上产生大量的回调函数 或者链式调用。

Async await 调用是把 Promise 的链式调用同步化,同时可以 Catch 到错误栈信息。

Promise 使用


const getGithubHooks = () => {
  return fetchRequest({
      api: 'https://github.com/xxx'
  }).then(result => {
      return result;
      // result data
  }.catch(err => {
      // error 
  })
}

Async await 使用


async function getGithubHooks() {
 let result = null
 // 同步 try catch 错误
 try {
  result =  await fetchRequest({
     api: 'https://github.com/xxx'
  })
  return result
 } catch(err) {
  return err; 
 }
}