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
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 :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 ouajouterAST ?
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 unobjet , 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
via astexplorer.net Le nœud AST correspondant est class
ClassDeclaration
dans vistor, ce qui signifie que je veux capturer tous les ClassDeclaration
nœuds dans le code js ClassDeclaration
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 :
Récupérez l'ancien nœud AST
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)
Bouclez l'objet AST de l'ancien nœud (plusieurs nœuds de fonction seront bouclés)
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
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
La boucle se termine et placez le nœud constructor
dans es5Fns
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 == 'constructor') { 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('prototype'), 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
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!