Vue.set

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

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

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虽然能用于删除数组,但位置还在,不能算真正的删除。

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

Vue.use

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

  1. Vue.use = function (plugin) {
  2. var installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
  3. if (installedPlugins.indexOf(plugin) > -1) {
  4. return this
  5. }
  6. // additional parameters
  7. var args = toArray(arguments, 1);
  8. args.unshift(this);
  9. if (typeof plugin.install === 'function') {
  10. plugin.install.apply(plugin, args);
  11. } else if (typeof plugin === 'function') {
  12. plugin.apply(null, args);
  13. }
  14. installedPlugins.push(plugin);
  15. return this
  16. };

安装的插件放到了 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] 开始截取)。

  1. Vue.use({
  2. a: 1,
  3. install: function (Vue) {
  4. console.log(this.a) //
  5. console.log(arguments) // [function Vue(options),"a", "b", "c"]
  6. }
  7. }, 'a', 'b', 'c')

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

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

Vue.extend

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

  1. strats.data = function (
  2. parentVal,
  3. childVal,
  4. vm
  5. ) {
  6. if (!vm) {
  7. if (childVal && typeof childVal !== 'function') {
  8. "development" !== 'production' && warn(
  9. 'The "data" option should be a function ' +
  10. 'that returns a per-instance value in component ' +
  11. 'definitions.',
  12. vm
  13. );
  14.  
  15. return parentVal
  16. }
  17. return mergeDataOrFn(parentVal, childVal)
  18. }
  19.  
  20. return mergeDataOrFn(parentVal, childVal, vm)
  21. };

传入非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的函数,源码结构如下:

  1. Vue.extend = function (extendOptions) {
  2. //***
  3. var Super = this;
  4. var SuperId = Super.cid;
  5. //***
  6. var Sub = function VueComponent(options) {
  7. this._init(options);
  8. };
  9. Sub.prototype = Object.create(Super.prototype);
  10. Sub.prototype.constructor = Sub;
  11. //***
  12. return Sub

vue采坑一:全局API的更多相关文章

  1. Vue源码探究-全局API

    Vue源码探究-全局API 本篇代码位于vue/src/core/global-api/ Vue暴露了一些全局API来强化功能开发,API的使用示例官网上都有说明,无需多言.这里主要来看一下全局API ...

  2. Vue基础二之全局API、实例属性和全局配置,以及组件进阶(mixins)的详细教程(案列实现,详细图解,附源码)

    本篇文章主要是写Vue.directive().Vue.use()等常用全局API的使用,vm.$props.vm.$options.vm.$slots等实例属性的使用,以及Vue全局配置.组件的mi ...

  3. VUE 采坑之旅-- Mint-ui 按需引入报出Module build failed: Error: Couldn't find preset "es2015" relative to directory "C:\\phpStudy\\PHPTutorial\\WWW\\text\\vuep\\vue-demo"

    首先按照mint-ui的文档中按需引入的要求,先执行 npm install babel-plugin-component -D 然后,将.babelrc文件替换了,但是后来我又将其改了(采坑过程我也 ...

  4. vue 采坑

    1.ref 在父组件中访问子组件实例,或者直接操作DOM元素时需要ref <input ref="ipt"> 通过this.$refs.ipt 得到此input $re ...

  5. vue采坑及较好的文章汇总

    1:父子组件传动态传值 https://www.cnblogs.com/daiwenru/p/6694530.html  -----互传数据基本流程 https://blog.csdn.net/qq_ ...

  6. vue采坑之——vue里面渲染html 并添加样式

    在工作中,有次遇到要把返回的字符串分割成两部分,一部分用另外的样式显示. 这时候,我想通过对得到字符串进行处理,在需要特别样式的字符串片段用html标签(用的span)包裹起来再通过变量绑定就好了.不 ...

  7. vue采坑记录

    1.项目在浏览器运行的时候没有ico图标 <link rel="shortcut icon" type="image/x-icon" href=" ...

  8. Vue基础(环境配置、内部指令、全局API、选项、内置组件)

    1.环境配置 安装VsCode 安装包管理工具:直接下载 NodeJS 进行安装即可,NodeJS自带 Npm 包管理工具,下载地址:https://nodejs.org/en/download/安装 ...

  9. vue文档全局api笔记1

    全局api方法 1.Vue.extend(options) 请注意,extend创建的是一个组件构造器,而不是一个具体的组件实例.所以他不能直接在new Vue中这样使用: new Vue({comp ...

随机推荐

  1. 创建虚拟机中的nova-scheduler 调度配置

    一个Openstack 系统中通常包括多个计算节点 root@controller:/etc/nova# nova hypervisor-list +----+-------------------- ...

  2. ANDROID窗体管理服务实现机制和架构分析

     一.功能 窗体管理是ANDROID框架一个重要部分,主要包含例如以下功能: )Z-ordered的维护 )窗体的创建.销毁 )窗体的绘制.布局 )Token管理,AppToken )活动窗体管理 ...

  3. Linux系统编程——特殊进程之僵尸进程

    僵尸进程(Zombie Process) 进程已执行结束,但进程的占用的资源未被回收.这种进程称为僵尸进程. 在每一个进程退出的时候,内核释放该进程全部的资源.包含打开的文件.占用的内存等. 可是仍然 ...

  4. luogu2149 [SDOI2009] Dlaxia的路线

    题目大意 在一个无向图中,定义两个点s,t的最短路径子图为一个极大边集,对于该边集内的所有有向边e,总存在一条起点为s,终点为t且经过边e的路径,使得该路径长度为s到t的最短路径长度.现给出一个无向图 ...

  5. js简单函数封装

    //每index个字符插入一个str字符串 String.prototype.insertStrPerIndex =function(index,str){ if(this.length>ind ...

  6. Get Length 使用dynamic关键字

    http://www.codewars.com/kata/566f571ed78037c7b6000036/train/csharp You don't have any idea what is t ...

  7. B3300 [USACO2011 Feb]Best Parenthesis 模拟

    这是我今天遇到最奇怪的问题,希望有人帮我解释一下... 一开始我能得90分: #include<iostream> #include<cstdio> #include<c ...

  8. 杂项-Java:EL表达式

    ylbtech-杂项-Java:EL表达式 EL(Expression Language) 是为了使JSP写起来更加简单.表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提 ...

  9. PCB 奥宝LDI 输出正负片转换关系

    今天继续对P2 奥宝LDI改造,在文件输出的时候遇到了一个正负片转换问题,研究了半天一直没有得到解决, 回来后前前后后整理今天参数输出与输出的关系,最终还梳理清楚了, 今天小结:一项技术只要用心去研究 ...

  10. 《疯狂Python讲义》重要笔记--变量

    一个Python解释器 接下来的旅程——你需要下载好Python,Python解释器通常放在 /usr/local/bin/python3.7 ; 在Unix系统的bash中输入 where pyth ...