源码角度分析 - Vue网络请求的时间点

源码角度分析 - Vue网络请求的时间点

React或Vue如今已经成为前端开发人员必点的技能。之前已经对React进行过分析,今天便要从源码的角度来分析Vue网络请求的时间点。

1、Vue是一个函数,没有constructor

Vue使用单文件组件的模式进行开发,vue-loaderscripttemplate的内容加载后通过vue-template-compiler编译成options供Vue.extend()调用,最终通过$mount方法挂载到DOM。

Vue.extend(options)生成的是一个Vue实例构造器,与Vue的区别是前者包含了传入的options。两者的实例化所做的操作是一样的,我们可以通过结构较为清晰的Vue来分析。
Vue 被定义在了src/core/instance/index.js中:

1
2
3
4
5
6
7
8
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}

Vue只是一个简单的函数,与React不同的是不能采用ES6 class的写法来表示一个组件。所以我们就不能在constructor中进行网络请求。而且函数只调用了_init方法,并没有给开发者进行手动初始化的机会。

2、new Vue 发生了什么?

我们深入_init方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
// ... 省略前部的数据校验、处理
vm._self = vm
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}

Vue源码的可阅读性是非常高的,将不同的逻辑封装成不同的函数,一目了然,犹如插件一般自如。
_init方法中可以明显的看到beforeCreatecreated两个生命周期函数被传入callHook,顾名思义就是调用options中对应的方法。在$mount函数中会依次调用beforeMountmounted
_init方法主要完成了初始化生命周期,初始化事件中心,初始化渲染,初始化 data、props、computed、watcher 等等。

3、beforeCreate/created/mounted

初始化请求一般有两种:

  • 想要造成页面渲染的响应类请求
  • 不关心response的单一请求

响应类请求

这类请求在接收到response后需要设置this.data来触发页面渲染,所以前提条件是要保证response callback执行的时候this.data存在,否则设置将无效。
_init中,第8行initState完成了data的初始化。所以请求必须要在其之后的created生命周期中发送。

单一请求

这类请求原则上不需要读/写组件的任何数据,可以放在最早执行的beforeCreate中发送。如果请求依赖于props,则需要将请求移动到created,因为这个时候props才有值。

服务端渲染

与React相同,Vue的SSR也不会进行组件的挂载操作,并不会执行beforeMount和mounted方法。所以如果网站考虑SSR的话,则需要尽量把请求放到mounted中,减少资源的浪费。

4、总结

场景 最早生命周期参考
响应类请求 created
单一请求 beforeCreate
单一请求(读取props) created
SSR mounted

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×