前端三个基本结构:结构层HTML、表现层CSS、行为层Javascript。现在的Web前端应用已经不是简单的三层结构就能轻松解决,而是已经形成了编译流程化、生产环境基础优化结构运行的模式。
HTML4.01是基于SGML(Standard Generalized Markup language,标准通用标记语言)规范来制定的;HTML5不是基于SGML演化而来。
DOCTYPE
不存在或形式不正确会使用较低的浏览器标准模式来解析整个HTML文本。/**
* CSS1Compat 严格(标准)模式:width/height = content;
* BackCompat 混杂(怪异)模式:width/height = content + padding + border;
*/
document.compatMode;
的定义(不基于SGML无需DTD)兼容所有HTML的历史版本和最新的HTML5版本,不支持HTML5中的DOCTYPE定义的浏览器仍然会使用HTML4.01等历史版本的兼容模式来进行文档解析。
流动网页提速(Accelerated Mobile Pages)是Google推出一个提升页面资源载入效率的HTML提议规范。思路:使用严格受限的高效HTML标签,使用静态网页缓存技术来提高网络访问静态资源的性能和用户体验。
一般浏览器对同一个域名支持5-8个并行下载。可以通过分域存放,即可增大并行下载数,同时可以隔离COOKIE,减少请求头大小!
AMP通过自定义标签来替换img、video、audio、embed、form、table、frame、object、iframe这类影响页面渲染的标签,通过Javascript异步加载完成。某种意义上图片懒加载和AMP思想是一致的!
面向未来的组件标准,包括四个部分:Custom Elements、HTML Imports、HTML Templates、Shadow DOM。
示例:创建自定义color
<template>
<style>
.coloured {
color: red;
}
style>
<p>
My favorite color is: <strong class="coloured">Redstrong>
p>
template>
<script>
(function() {
// 根据HTMLElement原型对象创建一个新对象
var element = Object.create(HTMLElement.prototype);
// Gets content from
var template = document.currentScript.ownerDocument.querySelector('template').content;
/**
* createdCallback:实例生成时触发
* attachedCallback:实例插入HTML文档时触发
* detachedCallback:实例从HTML文档移除时触发
* attributeChangedCallback(attrName, oldVal, newVal):实例的属性发生改变时(添加、移除、更新)触发
*/
// 实例生成时触发
element.createdCallback = function() {
// 创建Shadow DOM 向用户隐藏细节,直接提供组件;以封装内部样式表,不会影响到外部
var shadowRoot = this.createShadowRoot();
// Adds a template clone into shadow root
var clOne= document.importNode(template, true);
shadowRoot.appendChild(clone);
};
// 自定义元素
document.registerElement('my-color', {
// 自定义网页元素的原型对象
prototype: element,
// 自定义元素继承某种特定的网页元素
extend: 'h1'
});
}());
script>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<link rel="import" href="my-color.html" charset="utf-8">
head>
<body>
<my-color>my-color>
body>
html>
1999年12月,ECMAScript3发布;2009年12月,ECMAScript5标准发布;2015年6月,ECMAScript6发布;2016年,ECMAScript7发布。Javascript代码遵循ECMAScript规范。
ECMAScript5内容主要包括严格模式、JSON对象、新增Object接口、新增Array接口和Function.prototype.bind。
注意:
Array.prototype.reduce(callback, initalValue)
callback(previousValue, currentValue, currentIndex, array)
initalValue决定循环次数
['a', 'b', 'c'].reduce(function(prev, curv){
console.log(prev, curv);
return prev + curv;
}); // 执行2次【第一次:a b,第二次:ab,c】
['a', 'b', 'c'].reduce(function(prev, curv){
console.log(prev, curv);
return prev + curv;
}, ''); // 执行3次【第一次: a,第二次:a b,第三次:ab,c】
下面只列举一些常用或者说需要格外注意的ES6语法。所有ES6相关内容请查看 ES6–变量的声明及解构赋值、ES6–字符串、正则、数值、数组的扩展、 ES6–对象、函数的扩展、ES6–Set、Map、Symbol、Proxy及Reflect、 ES6–Promise、Generator及async、ES6–Class、Module及常用特性。
let、const不再挂载到window对象下,不存在提升的问题;
console.log(a); // Uncaught ReferenceError: a is not defined
let a = 1;
console.log(window.a); // undefined
数组新特性Array.from()、Array.of()
function test() {
console.log(Object.prototype.toString.call(Array.from(arguments)));
console.log(Object.prototype.toString.call(Array.of(arguments)));
console.log(Object.prototype.toString.call([...arguments]));
}
test('a', 'b'); // 结果全部为[object Array]
Array.prototype.findIndex更灵活的返回某个特定数组元素在数组中的位置。
var ary = [1, 2, 8, 9];
// 只能返回存在的某个元素下标,不能自定义条件
ary.indexOf(8); // 2
// 返回第一个大于5的元素下标
ary.findIndex(function(value) {
return value > 5;
}); // 2
循环与迭代器Iterator
ES6之后,实现遍历的方式又多了几种(注意不要用for…in来遍历数组,在部分浏览器会产生乱序)。map、forEach不能直接跳出整个循环,只能跳出单步循环。最佳方式是使用for…of
var ary = [1, 2, 8, 9];
/*forEach*/
ary.forEach((value, index) => {
if(!!(value % 2))
return false;
console.log(index, value)
}); // 只是跳过了2,8、9继续输出
/*for...of*/
var ary = [1, 2, 8, 9];
for(value of ary) {
if(value === 2) {
break;
}
console.log(value);
} // 只返回1
Reflect对象和tail calls尾调用
Reflect可以理解为原有对象上的一个引用代理,它用于对原有对象进行赋值或者取值操作但不会触发对象属性的getter或setter调用(使用=对对象进行赋值或取值操作会自动触发getter或setter方法)。
Javascript内存泄漏:
(1)闭包函数;(2)全局变量;(3)对象属性循环引用;(4)DOM节点删除时未解绑定事件;(5)Map和Set的属性直接删除;上述都会使内存无法被正常回收,导致内存泄漏。
异步方法:
(1)setTimeout;(2)事件监听;(3)观察者模式;(4)$.Deferred;(5)promise;(6)generator;(7)async/wait;(8)第三方async库等。
类别 | 权重 |
---|---|
!important | 最高 |
内联style | 1000 |
#id |
100 |
.class |
10 |
name |
1 |
优先级高的会覆盖优先级低的;相同优先级书写在后面的会覆盖前面的!
<div id="content" class="blue">testdiv>
<style type="text/css">
#content { /*100*/
background-color: red;
}
body div.blue { /*1+1+10*/
background-color: blue;
}
body .blue { /*1+10*/
background-color: green;
}
style>
CSS伪类和伪元素
:visited、:hover、:first-child、:nth-child、:enable、:checked
实现样式统一化的三种思路:reset、normalize、neat
reset将不同浏览器中标签元素的默认样式全部清除,清除不同浏览器下默认样式的差异;
body, div, span, ...{
margin: 0;
padding: 0;
}
normalize在整站样式基本确定的情况下对标签元素统一使用同一个默认样式规则;
body, p, ul, ol, ...{
margin: 5px;
padding: 5px;
}
neat是上述两者的结合。
通过编写更高效、易管理的类CSS脚本并将它们自动生成浏览器解释执行的CSS代码,实现高效开发和便捷管理。常见的有SASS、LESS、POSTCSS。
以SASS为例,主要包括模块引用、嵌套、父级选择符、变量、运算、函数、篡写、指令、mixin、继承等属性。**函数和mixin区别:**mixin的内容会被全部填充到引入的元素代码里面,而function函数只做过程处理并输出。
通常实现动画的方式有如下几种:(1)Javascript直接实现动画;(2)可伸缩矢量图形SVG动画;(3)CSS transition;(4)CSS3 animation;(5)Canvas动画;(6)requestAnimationFrame。
人眼能辨识的流畅动画为每秒60帧,1000ms/60=16ms可以用来Javascript中
setInterval(() => {}, 16)
的间隔时间!
标签元素,就可以认为是超出了动画边界;
)边界将不被展示;通常认为,响应设计是根据不同设备浏览器尺寸或分辨率来展示不同页面结构、行为层、表现层的设计方式。目前主流的实现方式:(1)通过判断userAgent来跳转到不同页面完成不同设备浏览器的适配,即维护两个不同站点来根据用户设备进行相应的跳转;(2)使用media query媒体查询手段,让页面根据不同设备浏览器自动改变页面的布局和显示,不需要跳转。
通常我们在选择方案时,需要考虑下面几个问题:
根据不同的设备浏览器渲染不同的页面结构,而不是直接跳转。可以通过下述两种方式:一是页面内容在前端渲染;二是页面内容在后端渲染。
首先要确保以移动端优化资源为主,保证移动端页面的首屏内容优先加载,然后通过异步的方式来实现桌面端或移动端剩余内容的加载。
let isMobile = navigator.userAgent.match(/iPhone|iPad|Android|iPad/i);
if(isMobile) {
require.async(['zepto', './mobileMain'], function($, main) {
main.init();
});
}else {
require.async(['jQuery', './main'], function($, main) {
main.init();
});
}
通过URL或者UA判断设备,尽可能将桌面端和移动端的业务层模块分开维护。这样既能复用共同的基础组件,还可以差异化开发不同的业务组件。Javascript和CSS资源完全分开加载,实现了两个端加载内容的相互对立。
let isMobile = this.headers["user-Agent"].match(/iPhone|iPad|Android|iPad/i);
if(isMobile) {
res.body = yield render('pages/mobile/main', {
data: pageData
});
}else {
res.body = yield render('pages/pc/main', {
data: pageData,
moreData: moreData
});
}
目前主要网站60%以上的流量数据都来自图片,确保不影响用户体验的前提下尽可能降低图片的输出流量具有很重要的意义。
(1)使用Media query背景图片替换
/* 默认使用1.JPG,小于500px使用2.JPG */
.img {
background-position: center center;
background-image: url('1.JPG');
}
@media only screen and (max-width :500px) {
.img {
background-image: url('2.JPG');
}
}
(2)Picture标签元素
<picture>
<source media="(max-width: 500px)" srcset="2.JPG">
<source srcset="1.JPG">
<img srcset="1.JPG" alt="My default image">
picture>
(3)模板判断响应式图片
{% if isMobile %}
<img src='2.JPG'>
{% else %}
<img src='1.JPG'>
{% endif %}
(4)图片服务器判断输出内容
浏览器访问图片服务器时带上浏览器UA或者URL参数信息,判断返回相关图片。
响应式布局是根据浏览器宽度、分辨率、横屏、竖屏等情况来自动改变页面元素展示的一种布局方式,一般使用栅格方式来实现;
<style>
.row {
width: 100%;
}
.row .col-1 {
width: 25%;
}
.row .col-2 {
width: 50%;
}
.row .col-3 {
width: 75%;
}
.row .col-4 {
width: 100%;
}
/* 屏幕分辨率为1280 */
/* 如果小于640px, 一排显示两个 */
@media screen and (max-width: 640px){
.row .col-1 {
width: 50%;
}
.row .col-2, .row .col-3 {
width: 100%;
}
}
/* 如果小于414px, 一排显示一个 */
@media screen and (max-width: 414px){
.row .col-1{
width: 100%;
}
}
div {
padding: 0;
margin: 0;
box-sizing: border-box;
border: 1px solid rgba(86,61,124,.2);
float: left;
background-color: rgba(86,61,124,.15);;
}
div.row {
border: 0;
}
style>
<div class="row">
<div class="col-1">.col-1div>
<div class="col-2">.col-2div>
<div class="col-3">.col-3div>
<div class="col-4">.col-4div>
div>
屏幕适配布局是为了实现网页内容根据移动端设备屏幕大小等比例缩放所提出的一种布局计算方式。通常依据HTML中标签元素的zoom属性缩放和根据REM自适配方案实现等比例缩放。
(1)zoom属性控制方案
如果希望在320px宽度屏幕上显示的内容在414px的宽度屏幕上进行等比例自动放大,可以考虑使用元素CSS的zoom属性来解决。document.body.style.zoom = screen.width/320;
通常使用Javascript计算得出,如果Javascript在页面渲染之后完成,则会出现页面内容全部重排情况。
(2)REM屏幕适配方案
CSS大小尺寸的表示单位主要有像素px、相对父元素大小百分比%、相对于当前对象内文本字体font-size的大小em、相对于文档根元素font-size的大小rem。
如果给HTML根元素一个根据屏幕自动调整的font-size,页面上所有元素的尺寸全部以rem为单位,无论屏幕宽度怎样变换,页面的内容和屏幕的比例将始终不变,实现了页面根据屏幕自动缩放。
1rem = 屏幕宽度*屏幕分辨率/10
这样得到的1rem恰好是屏幕宽度的10%。
1rem = 屏幕宽度/320*10
这样1rem在宽度320px的屏幕上表示的是10px。
和结构层类似,行为层的响应式同样分为Javascript内容在前端引入和在后端引入两种情况。