zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    bcrypt加密算法原理和应用
    spring security 防止iframes攻击
    angularjs在eclipse下不要随意ctrl+shift+f缩进代码
    第五章 容器之元组
    第五章 容器之列表
    第四章 函数
    第3章 编程概论
    mysql排序分组
    数据表的基本操作
    数据库基本操作
  • 原文地址:https://www.cnblogs.com/web-wjg/p/9248064.html
Copyright © 2011-2022 走看看