Maison  >  Article  >  interface Web  >  Compréhension approfondie de l'API globale Vue

Compréhension approfondie de l'API globale Vue

小云云
小云云original
2017-12-18 13:50:342363parcourir

Est-ce que tout le monde connaît l'API ? Cet article présente principalement une compréhension approfondie de l'API globale de la documentation officielle de Vue. L'éditeur pense qu'elle est plutôt bonne, je vais donc la partager avec vous maintenant et la donner comme référence. Suivons l'éditeur pour y jeter un œil, j'espère que cela pourra aider tout le monde.

Vue.extend

Les données de l'élément de configuration doivent fonctionner, sinon la configuration n'est pas valide. Le code source des règles de fusion de données (vous pouvez consulter "Vue Official Documentation - Global Configuration") est le suivant :

Transmettre les données de type non-fonction (le données dans l'image ci-dessus configurée comme {a:1}), lors de la fusion d'options, si les données ne sont pas de type fonction, la version de développement émettra un avertissement puis renverra directement parentVal, ce qui signifie que l'option de données transmise par extend est ignoré.

Nous savons que lors de l'instanciation de Vue, les données peuvent être un objet. Les règles de fusion ici ne sont-elles pas universelles ? Notez qu'il existe un jugement if(!vm) ci-dessus. vm a une valeur lorsqu'il est instancié, il est donc différent de Vue.extend. En fait, les commentaires suivants l'expliquent également (dans une fusion Vue.extend, les deux devraient fonctionner. ), c'est pourquoi la documentation officielle indique que les données constituent un cas particulier.

De plus, la "sous-classe" mentionnée dans le document officiel est due au fait que Vue.extend renvoie une fonction qui "hérite" de Vue. La structure du code source est la suivante :

<.>


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.nextTick

Puisque vous utilisez vue, vous devez bien sûr penser de manière basée sur les données. appelé basé sur les données signifie ne pas faire fonctionner directement le dom, toutes les opérations du dom peuvent être effectuées en utilisant diverses instructions de vue. Les instructions "lient" les données au dom peuvent non seulement mettre à jour le dom, mais aussi être plus pratiques.


Si le navigateur prend en charge Promise, ou utilise la bibliothèque Promise (mais celle exposée à l'extérieur doit s'appeler Promise, car le jugement dans le code source est de type Promise !== 'undefined') , nextTick renvoie l'objet Promise.



Vue.nextTick().then(() => {
  // do sth
})
Le rappel permettant à Vue d'exécuter nextTick utilise la méthode d'appel cb.call(ctx) est l'instance actuelle de Vue, elle peut donc être utilisé directement dans le callback. Celui-ci appelle la configuration de l'instance.

nextTick peut être simplement compris comme plaçant le rappel à la fin pour l'exécution. Si Promise et MutationObserver ne sont pas actuellement pris en charge dans le code source, la méthode setTimeout sera utilisée pour exécuter le rappel. retarder l'exécution du code.


 if (typeof Promise !== &#39;undefined&#39; && isNative(Promise)) {
 } else if (typeof MutationObserver !== &#39;undefined&#39; && (
     isNative(MutationObserver) ||
     // PhantomJS and iOS 7.x
     MutationObserver.toString() === &#39;[object MutationObserverConstructor]&#39;
   )) {
 } else {
   // fallback to setTimeout
   /* istanbul ignore next */
   timerFunc = function () {
     setTimeout(nextTickHandler, 0);
   };
 }
Prenons un exemple :



<p id="app">
  <p ref="dom">{{a}}</p>
</p>
new Vue({
  el: &#39;#app&#39;,
  data: {
    a: 1
  },
  mounted: function name(params) {
    console.log(&#39;start&#39;);
    this.$nextTick(function () {
      console.log(&#39;beforeChange&#39;, this.$refs.dom.textContent)
    })
    this.a = 2;
    console.log(&#39;change&#39;);
    this.$nextTick(function () {
      console.log(&#39;afterChange&#39;, this.$refs.dom.textContent)
    })
    console.log(&#39;end&#39;);
  }
})
// 控制台依次打印
// start
// change
// end
// beforeChange 1
// afterChange 2
Vous pourriez être un peu confus. Puisqu'il est exécuté en dernier, pourquoi beforeChange génère-t-il 1 au lieu de 2 ? C'est parce que la mise à jour dom déclenchée derrière this.a=2 utilise également nextTick. L'ordre d'exécution réel du code ci-dessus est :beforeChange>Update dom>. ;aprèsChangement.

Vue.set

Vue.set( target, key, value ), la cible ne peut pas être une instance de Vue, ni l'objet de données racine d'une instance de Vue, car cela est fait dans le code source Le jugement suivant est rendu :



var ob = (target).__ob__;
if (target._isVue || (ob && ob.vmCount)) {
"development" !== &#39;production&#39; && warn(
  &#39;Avoid adding reactive properties to a Vue instance or its root $data &#39; +
  &#39;at runtime - declare it upfront in the data option.&#39;
);
return val
}
target._isVue empêche l'ajout d'attributs à l'instance Vue, ob && ob. vmCount empêche l'ajout de l'objet de données racine des propriétés Ajouter de l'instance Vue.


Vue.delete

Si Vue peut détecter l'opération de suppression, alors cette API n'apparaîtra pas. Si vous devez utiliser delete pour supprimer l'attribut $data, utilisez Vue.delete, sinon la mise à jour dom ne sera pas déclenchée.


Comme Vue.set, la cible de Vue.delete(target, key) ne peut pas être une instance Vue ou l'objet de données racine d'une instance Vue. La méthode de blocage dans le code source est la même que celle de Vue.set.


Dans la version 2.2.0+, si la cible est un tableau, la clé est l'indice du tableau. Étant donné que Vue.delete utilise en fait splice pour supprimer un tableau, bien que delete puisse être utilisé pour supprimer un tableau, la position est toujours là et ne peut pas être considérée comme une véritable suppression.



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

Vue.use

Vue.use Le code source est relativement simple et peut être publié dans complet.



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 === &#39;function&#39;) {
    plugin.install.apply(plugin, args);
  } else if (typeof plugin === &#39;function&#39;) {
    plugin.apply(null, args);
  }
  installedPlugins.push(plugin);
  return this
};
Les plug-ins installés sont placés dans InstallPlugins Avant d'installer le plug-in, utilisez InstallPlugins.indexOf(plugin) pour déterminer si le plug est installé. -in a été installé, empêchant ainsi le même plugin d'enregistrement plusieurs fois.


Le type du plug-in est objet, et l'attribut install doit être spécifié pour installer le plug-in (typeof plugin.install === 'function') De plus, exécution du plug-in). utilise plugin.install.apply(plugin, args);, donc cela accède à d'autres propriétés de l'objet. Les arguments ici sont les paramètres autres que le plugin transmis par Vue (args.unshift(this);) et Vue.use (toArray(arguments, 1), 1 signifie intercepter à partir des arguments[1]).



Vue.use({
  a: 1,
  install: function (Vue) {
    console.log(this.a) // 1
    console.log(arguments) // [function Vue(options),"a", "b", "c"]
  }
}, &#39;a&#39;, &#39;b&#39;, &#39;c&#39;)
Le type de plug-in est fonction, et l'installation appelle plugin.apply(null, args);, donc en mode strict le plug- dans le contexte d'exécution, il s'agit de null , le mode non strict est Window.



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

Vue.compile

和众多 JS 模板引擎的原理一样,预先会把模板转化成一个 render 函数,Vue.compile 就是来完成这个工作的,目标是将模板(template 或 el)转化成 render 函数。
Vue.compile 返回了{render:Function,staticRenderFns:Array},render 可直接应用于 Vue 的配置项 render,而 staticRenderFns 是怎么来的,而且按照官网的例子,Vue 还有个隐藏的配置项 staticRenderFns,先来个例子看看。


var compiled = Vue.compile(
  &#39;<p>&#39; +
  &#39;<header><h1>no data binding</h1></header>&#39; +
  &#39;<section>{{prop}}</section>&#39; +
  &#39;</p>&#39;
)
console.log(compiled.render.toString())
console.log(compiled.staticRenderFns.toString())
// render
function anonymous() {
  with(this) {
    return _c(&#39;p&#39;, [_m(0), _c(&#39;section&#39;, [_v(_s(prop))])])
  }
}
// staticRenderFns
function anonymous() {
  with(this) {
    return _c(&#39;header&#39;, [_c(&#39;h1&#39;, [_v("no data binding")])])
  }
}

原来没有和数据绑定的 dom 会放到 staticRenderFns 中,然后在 render 中以_m(0)来调用。但是并不尽然,比如上述模板去掉4a249f0d628e2318394fd9b75b4636b1,staticRenderFns 长度为 0,header 直接放到了 render 函数中。


function anonymous() {
  with(this) {
    return _c(&#39;p&#39;, [_c(&#39;header&#39;, [_v("no data binding")]), _c(&#39;section&#39;, [_v(_s(prop))])])
  }
}

Vue.compile 对应的源码比较复杂,上述渲染 1aa9e5d373740b65a0cc8f0a02150c53 没有放到 staticRenderFns 对应源码的核心判断如下:


 // For a node to qualify as a static root, it should have children that
 // are not just static text. Otherwise the cost of hoisting out will
 // outweigh the benefits and it&#39;s better off to just always render it fresh.
 if (node.static && node.children.length && !(
     node.children.length === 1 &&
     node.children[0].type === 3
   )) {
   node.staticRoot = true;
   return
 } else {
   node.staticRoot = false;
 }

1aa9e5d373740b65a0cc8f0a02150c53 不符判断条件 !(node.children.length === 1 && node.children[0].type === 3), 1aa9e5d373740b65a0cc8f0a02150c53 有一个子节点 TextNode(nodeType=3)。 注释也说明了一个 node 符合静态根节点的条件。

另外官网说明了此方法只在独立构建时有效,什么是独立构建?这个官网做了详细的介绍,不再赘述。对应官网地址:对不同构建版本的解释。

仔细观察编译后的 render 方法,和我们自己写的 render 方法有很大区别。但是仍然可以直接配置到 render 配置选项上。那么里面的那些 _c()、_m() 、_v()、_s() 能调用?随便看一个 Vue 的实例的 __proto__ 就会发现:


// internal render helpers.
// these are exposed on the instance prototype to reduce generated render
// code size.
Vue.prototype._o = markOnce;
Vue.prototype._n = toNumber;
Vue.prototype._s = toString;
Vue.prototype._l = renderList;
Vue.prototype._t = renderSlot;
Vue.prototype._q = looseEqual;
Vue.prototype._i = looseIndexOf;
Vue.prototype._m = renderStatic;
Vue.prototype._f = resolveFilter;
Vue.prototype._k = checkKeyCodes;
Vue.prototype._b = bindObjectProps;
Vue.prototype._v = createTextVNode;
Vue.prototype._e = createEmptyVNode;
Vue.prototype._u = resolveScopedSlots;
Vue.prototype._g = bindObjectListeners;

正如注释所说,这些方法是为了减少生成的 render 函数的体积。

全局 API 还剩 directive、filter、component、mixin,这几个比较类似,而且都对应着配置项,会在「选项」中再详细介绍。

相关推荐:

Vue官方文档梳理的全局配置详解

Vue拦截器vue-resource 拦截器使用详解

vue项目的构建,打包,发布详解

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn