Maison  >  Article  >  interface Web  >  Comment Babel convertit-il la syntaxe de la classe Es6

Comment Babel convertit-il la syntaxe de la classe Es6

php中世界最好的语言
php中世界最好的语言original
2018-04-08 11:34:412221parcourir

Cette fois, je vais vous montrer comment Babel convertit la syntaxe de classe d'es6. Quelles sont les choses à noter lors de la conversion de Babel en syntaxe de classe d'es6 Ce qui suit est un cas pratique, jetons un coup d'oeil.

Babel est un transcodeur actuellement utilisé lors du développement de projets React et Vue. Il peut convertir la syntaxe es6+ en es5, ainsi que JSX et autres syntaxes.

Dans nos projets, nous convertissons tous des codes spécifiques, tels que env, stage-0, etc., en configurant des plug-ins et des préréglages (une collection de plusieurs plug-ins).

En fait, Babel peut convertir n'importe quel code via des plug-ins personnalisés. Ensuite, découvrons Babel à travers un exemple de « conversion d'es6

en es5 ». class

Le contenu est le suivant :

Configuration de l'environnement webpack

Tout le monde devrait avoir configuré le chargeur babel-core et son rôle Il fournit l'API de base de babel. En fait, notre conversion de code est implémentée via des plug-ins.

Ensuite, nous implémenterons nous-mêmes un plug-in de conversion de classe es6 sans utiliser de plug-ins tiers. Effectuez d'abord les étapes suivantes pour initialiser un projet :

  1. npm install webpack webpack-cli babel-core -D

  2. Créez un nouveau webpack. config.js

  3. Configurer webpack.config.js

Si le nom de notre plug-in veut être appelé transform-class, nous devons le faire. faites la configuration suivante dans la configuration du webpack :

Ensuite, nous créons un nouveau dossier de babel-plugin-transform-class dans node_modules pour écrire la logique du plug-in ( s'il s'agit d'un vrai projet, vous devez écrire ce plug-in et le publier dans l'entrepôt npm), comme indiqué ci-dessous :

La zone rouge est mon dossier nouvellement créé , et au-dessus se trouve une structure de projet de plug-in standard. Pour plus de commodité, je viens d'écrire le fichier principal index.js.

Comment écrire un plug-in Babel

Le plug-in Babel est en fait implémenté via AST (Abstract Syntax Tree).

babel nous aide à convertir le code js en AST, puis nous permet de le modifier, et enfin de le convertir en code js.

Il y a donc deux questions en jeu : quelle est la relation de mappage entre le code js et AST ? Comment remplacer ou

ajouterAST ?

Bien, introduisons d'abord un outil : astexplorer.net :

Cet outil peut convertir un morceau de code en AST :

Comme le montre la figure , nous avons écrit une classe es6, puis le côté droit de la page Web a généré un AST pour nous, qui a en fait transformé chaque ligne de code en un

objet , de sorte que nous avons implémenté un mappage.

Présentation d'un autre document : babel-types :

Ceci est le document API pour créer des nœuds AST.

Par exemple, si nous voulons créer une classe, nous la convertissons d'abord dans astexplorer.net et constatons que le type AST correspondant à la classe est

. D'accord, cherchons dans la documentation et constatons qu'il suffit d'appeler l'API suivante : ClassDeclaration

Il en va de même pour la création d'autres instructions. Avec les deux choses ci-dessus, nous ne pouvons pas. des conversions ont été effectuées.

Maintenant, nous commençons à écrire un plug-in, qui est divisé en les étapes suivantes :

  1. Exporter une fonction dans index.js

  2. La fonction renvoie un objet, et l'objet a un paramètre visiteur (doit être appelé visiteur)

  3. Requête

    via astexplorer.net Le nœud AST correspondant est classClassDeclaration

  4. Définir une fonction de capture

    dans vistor, ce qui signifie que je veux capturer tous les ClassDeclaration nœuds dans le code js ClassDeclaration

  5. Écrivez le code logique pour terminer la conversion

module.exports = function ({ types: t }) {
 return {
  visitor: {
   ClassDeclaration(path) {
    //在这里完成转换
   }
  }
 };
}

Il y a deux paramètres dans le code La première {types:t} chose est de déconstruire la variable t à partir des paramètres, qui est en fait celle de babel. -types le document t (encadré rouge dans l'image ci-dessous), qui sert à créer des nœuds :

Le deuxième paramètre path, qui est l'information correspondant au capturé nœud, nous pouvons obtenir l'AST de ce nœud via path.node, et le modifier sur cette base pour atteindre notre objectif.

Comment convertir des classes es6 en classes es5

Ce qui précède sont tous des travaux préparatoires, la vraie logique commence à partir de maintenant, considérons d'abord deux questions :

Nous devons effectuer la conversion suivante. Tout d'abord, convertir les classes es6 en écriture de classe es5 (c'est-à-dire des fonctions ordinaires). Nous avons observé que beaucoup de code peut être réutilisé, y compris les noms. blocs de code à l'intérieur des fonctions, etc.

Si la méthode constructor de la classe n'est pas définie, le moteur JavaScript y ajoutera automatiquement une méthode constructor() vide, ce qui nécessite Nous effectuons un traitement de compatibilité.

Ensuite, nous commençons à écrire du code. L'idée est :

  1. Récupérez l'ancien nœud AST

  2. Créez un tableau avec To. conserver le nouveau nœud AST (bien que la classe d'origine ne soit qu'un seul nœud, elle sera remplacée par plusieurs nœuds de fonction après remplacement) Initialiser le nœud constructor par défaut (comme mentionné ci-dessus, le constructeur peut ne pas être défini dans la classe)

  3. Bouclez l'objet AST de l'ancien nœud (plusieurs nœuds de fonction seront bouclés)

  4. Déterminez si le type de la fonction est constructor , si tel est le cas, créez un nœud de fonction normal en récupérant les données, et mettez à jour le nœud constructor par défaut

  5. pour traiter les nœuds restants qui ne sont pas constructor, créez un prototype tapez la fonction à travers les données et mettez Aller à es5Fns

  6. La boucle se termine et placez le nœud constructor dans es5Fns

  7. pour déterminer si la longueur de es5Fns est supérieure à 1. Si elle est supérieure à 1, utilisez replaceWithMultiple cette API pour mettre à jour l'AST

module.exports = function ({ types: t }) {
 return {
  visitor: {
   ClassDeclaration(path) {
    //拿到老的AST节点
    let node = path.node
    let className = node.id.name
    let classInner = node.body.body
    //创建一个数组用来成盛放新生成AST
    let es5Fns = []
    //初始化默认的constructor节点
    let newConstructorId = t.identifier(className)
    let constructorFn = t.functionDeclaration(newConstructorId, [t.identifier('')], t.blockStatement([]), false, false)
    //循环老节点的AST对象
    for (let i = 0; i < classInner.length; i++) {
     let item = classInner[i]
     //判断函数的类型是不是constructor
     if (item.kind == &#39;constructor&#39;) {
      let constructorParams = item.params.length ? item.params[0].name : []
      let newConstructorParams = t.identifier(constructorParams)
      let constructorBody = classInner[i].body
      constructorFn = t.functionDeclaration(newConstructorId, [newConstructorParams], constructorBody, false, false)
     } 
     //处理其余不是constructor的节点
     else {
      let protoTypeObj = t.memberExpression(t.identifier(className), t.identifier(&#39;prototype&#39;), false)
      let left = t.memberExpression(protoTypeObj, t.identifier(item.key.name), false)
      //定义等号右边
      let prototypeParams = classInner[i].params.length ? classInner[i].params[i].name : []
      let newPrototypeParams = t.identifier(prototypeParams)
      let prototypeBody = classInner[i].body
      let right = t.functionExpression(null, [newPrototypeParams], prototypeBody, false, false)
      let protoTypeExpression = t.assignmentExpression("=", left, right)
      es5Fns.push(protoTypeExpression)
     }
    }
    //循环结束,把constructor节点也放到es5Fns中
    es5Fns.push(constructorFn)
    //判断es5Fns的长度是否大于1
    if (es5Fns.length > 1) {
     path.replaceWithMultiple(es5Fns)
    } else {
     path.replaceWith(constructorFn)
    }
   }
  }
 };
}

Optimiser l'héritage

En fait, la classe implique également l'héritage, et l'idée n'est pas compliquée, elle détermine simplement qu'il n'y a pas d'attribut superClass dans l'AST. , nous devons ajouter une ligne de code supplémentaire Bird.prototype = Object.create(Parent) Bien sûr, n'oubliez pas de traiter le mot-clé super.

Code packagé

Exécuter npm start Après packaging, on voit class

La syntaxe a été convertie avec succès en fonctions es5 une par une.

Je pense que vous maîtrisez la méthode après avoir lu le cas dans cet article. Pour des informations plus intéressantes, veuillez prêter attention aux autres articles connexes sur le site Web chinois de php !

Lecture recommandée :

Comment introduire la fonction de code de vérification Tencent dans le projet Vue

Implémentation JS de la minuterie + boîte d'invite

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