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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM