Web前端
浏览器组成
渲染引擎
解析HTML构建DOM树 -> 构建渲染树 -> 渲染树布局阶段 -> 绘制渲染树
页面生成后 如果页面元素位置发生变化 就要从布局阶段开始重新渲染
HTML解析
当进行token解析后,就可以利用栈来构建一颗DOM树
CSS解析
依次拿到上一步构造好的元素,去检查它匹配到了哪些规则,再根据规则的优先级,做覆盖和调整
选择器的出现顺序,必定跟构建 DOM 树的顺序一致。这是一个 CSS 设计的原则,即保证选择器在 DOM 树构建到当前节点时,已经可以准确判断是否匹配,不需要后续节点信息
因为父元素选择器要求根据当前节点的子节点,来判断当前节点是否被选中,而父节点会先于子节点构建,这点跟原则冲突,所以目前并没有父元素选择器这种玩意
持久化存储机制
- HTTP缓存
- localSorage:单个域下存放容量有限
- sessionStorage:浏览器关闭自动清空
- Cookie
- sessionCookie
- HTTP only
- WebSQL:特定浏览器的特性
- IndexDB:NoSQL类型的数据库 大小限制50M
- Application Cache
- 渐渐废弃 使用ServiceWorkers替代
- cacheStorage
- ServiceWorker规范中的Cache对象
- Flash缓存
浏览器Web安全
- X-XSS-Protection
- 控制浏览器对反射型XSS的防护
- Strict-Transport-Security
- 强制所有通信使用HTTPS
- Content-Security-Policy
- 控制浏览器只信任来自指定源的内容
- Access-Control-Allow-Origin
前端与协议
- HTTP
实时协议
- WebSocket
- Poll(轮询):实时性差 影响性能
- Long-poll(长轮询):比上面好一点
- 前端DDP(分布式数据协议)
- meteor:服务端-客户端双向数据更新
Native交互协议
混血应用特性:
- 可用系统资源少
- 浏览器内核支持较新的特性
- 可实现离线应用
- 机型兼容(屏幕兼容)
- 支持与Native交互
Web到Native协议调用:
- 通过URI
- Web应用通过发起一个URI请求 Native会进行捕获
- addJavascriptInterface
- Native会注入一个全局对象给Web调用
Native到Web:
- Native通过loadURL调用Web暴露的全局对象或者方法
JSBridge协议规范
- Native注册一个自定义JSBridge Schema头
- 协议URL由几部分组成:欲被调用的类名、回调方法、欲被调用的方法、json对象(调用方法的参数)
三层结构
结构层
XML -> HTML -> HTML5
DOCTYPE:指示浏览器使用哪个HTML版本编写的指令进行解析
语义化标签:语义化标签帮助人更容易理解
AMP HTML:提升页面资源载入效率的规范
Shadow DOM:用来支持实现Web Component,如video标签等,其不会被外界的css或者js所影响
浏览器脚本
ES5 -> CoffeScript -> ES6 -> TS
表现层
CSS
CSS统一处理:
- reset:清除所有元素默认样式
- normalize:为所有元素增加默认样式
- neat:上面两种方式的组合
CSS预处理:sass less ...
一个良好的预处理器的功能:
- 变量声明计算
- 语法表达式 if-else for
- 函数处理
- 属性继承
- 兼容性补全 自动添加浏览器私有前缀
动画实现:
- js实现:由于频繁重绘 非常消耗性能
- SVG动画:比js实现功能会更丰富 但一旦复杂起来 仍会影响性能
- CSS3 transition:只能实现过渡变化
- CSS3 animation:脱离JS 可以硬件加速 复杂动画也能应付
- Canvas 动画:本质是通过js控制标签来实现
响应式页面
- 基于UA跳转
- 基于媒体查询响应式
结构层响应式
- 结构层数据响应式
- 在前端判断不同端加载不同的数据
- 后端数据响应式
- 后端渲染时直接判断 差别渲染
- 结构层媒体查询
- 根据不同的屏幕渲染不同的图片 节省流量
- Picture 可以包含多个图片 自动进行选择(Polyfill)
- 后端模板判断渲染不同图片
- CDN
表现层响应式
- 响应式布局:栅格布局
- 屏幕适配布局:viewport
- 控制zoom
- REM适配
行为层响应式
- 通过js进行判断执行不同脚本
- 后端判断直接渲染不同脚本
现代前端交互框架
直接DOM操作
随着AJAX技术的发展 在DOM操作上面也越来越复杂
这个时期的代表性框架就是jQuery,其主要功能就是封装了浏览器的DOM API
MV*交互
- 前端MVC
通过将组件的数据及行为划分到 M V C 来进行管理,由系统统一来控制
- 前端MVP
使用P来处理逻辑 M 和 V 只反映视图和数据
各个部位职责更清晰 但是P的内容变得很重
- 前端MVVM
自动化的MVP 使用ViewModel 替代 P,这样数据的变化就会自动影响到识图 反之亦然
数据更新检测
- 手动触发更新
- 脏检测机制:当ViewModel的某个值发生变化时找到其相关联的所有元素 然后比较更新
- 前端数据对象劫持:通过Object.defineProperies来监听get和set,当发生变化 则需要运行相对应节点的指令
- ES6 Proxy:实现效果跟上面一样
Virtual DOM交互
通过新建一个虚拟的DOM数据结构 并将其与真实DOM对比 找出差异部分进行更新
核心实现
- 将真实DOM转换为虚拟DOM:
自己解析HTML而非使用DOM API来生成
- 对比虚拟DOM
使用多叉树遍历算法 DFS或者BFS 遍历过程中需要记录节点改变的内容、差异化改变的类型及位置(在哪里增加、删除等)
前端MNV*
Model Native View *
JS调用原生控件或者事件绑定
前端开发规范
通用规范
- 三层结构分离:js css html 分离
- 缩进保持一致
- 内容编码:为html指定utf8编码
- 注意大小写的使用场景
- html属性名一律使用小写以-分割
- 属性值可以使用驼峰命名
- 代码单行长度限制
- 注释可以参考java
- 代码自描述
- 删除行尾空格及符号
HTML规范
- 文档类型定义统一使用HTML5的!DOCTYPE 避免使用HTML4的DTD定义
- head必须定义title keyword description等基本SEO字段 移动端注意定义viewport
- 引入style标签或者script标签可以省略type属性
- 标签属性值统一使用双引号
- 诸如readonly disabled等属性的属性值可以省略
- 元素标签必须正确嵌套 尽量使用语义化标签
- 非自闭和标签需要添加关闭标识 自闭和标签无需添加(img br)
- 避免img的alt属性为空
- label标签经历增加for属性与输入域进行关联
- 按模块添加注释 start end
- 标签元素格式:块级元素另起一行 行内元素根据情况内联或者换行
CSS规范
- 尽量使用外部样式文件,避免使用内联样式
- 命名:避免过于笼统,根据功能和内容进行命名,可以根据需要统一添加某种前缀
- 简写
- 值为0可以省略单位
- 0.x的单位可以省略0
- 颜色尽量缩写到3位
- 属性书写顺序:优先写布局元素,然后再写元素的内容属性
- 避免CSS奇淫技巧
- 若要兼容多种浏览器私有样式 则私有样式写前 标准样式写后
- 避免类名或ID与类选择器组合使用 会造成冗余
- 使用简短的CSS实现 合并写法
- 元素之间存在继承关系时 提取公共部分 避免重复定义
- 使用预处理来提高编码效率
ES5规范
- 语句添加分号结束可以使语句之间关系更清晰
- 在合适的地方添加空格
- 代码块后留空一行,使内容块更有层次
- 字符串最外层统一使用单引号
- 变量命名参考JAVA
- 对象属性名不需要引号
- 对象属性过多可以使用缩进的方式书写
- 代码块必须加花括号
- 不适用undefined直接进行判断 可以使用typeof
- 避免使用 != ==
- 禁止在条件语句或者循环语句里声明函数
- for-in循环访问属性前要判断 避免访问不存在的属性报错
- 避免在Array Date基础类库对象原型添加方法 否则会污染JS内置对象
ES6规范
- 正确使用变量声明let const
- 字符串拼接尽量使用模板字符串
- 解构赋值尽量只使用一层
- 数据拷贝使用...来高效简洁实现
- 数组循环遍历优先使用for...of
- 尽量使用ES6的class实现oop
- 模块化多变量导出尽量使用对象结构 不要讲import和export写在同一行
- 导出类时,保持模块名称和文件名相同
- 生成器yield使用时需要注意对异常的处理
- 使用Promise代替回调
- 尽量避免使用迭代器 性能太差
- 推荐使用async await
防御性编程规范
- 对于外部传入的数据 需要做校验 避免为空导致的模板报错
- 注意错误处理
前端组件规范
UI组件规范
- 统一的页面布局方案
- 基础UI结构和样式实现
- 组件化UI结构和样式实现
- 响应式布局
- UI可扩展性
模块化规范
- AMD 浏览器端的模块化异步加载规范
- CMD 用到模块才会执行
- CommonJS Node端使用的模块化规范
- import/export ES6定义的规范
项目组件化规范
- Web Component 组件化
- MVVM框架组件化 每个组件以单文件的形式引入模块 通过构建或者动态解析的方式注入到页面
- 虚拟DOM组件化 reactjs为代表的jsx
- 基于目录管理的通用组件化
组件化规范应该解决的问题:
- 组件之间独立 松耦合
- 组件可以嵌套使用
- 组件通信问题
- 组件公用部分设计
- 组件构建打包
- 异步组件加载
- 组件继承与复用
- 私有组件的管理
自动化构建
目的:对源项目文件或资源进行文件级处理 将文件或资源处理成最佳输出结构和形式
构建工具的设计
- 模块分析引入:通过分析依赖调用生成AST,生成依赖字典
- 模块化规范支持:目前较多的构建工具都是将ES6转换为ES5 构建工具应尽可能支持较多标准
- CSS编译 图片合并
- 资源压缩优化
- 路径分析替换
- 环境区分
- 异步文件打包
- 文件目录白名单
前端用户数据分析
用户访问统计
- PV
- UV
- IP配合其他手段
- VV:对用户访问网站多次跳转统计为一次VV
- IP
用户行为分析
- 页面点击量
- 页面某个区域点击量
- 用户点击流
- 在用户一次VV记录用户的点击行为
- 用户访问路径
- 用户点击热力图
- 用户转化率:访问用户与注册用户之比
- 导流转化率:原页面与导流页面之比
- 访问时长
前端日志上报
- 性能日志上报
- 错误日志上报
获取错误日志方式:
- try catch:无法捕获语法错误 无法捕捉不同作用域
- window.onerror:功能比try catch全 ,但无法处理跨域情况
错误信息上传:
- 如果访问量大 注意按一定条件上传
错误排查:
- 对错误归类 注意版本问题
前端跨栈技术
后端:node
- web框架:koa,express
- 后端数据渲染
- 前后端同构
- 基于模板:不同的请求渲染不同的模板
- 基于MVVM:在服务端对MVVM模板语法直接渲染
- 基于虚拟DOM
跨终端
- 前端为主:直接将前端页面打包进安装包 主要执行这些页面
- Native和Web结合:分别实现自己最擅长的
- 自己设计交互协议
- Web资源离线和更新
- serviceWorker
- localStorage
- 基于增量文件
- 基于文件代码块
- Native与Web资源离线和更新
- 根据时机向服务端主动拉取 否则使用本地缓存
- 资源覆盖率统计
- 日志上报
其他
- 前端代码编译为Native
- 桌面应用
趋势
- 标准技术趋向于稳定
- 工具仍会持续不断发展
- 浏览器平台新特性未来应用的可能
- 前端开发生态
- 效率
- 维护成本
- 性能
- 扩展性
- 前端新领域
- 物联网
- AI
- VR