Vue 动态组件 & 异步组件原理

栏目: JavaScript · 发布时间: 5年前

内容简介:动态组件 & 异步组件的存在,使得我们更方便地控制首屏代码的体积,加快加载速度。抛开具体细节不谈,一个普通 Vue 组件从创建到展现在页面里,主要经历了以下流程:动态组件&异步组件与之有什么区别呢?

动态组件 & 异步组件的存在,使得我们更方便地控制首屏代码的体积,加快加载速度。

抛开具体细节不谈,一个普通 Vue 组件从创建到展现在页面里,主要经历了以下流程:

// 组件 Object
{
    template: '<div>I am async!</div>'
}
// 经过 compileToFunctions 得到对应的 render function 
with(this) {
    return _c('div', [_v("I am async!")])
}
// 在经过 render 得到 Vnode 再 update 成为真实DOM
复制代码

动态组件&异步组件与之有什么区别呢?

主要区别在于 rendercreateComponent 这一步,举例。

// 组件
Vue.component('example', {
    template: '<div>I am async!</div>'
})
复制代码

普通组件在 createComponent 时,会依据开发者自定义的 options ,利用 Vue.extend 生成对应的构造函数,从而得到对应的 Vnode 。而一个异步组件

// 异步组件
Vue.component('async-example', function (resolve, reject) {
    // 利用 setTimeout 模拟请求
    setTimeout(function () {
        // 向 `resolve` 回调传递组件定义
        resolve({
            template: '<div>I am async!</div>'
        })
    }, 1000)
})
复制代码

则是要经过一系列处理,具体过程如下

在源码的 create-component

// async component
let asyncFactory
if (isUndef(Ctor.cid)) {
    asyncFactory = Ctor
    Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context)
    if (Ctor === undefined) {
        // return a placeholder node for async component, which is rendered
        // as a comment node but preserves all the raw information for the node.
        // the information will be used for async server-rendering and hydration.
        return createAsyncPlaceholder(
            asyncFactory,
            data,
            context,
            children,
            tag
        )
    }
}
复制代码

首先 Ctor 就与之前不同,这里为一个 function

function (resolve, reject) {
    // 利用 setTimeout 模拟请求
    setTimeout(function () {
        // 向 `resolve` 回调传递组件定义
        resolve({
            template: '<div>I am async!</div>'
        })
    }, 1000)
}
复制代码

之后调用 resolveAsyncComponent(asyncFactory, baseCtor, context)

resolveAsyncComponent在源码的 resolveAsyncComponent

resolveAsyncComponent 的主要功能是定义 Ctor 所需要的 resolvereject 函数

// factory 为 Ctor
factory(resolve, reject)
复制代码

resolve 函数为例

const resolve = once((res: Object | Class<Component>) => {
    // 缓存 resolved
    factory.resolved = ensureCtor(res, baseCtor)
    // 强制渲染
    if (!sync) {
    	forceRender(true)
    }
})
复制代码

once 字面理解,就是只调用一次。当 CtorsetTimeout 结束时调用。

ensureCtor 就是 Vue.extend 的封装以适应不同场景,所以 resolve 函数的主要功能就是在异步完成时,将得到的 Ctor 转化为构造函数,缓存在 factory.resolved 中。

之后利用 forceRender(true) 强制重新 render,由于之前缓存了 factory.resolvedresolveAsyncComponent 函数就直接返回了组件的构造函数。

if (isDef(factory.resolved)) {
    return factory.resolved
}
复制代码

之后就与普通组件一致了。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Math Adventures with Python

Math Adventures with Python

Peter Farrell / No Starch Press / 2018-11-13 / GBP 24.99

Learn math by getting creative with code! Use the Python programming language to transform learning high school-level math topics like algebra, geometry, trigonometry, and calculus! In Math Adventu......一起来看看 《Math Adventures with Python》 这本书的介绍吧!

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具