现代web前端技术概述
页面内容太多了,如何保证开发效率?
使用jQuery或者MVVM框架开发
页面内容太多了,如何组织和管理代码?
使用H5的web component组件化开发方式开发,模块或者组件化。
页面内容太多了,如何快速实现页面加载?
实现按需加载,异步加载,懒加载。
页面图片太多了,如何快速加载图片。
使用webp格式的图片,在不影响图片质量的前提下快速加载图片。
对于重复打开的页面,如何快速加载页面。
不重复发送请求,合理利用文件缓存。
技术栈:前端开发框架,模块化和组件化,资源异步加载,响应式站点开发,缓存和前端优化。
当我们在浏览器地址栏输入一个地址之后,服务端和客户端分别会做什么事?
1.在接收到用户输入的网址之后,浏览器会开启一个线程来处理这个请求,对用户输入的URL进行解析和判断,如果是HTTP协议就按照HTTP方式来处理。
2.调用浏览器引擎中的对应方法,比如WebView中的loadURL方法,分析并加载这个URL地址。
3.通过DNS解析获取该网站地址对应的IP地址,查询完成后连同浏览器的Cookie,userAgent等信息向网站目的IP发出GET请求。
4.进入HTTP协议会话,浏览器客户端向Web服务器发送报文。
5.进入网站后台上的Web服务器处理请求,如Apache,Tomcat,Node.js等服务器。
6.进入部署好的后端应用,如PHP,JAVA,JS,Python等后端程序,找到对应的请求逻辑,这期间可能会读取系统缓存,或者查询数据库等。
7.服务器处理请求并返回响应报文,此时如果浏览器访问过该页面,缓存上对应的资源,会与服务器最后记录做对比,一致返回304,否则返回200和对应的内容。
8.浏览器下载HTML文档(响应报头状态码为200时)或者从本地缓存读取文件内容(浏览器缓存有效或响应报头状态码为304时)
9.浏览器根据下载接收到的HTML文档解析结构建立DOM文档树,并根据HTML中的标记请求下载指定的MIME类型文件(CSS,JS),同时设置缓存文件。
10.页面开始解析渲染DOM,css根据规则解析并结合DOM文档树进行网页内容布局和绘制渲染,JS根据JS脚本来操作DOM。
简析成为一句话:用户地址栏输入框,网络请求,浏览器文档解析,渲染引擎,JavaScript执行引擎,客户端存储。
页面内容多,如何进行项目的管理?
将复杂的代码结构拆分成为多个独立,简单,解耦合的结构或文件分开管理。
页面加载的内容很多,怎样保证将页面内容尽快的显示给用户?
异步加载内容,参考vue的懒加载。 像vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,时间过长,会出啊先长时间的白屏,即使做了loading也是不利于用户体验,而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时 vue-router的懒加载
路由配置routes:[
{ path:'/Login', name:'Login', component:resolve => require(['@/components/Login'],resolve)
},
····]
注意一点: 就是用了懒加载后打完包直接运行那个index.html会报错,报文件引用错误其实是打包时候路径配置有点问题修改下就好了。
找到build下面的webpack.prod.conf.js 添加 publicPath:"./",
限制页面中的图片大小,让页面快速显示?
使用最新格式的图片,比如webp格式的图片。在图片质量不降低的前提下,可以大幅度减少图片的网络流量消耗。WebP格式,谷歌(google)开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器宽带资源和数据空间。Facebook Ebay等知名网站已经开始测试并使用WebP格式。
对于重复打开的页面,能否让服务器不请求重复的数据呢?
合理的运用文件缓存方式:H5离线缓存---manifest什么是Manifest:其实Manifest是一个简单的 文本文件,它的扩展名是任意的,定义需要缓存的文件、资源,当第一次打开时,浏览器会自动缓存相应的资源。
Manifest的使用:html新增了一个manifest属性,可以用来指定当前页面的manifest文件。
创建一个和html同名的manifest文件,比如页面为index.html,那么可以建一个index.manifest的文件,然后给index.html的html标签添加如下属性即可:<html lang="en" manifest="index.manifest"> 或<html manifest="http://www.example.com/index.manifest">
1、manifest 的引入可以使绝对路径也可以是相对路径,如果你使用的是绝对路径,你的manifest文件必须和你的站点挂在同一个域名下。
2、manifest文件你可以保存为任意的扩展名,但mine-type 必须是 text/cache-manifest。<html lang="en" manifest="index.manifest"> 或 <html lang="en" manifest="index.cache"> 在服务器上部署时需要在服务器上添加相应的mie-type需要注意的是manifest文件放在服务器上,MIME类型必须是text/cache-manifest,如果使用 Apache,需要修改.htaccess文件。IE下默认application/octet-stream,需要在服务器指定manifest 标签应该包含到你需要缓存资源的页面,当第一次打开该页面时,浏览器会解析该页面中的mainfest,并缓存里面列举的资源,同时该页面也会自动会被浏览器缓存,即使该页面没有在Manifest中列出。注意: "/page-url/", "/page-url/?something", "/page-url/?something-else" Manifest 会当成不同的页面,如果page-url 页面中包含了 Manifest 属性则浏览器会将该页面中列举出来的资源分别保存,所以Manifest最好使用在SPA(单页应用)项目中。在Chrome中,可以使用chrome://appcache-internals/ 查看你缓存在本地的资源文件。
1、第一行是CACHE MANIFEST 这是必须需要的。
2、CACHE(必须) 标识出哪些文件需要缓存,可以是相对路径也可以是绝对路径。这里列举出来的文件,当第一次加载下来时,会被浏览器缓存在本地。
3、NETWORk 这一部分是要绕过缓存直接读取的文件,可以使用通配符 *,大多数网站使用 * 。 当使用* 时 表示所有站点都可访问该资源。
前端技术基础
开发调试技术
前端相关协议
三层结构演进与实践
响应式网站
页面交互框架
大型项目实践经验
跨栈开发实践
前端技术基础
前端与协议
前端三层结构与应用
HTML部分
必须要知道的DOCTYPE
为什么只用写一个DOCTYPE即可了,不像htmk4那样写一大串?
因为html5不是按照SGML规定来的,而是一套全新的W3C的实现方案。HTML5向后兼容了绝大多数低版本的HTML元素标签,并新增了很多特性。
如果,我们在页面中写了DOCTYPE,页面又不支持H5,该怎么办呢?
其实,完全不用担心,DOCTYPE声明只用于指示WEB浏览器页面使用哪个HTML版本编写的指令进行解析,不支持H5的话,浏览器会自动使用HTML4的标准来解析,如果书写了H5特有的特性,也要在不兼容H5的浏览器上解析,我们可以使用html5.js来兼容。
关于前端标签元素或特性的兼容性,我们一般可以通过caniuse这个网站来检查。
语义化标签
在HTML结构的恰当位置上使用语义恰当的标签,使页面具有良好的结构,使页面标签元素具有含义,能够让人或搜索引擎更容易理解。
table元素特殊点
在前端页面中使用<table>这个元素会使页面加载缓慢,因为<table>里面的内容渲染是等表格内容完全解析完成后渲染树一次性渲染到页面上,所以,我们常常可以用div来模拟表格,来提高渲染的速度。
如何用div来模拟table.
table事实上是具有默认样式的div容器:
<table> //display:table; <thead> //display:table-header-group; <tr> //display:table-row; <td>1</td> //display:table-cell; <td>2</td> <tr> </thead> <tbody> //display:table-row-group; <tr> <td>3</td> <td>4</td> <tr> </tbody> </table>
所以,为div加上这些样式,就可以模拟table布局, 其中,thead/tbody/tr都是可以省略的。
<div id=testDivTable> //display:table; <div> //display:table-row; <div> //display:table-cell; 1 </div> <div> 2 </div> </div> </div> #testDivTable{ width:100%; display:table; } #testDivTable>div{ display:table-row; } #testDivTable>div>div{ display:table-cell; vertical-align:middle; }
新鲜玩意儿——PWA渐进式Web App
一个 PWA 应用首先是一个网页, 可以通过 Web 技术编写出一个网页应用. 随后添加上 App Manifest 和 Service Worker 来实现 PWA 的安装和离线等功能
解决了哪些问题?
-
可以添加至主屏幕,点击主屏幕图标可以实现启动动画以及隐藏地址栏
-
实现离线缓存功能,即使用户手机没有网络,依然可以使用一些离线功能
-
实现了消息推送
它解决了上述提到的问题,这些特性将使得 Web 应用渐进式接近原生 App。
APP Manifest 实现添加至主屏幕
service worker 实现离线缓存
service worker 实现消息推送
PWA的优势
-
可以将app的快捷方式放置到桌面上,全屏运行,与原生app无异
-
能够在各种网络环境下使用,包括网络差和断网条件下,不会显示undefind
-
推送消息的能力
-
其本质是一个网页,没有原生app的各种启动条件,快速响应用户指令
PWA存在的问题
-
支持率不高:现在ios手机端不支持pwa,IE也暂时不支持
-
Chrome在中国桌面版占有率还是不错的,安卓移动端上的占有率却很低
-
各大厂商还未明确支持pwa
-
依赖的GCM服务在国内无法使用
-
微信小程序的竞争
尽管有上述的一些缺点,PWA技术仍然有很多可以使用的点。
-
service worker技术实现离线缓存,可以将一些不经常更改的静态文件放到缓存中,提升用户体验。
-
service worker实现消息推送,使用浏览器推送功能,吸引用户
-
渐进式开发,尽管一些浏览器暂时不支持,可以利用上述技术给使用支持浏览器的用户带来更好的体验。
https://github.com/bjw1234/newsPWA --PWA DEMO
JAVASCRIPT部分
新增的Object原型上的方法
方法 | 描述 |
---|---|
getPrototypeOf | 返回一个对象的原型 |
getOwnPropertyDescriptor | 返回某个对象自有属性的属性描述符 |
getOwnPropertyNames | 返回一个数组 |
create | 创建一个拥有指定原型和若干指定属性的对象 |
defineProperties | 为对象定义一个新属性,或者修改已有的属性,并对属性重新设置getter和setter,这里可以被用作数据绑定的对象劫持作用 |
新增的Array方法
方法 | 描述 |
---|---|
indexOf | 返回根据指定元素找到的第一个索引值,如果存在则返回-1 |
lastIndexOf | 最后一个 |
every | 测试数组中的所有元素是否都通过了指定函数的测试 |
some | 测试数组中的某些元素是否通过了指定函数的测试 |
forEach | 令数组的每一项都执行指定的函数 |
map | 返回一个由原数组中每个元素调用某个指定方法得到的返回值所组成的新数组,返回每一个处理的结果 |
filter | 利用所有通过指定函数处理的元素创建一个新的数组并返回 |
reduce | 接收一个函数作为累加器,数组中的每个值开始缩减,最终缩减为一个值 |
Function.prototype.bind
bind()方法会创建一个新函数,称为绑定函数。当调用这个绑定函数时,绑定函数会以创建它的第一个参数作为this,以传入bind()第二个及以后的参数作为原函数的参数来使用。
bind(),call(),apply()这种直接改变this指向方法之间的区别。
bind()方法是返回一个新的函数,并将传入的参数和函数绑定起来。 call(),apply()则是用新的this指向直接去调用,执行函数。
es6
let,const,var 三种变量声明方式之间的区别
let,const属于块级作用域变量的声明,且只在块级作用域中生效,使用const声明的变量必须进行初始化赋值,且一旦赋值后不可再改变,使用let,const在全局作用域下声明的变量不会作为属性添加进全局作用域对象中,这点和var不一样。另外一点,使用let,const效率会比var高。
新增的数组方法
Array.prototype.from --- 将类数组对象转化为真正的数组
Array.prototype.of -- 可以将传入的参数转换为数组
const arrayLike = { '0': 'a', '1': 'b', '2': 'c', length: 3 }; console.log(arrayLike); //{ '0': 'a', '1': 'b', '2': 'c', length: 3 } // ES5 写法一 const array1 = [].slice.call(arrayLike); console.log(array1); //[ 'a', 'b', 'c' ] // ES5 写法二 const array2 = Array.prototype.slice.call(arrayLike); console.log(array2); //[ 'a', 'b', 'c' ] // ES6 const array3 = Array.from(arrayLike); console.log(array3); //[ 'a', 'b', 'c' ]
常见的类数组
arguments
NodeList
字符串 String
TypedArray
为函数参数提供默认值写法
箭头函数 -- 注意:this值和外层的this值相等。
类的实现,统一了实现继承的方式,在es5时,实现继承的方式有:原型链继承,构造函数继承,实例继承和拷贝继承。在es6实现了使用class继承。
class 和 extends
模块module
使用import 和 export
promise 解决回调地狱
Promise 表示一个异步操作的执行返回状态,这个执行返回状态在Promise对象创建时是不可知的,它允许为异步操作的成功或失败指定处理方法。
使用then方法为交互的核心。
通常Promise的状态有三种,Fullfilled--成功,Rejected--失败,Pending-- 正在窒执行中。
var p = new Promise(function(resolve, reject){ //做一些异步操作 setTimeout(function(){ console.log('执行完成'); resolve('随便什么数据'); }, 2000); });
Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。
上一个操作返回的数据可以return 给下一个then接收。
css表现层
CSS属性分类
属性类型 | 属性名 |
---|---|
布局类属性 | position类,弹性布局flex,浮动布局float,对齐align |
几何类属性 | 盒模型相关(margin,padding,width,height,border),box-shadow, |
文本类属性 | font类 |
CSS3动画属性 | transition,animation |
查询类 | 媒体查询 |
CSS预处理器 LESS
在webpack中使用less npm install -D less less-loader // webpack.config.js -> module.rules { test: /\.less$/, use: [ 'vue-style-loader', 'css-loader', 'less-loader' ] } 在style标签中使用 lang=less scope
实现CSS3 animation动画
@keyframes move { //关键帧的处理 ···· } animation: move 4s infinite.
响应式页面的实现
第一种方案:通过前端或后端判断userAgent来跳转不同的页面完成不同设备浏览器的适配,也就是维护两个不同的站点来根据用户设备进行对应的跳转。适用于功能复杂并对性能要求很高的站点应用。
第二种方案:使用媒体查询等手段,让页面根据不同设备浏览器自动改变页面的布局和显示,但不做跳转。
//前端页面跳转判断,获取用户的userAgent if(navigator.userAgent.match(/iPhone/ipod/Android/ipad/i)){ let hash = window.location.hash, params = window.location.search; ```` }
移动端页面的适配
使用rem
flexible.js正是利用rem单位相对根元素<html>的font-size来做计算,而我们需要做的就是根据不同的屏幕算出html的font-size,而页面内的大小单位都根据rem来写,从而实现了自适应。
前端项目与技术实践
前端通用规范
html代码编写规范
-
文档类型定义--使用H5的标准文档定义
-
head内容必须定义title,keyword,description,保证基本的SEO页面关键字和内容描述。
-
省略type属性,在引入js和css时,type属性省略不写,因为默认的就行了
-
使用双引号包裹属性值
-
属性值省略--非必需的属性值可以省略,比如说:readonly,disabled,required.
-
嵌套一定得正确,尽量使用语义化的标签,不允许交叉,也不允许在inline元素中包含block元素。
-
标签闭合,非自闭标签必须添加关闭标识,自闭合标签无须关闭。
-
使用img的alt属性
-
使用label的for属性
-
按模块添加注释
-
标签元素格式
-
语义化标签
CSS编写规范
-
CSS引用规范,要使用link的方式引入,因为外部文件可以复用,提高浏览器加载效率。
-
样式的命名约定--BEM。(块,元素,修饰符)
-
简写方式 属性值为0,一定要去掉单位
-
属性书写顺序 -- 先写元素的布局属性,再写元素的内容属性。
-
使用CSS预处理器
JS编写规范
-
引号
-
变量命名 -- 使用驼峰
-
使用大括号包裹代码块
-
不要在条件语句或者循环语句中声明函数
-
数组拷贝使用 ... 实现 - - const array = [1,2,3] itemArray = [...array];
-
推荐 使用promise来处理回调
let promise = new Promise(function(resolve,reject){}); promise.then(function(){ //成功处理 },function(){ //失败处理 })
VUE编写规范
-
基于组件化开发理解
-
组件命名规范
-
结构化规范
-
注释规范
-
编码规范
GA 数据分析--设置数据埋点- 分析用户行为
前端性能优化
桌面端性能优化
-
减少HTTP资源请求次数
-
减少HTTP请求大小 --使用webpack打包,雪碧图的使用
-
将CSS,JS放在外部文件中引入
-
避免页面中空的href和src -- 浏览器在渲染过程中仍会加载空的href属性和src属性直至加载失败,这样就阻塞了页面中其他资源的下载。
-
使用文件缓存,避免重复向服务端请求相同的数据
-
减少页面的重定向 -- 每次重定向都会延长页面返回页面内容的时间。
-
使用CDN。
-
使用可缓存的Ajax
$.ajax({ url:url, type:'get', cache:true,
})
移动端性能优化
## 移动端性能优化 - 首屏数据请求提前 --通常数据请求是页面内容渲染中关键路径最长的部分,所以要尽可能的将数据请求提前,避免加载完全部的js才完成数据请求。 - 首屏加载和按需加载,非首屏内容滚屏加载,保证首屏内容最小化。 - inline首屏必备的css和javascript -- 通常为了在html加载完成时能使浏览器中有基本的样式,需要将页面渲染时必备的css和javascript内嵌到页面中。 - 资源预加载 - 使用静态资源离线缓存方案 - 使用iconfont代替图片 - 使用touchstart代替click -- 因为click在移动端存在300ms延迟 - 使用css3动画,开启GPU加速 -- 设置 transform:translateZ(0)来开启移动设备的GPU加速
开发中需要注意的问题
-
首先要明确产品经理提出的需求
-
技术方案是否可行,即需求开发的难度
-
需求性价比是否够高,如果一个功能实现要求代价很高,而实现后价值不大,这种需求建议沟通后,直接砍掉。
-
需求是否合理,不合理的不要做。
-
风险管理,产品需求经常会变更,开发也会延期,如果因为需求变更导致延期一定要告知产品经理,不要等到需求交付的时候再告诉大家,需求仍未完成。
-
与后端开发定义好开发接口,通常是以接口开发文档的方式来定义的。
在平时仍需要自己关注的点
学会高效的沟通
使用高效的开发工具
webstrom X-sell ftp vmware git
处理问题
学会前端项目开发流程设计
快速进行前端项目的基础工程,常用业务模块以及开发流程的搭建能力。
包括:前端框架选型,模块化方案,代码规范化,构建自动化,组件化目录设计,代码优化处理,数据统计,同构项目结构设计等。
切勿过分追求技术
不要一直将技术放在第一位,因为一切的技术最终都是为了产品实现服务的。要更多的考虑如何更好的实现产品服务。
必要的产品设计思维
什么是产品思维:通俗的讲就是用户体验思维,或者说将自己当成普通用户来对产品进行思考。因为大多数产品经理只站在用户的角度考虑问题,没有技术方面的考虑。