vue采坑一:全局API

Posted web_study

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue采坑一:全局API相关的知识,希望对你有一定的参考价值。

Vue.set

Vue.set( target, key, value )target不能是 Vue 实例,或者 Vue 实例的根数据对象,因为源码中做了如下判断:

var ob = (target).__ob__;
if (target._isVue || (ob && ob.vmCount)) {
"development" !== \'production\' && warn(
    \'Avoid adding reactive properties to a Vue instance or its root $data \' +
    \'at runtime - declare it upfront in the data option.\'
);
return val
}

target._isVue阻止了给Vue实例添加属性,ob && ob.vmCount阻止了给Vue实例的根数据对象添加属性。

Vue.delete

如果Vue能检测到delete操作,那么就不会出现这个api。如果一定要用delete来删除$data的属性,那就用Vue.delete,否则不会触发dom的更新。

同Vue.set,Vue.delete( target, key )的target不能是一个 Vue 示例或 Vue 示例的根数据对象。源码中的阻止方式和Vue.set相同。

在2.2.0+ 版本中target若为数组,key则是数组下标。因为Vue.delete删除数组实际是用splice来删除,delete虽然能用于删除数组,但位置还在,不能算真正的删除。

var a = [1, 2, 3];
delete a[0];
console.log(a); // [undefined, 2, 3]

Vue.use

Vue.use 源码比较简单,可以全部贴出来。

Vue.use = function (plugin) {
    var installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
    if (installedPlugins.indexOf(plugin) > -1) {
        return this
    }
    // additional parameters
    var args = toArray(arguments, 1);
    args.unshift(this);
    if (typeof plugin.install === \'function\') {
        plugin.install.apply(plugin, args);
    } else if (typeof plugin === \'function\') {
        plugin.apply(null, args);
    }
    installedPlugins.push(plugin);
    return this
};

安装的插件放到了 installedPlugins ,安装插件前通过installedPlugins.indexOf(plugin)来判断插件是否被安装过,进而阻止注册相同插件多次。

插件类型为 object,必须指定 install 属性来安装插件typeof plugin.install === \'function\'),另外插件执行采用plugin.install.apply(plugin, args);,因此 this 访问 object 的其他属性。此处的 args 是由 Vue(args.unshift(this);) 和 Vue.use 传入的除了 plugin 的其他参数(toArray(arguments, 1),1 表示从 arguments[1] 开始截取)。

Vue.use({
    a: 1,
    install: function (Vue) {
        console.log(this.a) // 1
        console.log(arguments) // [function Vue(options),"a", "b", "c"]
    }
}, \'a\', \'b\', \'c\')

插件类型为 function,安装调用plugin.apply(null, args);,因此在严格模式下插件运行时上下文 this 为 null,非严格模式为 Window。

\'use strict\'
Vue.use(function plugin() {
    console.log(this) // null
    console.log(arguments) // [function Vue(options),"a", "b", "c"]
}, \'a\', \'b\', \'c\')

Vue.extend

配置项data必须为function,否则配置无效。data的合并规则源码如下:

strats.data = function (
  parentVal,
  childVal,
  vm
) {
  if (!vm) {
    if (childVal && typeof childVal !== \'function\') {
      "development" !== \'production\' && warn(
        \'The "data" option should be a function \' +
        \'that returns a per-instance value in component \' +
        \'definitions.\',
        vm
      );

      return parentVal
    }
    return mergeDataOrFn(parentVal, childVal)
  }

  return mergeDataOrFn(parentVal, childVal, vm)
};

传入非function类型的data(上图中data配置为{a:1}),在合并options时,如果data不是function类型,开发版会发出警告,然后直接返回了parentVal,这意味着extend传入的data选项被无视了。

我们知道实例化Vue的时候,data可以是对象,这里的合并规则不是通用的吗?注意上面有个if(!vm)的判断,实例化的时候vm是有值的,因此不同于Vue.extend,其实下面的注释也做了说明(in a Vue.extend merge, both should be function),这也是官方文档为何说data是个特例。

另外官方文档所说的“子类”,是因为Vue.extend返回的是一个“继承”Vue的函数,源码结构如下:

Vue.extend = function (extendOptions) {
    //***
    var Super = this;
    var SuperId = Super.cid;
    //***
    var Sub = function VueComponent(options) {
        this._init(options);
    };
    Sub.prototype = Object.create(Super.prototype);
    Sub.prototype.constructor = Sub;
    //***
    return Sub

 

 

以上是关于vue采坑一:全局API的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段11——vue路由的配置

VSCode自定义代码片段11——vue路由的配置

VSCode自定义代码片段11——vue路由的配置

VSCode自定义代码片段2——.vue文件的模板

VSCode自定义代码片段13——Vue的状态大管家