最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 深入介绍从options到Vue组件的几种方式

    正文概述 掘金(flyingbird)   2021-05-17   578

    问题背景

    最近发现通过远程加载组件后,在组件初始化的过程中,浏览器控制台有报错:

    深入介绍从options到Vue组件的几种方式

    于是就跟着代码流程看看报错的原因。定位到报错处的代码:

    const originalVal = comp.props[key].default || '';
    

    其中comp是远程加载的Vue单文件组件经过编译之后的发布到CDN上的组件。我们知道一般Vue单文件组件经过vue-loader处理之后一般会变成具有这种数据结构的对象:

    深入介绍从options到Vue组件的几种方式

    整体结构和我们通常的写的组件options比较像似,这个对象作为Vue中比较常见的h函数处理后就能渲染出来了。然而,经过查看本次从远程环境中加载的对象,显示为:

    深入介绍从options到Vue组件的几种方式

    如果对Vue比较熟悉的话,可能一眼就能看出问题所在了。但是由于平时都比较关注Vue的响应式原理、各种接口API了,反倒对Vue整体上的了解有些欠缺了。

    深入介绍从options到Vue组件的几种方式

    Vue组件

    要详细理解上述的具体原因,需要从Vue组件进行深入理解。说起Vue组件化,通常都会想起Vue.component, 而对于Vue.extend的使用反而比较少。

    Vue.extend原理分析

    刚开始见到extend方法时,其实觉得比较奇怪的,后来仔细理解了下,觉得名字挺贴切的。

    这里可以参考Version2.0.0版本中,Vue对extend方法的实现。其实,整个extend的流程是比较清晰的(可以参考代码中给出的一点点注释)。

    主要是通过Object.create方法实现原型链继承(对于Object.create的用法可以参考之前的一篇文章:链接),返回的Sub是一个构造函数,通过new方式调用后,就会通过调用Vue原型链上的_init方法进行初始化,后续流程和new Vue(options)创建一个Vue实例基本上就一致了。

    Vue.extend = function (extendOptions) {
        extendOptions = extendOptions || {};
        var Super = this;
        var isFirstExtend = Super.cid === 0;
        if (isFirstExtend && extendOptions._Ctor) {
          return extendOptions._Ctor
        }
        var name = extendOptions.name || Super.options.name;
        // 1. 定义extend返回对象
        var Sub = function VueComponent (options) {
          this._init(options);
        };
        // 1.1 通过Object.create方法进行原型链继承
        Sub.prototype = Object.create(Super.prototype);
        Sub.prototype.constructor = Sub;
        Sub.cid = cid++;
        // 2. 设置构造函数上的options, 用来存储配置
        Sub.options = mergeOptions(
          Super.options,
          extendOptions
        );
        Sub['super'] = Super;
        Sub.extend = Super.extend;
        config._assetTypes.forEach(function (type) {
          Sub[type] = Super[type];
        });
        if (name) {
          Sub.options.components[name] = Sub;
        }
        Sub.superOptions = Super.options;
        Sub.extendOptions = extendOptions;
        if (isFirstExtend) {
          extendOptions._Ctor = Sub;
        }
        // 3. 返回新的构造函数
        return Sub
    };
    

    Vue.component原理分析

    在进行组件注册时,Vue.component是一个使用频率比较高的方法,一般大家对调用方法都比较熟悉了。简单介绍一下Vue 2.0.0版本的实现源码(删除了一些无关component函数里面的分支),便于与Vue.extend进行比较

    Vue[type] = function (
      id,
      definition
    ) {
      if (!definition) {
        // 直接获取组件
        return this.options[type + 's'][id]
      } else {
        if (type === 'component' && isPlainObject(definition)) {
          definition.name = definition.name || id;
          // 定义组件的构造函数
          definition = Vue.extend(definition);
        }
        this.options[type + 's'][id] = definition;
        return definition
      }
    };
    

    从Vue中的代码实现中可以获取以下几点信息:

    为什么更改成Vue.extend(options),测试组件渲染还是正常呢?

    这是因为Vue在使用h函数(createElement方法)时,对传入的参数进行了判断,然后进行分类处理,其实最终的结果还是转换成组件的构造函数。然而我们自己的代码逻辑中并未对构造函数这种形式的组件进行判断和处理,导致异常的发生。

    一般来说有两种解决方法:

    • 规范内部对组件的写法,统一成一种格式,这样开发同学在写代码时会比较清晰
    • 借鉴Vue的做法,对两种组件写法进行兼容处理

    总结

    Vue.extend方法创建一个组件的构造函数,通过new调用后可以获得组件的一个实例对象。

    stateDiagram-v2
    
    Options --> Vue
    Options --> Vue.extend
    Options --> Vue.component
    Vue.component-->Vue.extend
    Vue --> instance
    Vue.extend --> instance
    

    起源地下载网 » 深入介绍从options到Vue组件的几种方式

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元