第三趴:vue框架进阶

整理中高级前端系列,能够看成面试复习,也能够看成实战来看,分享一下 方便本身,方便他人。有不足的地方欢迎评论~css

第一趴:css进阶前端

第二趴:js进阶vue

第三趴:vue框架进阶node

第四趴:工程化react

MVC架构 (model、controller、view)

  • View: 检测用户输入、操做(键盘、鼠标)行为,传递调用Controller执行对应逻辑。View更新须要从新获取 Model的数据。
  • Controller:是View和Model 之间协做的应用层,负责业务逻辑处理。
  • Model:数据层,数据变化后 经过观察者模式通知 View更新视图。

优势:面试

  • 模块化:低耦合、可替换、可扩展性、可复用性强
  • 多视图更新:使用观察者模式能够作到 单方Model通知多视图 实现数据更新

缺点:算法

  • 依赖强:View和 Model 强依赖,很难抽离成 组件化

MVVM框架核心原理

图上能够看到,view经过viewmodel 的DOM Listeners 将事件绑定到 Model上,而Model则经过 Data Bindings来管理View中的数据,View-Model从中起到一个链接桥的做用。

更详细的查看 vuex

双向数据绑定(响应式)原理

vue.js 是采用数据劫持结合发布者-订阅者模式的方式,经过Object.defineProperty()来劫持各个属性的setter,getter,在数据变更时发布消息给订阅者,触发相应的监听回调。segmentfault

Vue实现这种数据双向绑定的效果,须要三大模块:数组

  • Observer:可以对数据对象的全部属性进行监听,若有变更可拿到最新值并通知订阅者
  • Compile:对每一个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
  • Watcher:做为链接Observer和Compile的桥梁,可以订阅并收到每一个属性变更的通知,执行指令绑定的相应回调函数,从而更新视图

Vue全家桶

组件深刻( 组件通讯、生命周期 )

  • 使用 kebab-case my-component-name 或者 MyComponentName

组件通讯:

  1. 父子之间:props ----- $emit
  2. this.parent.event 调用父组件的方法、this.refs.xxx.属性/方法:父组件里直接获取子组件 方法和属性
  3. eventBus模式:新建Vue事件bus对象,而后经过 bus.emit 触发事件,bus.on监听触发事件。

脚手架的 使用

Vue Loader

这个插件是必须的! 将你定义过的其余规则赋址并应用到 .vue文件里相应语言的块。例如:你有一条匹配/\.js$/ 的规则,那么它会应用到 .vue文件里的 <script>

路由 原理

HashHistory:利用URL中的 hash("#")

  • hash是用来指导浏览器动做的,对服务器端彻底无用,所以 改变hash不会从新加载页面。
  • 能够为 hash 的改变添加监听事件:

window.addEventListener("hashchange", funcRef, false)

  • 每次改变hash(window.location.hash)都会在浏览器的访问历史中增长一个记录

利用这几点特性,就能够实现前端路由 【更新视图但不从新请求页面】的功能了

HashHistory.push()

从设置路由改变到视图更新的流程以下: $router.push() --> HashHistory.push() --> History.transitionTo() --> History.updateRoute() --> {app._route = route} --> vm.render()

HashHistory.replace()

其实和push()相似,不一样就是 替换掉当前路由,调用的是window.location.replace方法。

HTML5History:

利用HTML5中新增的方法pushState\replaceState

  • pushState() 、replaceState()使得咱们能够对浏览器历史记录栈进行修改
window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)
复制代码

实现原理:代码结构以及更新视图的逻辑与hash模式基本相似,只不过将对window.location.hash直接进行赋值window.location.replace(),改成了调用history.pushState()和history.replaceState()方法。

非浏览器环境准备了一个abstract模式 (没使用过 可百度)

vuex 原理

state: 存储数据(至关于 data)

咱们设置在state中的属性会被存储在根元素中, this._modules = new ModuleCollection(options) //初始化

const state = this._modules.root.state // 获取定义的state

vuex初始化时先去获取定义在state属性的值 new ModuleCollection(options) 进行模块收集(从新组装 store中的相关属性),最终造成一颗module树。

getter:获取store属性方法 (至关于 computed)

mutations: 更改store中状态的惟一方法就是 提交 mutation,相似于调用事件(methods)

视图经过点击事件,触发 mutattions中的方法,能够更改state中的数据,此时 getters把数据反映到视图。

action: 提交 mutation 去变动状态

那么action 能够理解是 为了处理异步,单纯多加的一层。

dispatch、commit

在vue中 咱们触发 click事件,就能触发 methods中的方法。可是 vuex就不行,必定要有个东西来触发才行,就至关于自定义事件on\emit。

关系就是,经过dispatch来触发actions中得方法,action中commi去触发mutions中方法。

Proxy与Object.defineProperty的优劣对比?

Proxy的优点:

  • 能够直接监听对象而非属性
  • 能够直接监听数组的变化
  • Proxy返回的是一个新对象,咱们能够只操做新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改
  • 做为新标准会收到浏览器厂商重点持续的性能优化。

Object.defineProperty的优点以下:

虚拟dom原理

Virtual DOM是对DOM的抽象,本质上是JavaScript对象,这个对象就是更加轻量级的对DOM的描述.

出发点

Virtual DOM最初的目的,就是更好的跨平台,好比Node.js就没有DOM,若是想实现SSR(服务端渲染),那么一个方式就是借助Virtual DOM,由于Virtual DOM自己是JavaScript对象.

主流

现代前端框架的一个基本要求就是无须手动操做DOM, 一方面是由于手动操做DOM没法保证程序性能,多人协做的项目中若是review不严格,可能会有开发者写出性能较低的代码, 另外一方面更重要的是省略手动DOM操做能够大大提升开发效率.

实现流程

一、须要一个**函数建立单个Virtual DOM **,这个函数很简单,接受必定的参数,再根据这些参数返回一个对象,这个对象就是DOM的抽象.

/**
 * 生成 vnode
 * @param  {String} type     类型,如 'div'
 * @param  {String} key      key vnode的惟一id
 * @param  {Object} data     data,包括属性,事件等等
 * @param  {Array} children  子 vnode
 * @param  {String} text     文本
 * @param  {Element} elm     对应的 dom
 * @return {Object}          vnode
 */
function vnode(type, key, data, children, text, elm) {
  const element = {
    __type: VNODE_TYPE,
    type, key, data, children, text, elm
  }
  return element
}
复制代码

二、DOM实际上是一个Tree,咱们接下来要作的就是声明一个函数用于建立DOM Tree的抽象 -- Virtual DOM Tree.

三、Virtual DOM 归根究竟是JavaScript对象,咱们得想办法将Virtual DOM与真实的DOM对应起来,也就是说,须要咱们声明一个函数,此函数能够将vnode转化为真实DOM.

四、Virtual DOM 的 diff才是整个Virtual DOM 中最难理解也最核心的部分,diff的目的就是比较新旧Virtual DOM Tree找出差别并更新.

Virtual DOM的优化

snabbdom.js已是社区内主流的Virtual DOM实现了**,vue 2.0阶段与snabbdom.js同样**都采用了上面讲解的 「双端比较算法」,那么有没有一些优化方案可使其更快?

其实,社区内有更快的算法,例如inferno.js就号称最快react-like框架(虽然inferno.js性能强悍的缘由不只仅是算法,可是其diff算法的确是目前最快的),而vue 3.0就会借鉴inferno.js的算法进行优化.

Vue中的key到底有什么用?

diff算法的过程当中,先会进行新旧节点的首尾交叉对比,当没法匹配的时候会用新节点的key与旧节点进行比对,而后超出差别.

快速: key的惟一性能够被Map数据结构充分利用,相比于遍历查找的时间复杂度O(n),Map的时间复杂度仅仅为O(1).

$nextTick的原理

将回调延迟到下次DOM更新循环以后执行。在修改数据以后当即使用它,而后等待DOM更新。

<template>
	<div id="example">{{message}}</div>
</template>
<script>
    var vm = new Vue({
      el: '##example',
      data: {
        message: '123'
      }
    })
    vm.message = 'new message' // 更改数据
    console.log(vm.$el.innerHTML) // '123'
    Vue.nextTick(function () {
      console.log(vm.$el.innerHTML) // 'new message'
    })
</script>
复制代码

在上面这个例子中,当咱们经过vm.message = 'new message'更新数据时,此时该组件不会当即从新渲染。当刷新事件队列时,组件会在下一个事件循环“tick”中从新渲染。因此当咱们更新完数据后,此时又想基于更新后的DOM状态来作点什么,此时咱们就须要使用Vue.nextTick(callback),把基于更新后的DOM状态所须要的操做放入回调函数callback中,这样回调函数将在DOM更新完成后被调用。

数据为何频繁变化但只会更新一次

vue异步执行DOM更新

首屏加载性能优化

此点其实在说的是 白屏问题,白屏时间就是 当用户地址栏按下确认键开始到首次内容绘制(即看到第一个内容)。 因此 解决 白屏问题 才是关键 优化点。 ** 咱们先梳理下白屏时间内发生了什么:

  1. 回车按下,浏览器解析网址,进行 DNS 查询,查询返回 IP,经过 IP 发出 HTTP(S) 请求
  2. 服务器返回HTML,浏览器开始解析 HTML,此时触发请求 js 和 css 资源
  3. js 被加载,开始执行 js,调用各类函数建立 DOM 并渲染到根节点,直到第一个可见元素产生

开启 HTTP2

  1. http2 的通讯效率更高
  2. 能够进行多路复用
  3. http2 能够头部压缩,可以节省消息头占用的网络的流量

使用骨架屏

第一趴:css进阶

第二趴:js进阶

第三趴:vue框架进阶

第四趴:工程化

同窗以为有帮助的能够点个赞哈,以示鼓励 😊

相关文章
相关标签/搜索