Open AnnVoV opened 5 years ago
上一篇写了通过写babel插件来入门ast, 在组内分享的时候,有同学说是不是可以写一个判空的插件呢? 把a.b => a && a.b呢?我觉得是的,这完全可以做呀!然后就尝试着在分享后写了一个。
a.b
a && a.b
https://astexplorer.net/#/gist/a54996b88a3fd57b65dbd9f2a14b4c91/fd5dbe0ea9ca616226980861f9d81e0984568753
var change = babelCheckEmpty(a.b.c.d); var notChange = d && d.e;
var change = a && (a.b && a.b.c && a.b.c.d); var notChange = d && d.e;
我只会去转换带有babelCheckEmpty 包裹的方法,这样避免影响其他方法的调用, 代码我贴在下面
module.exports = function (babel) { const {types: t} = babel; let isEnter = false; let objectName = ''; let stack = []; function getTemplateAst(tpl, opts = {}) { let ast = babel.template(tpl, opts)({}); if (Array.isArray(ast)) { return ast; } else { return [ast]; } } function generateExpressionStack(stack = []) { if (stack.length === 0) { return []; } let result = []; stack.reduce((sum, current) => { const nowStr = sum.concat('.').concat(current); result.push(nowStr); return nowStr; }); return result; } return { name: "ast-transform", // not required visitor: { CallExpression: { enter(path) { if (path.node.callee.name !== 'babelCheckEmpty') { return; } isEnter = true; }, exit(path) { if (path.node.callee.name !== 'babelCheckEmpty') { return; } isEnter = false; const resultArr = generateExpressionStack(stack); const arr = getTemplateAst(resultArr.join('&&')) || []; if (arr.length === 0 || stack.length === 0) { return; } path.replaceWith( t.logicalExpression('&&', t.identifier(stack[0]), arr[0].expression), ); stack = []; }, }, MemberExpression(path) { if (!isEnter || !path.node) return; objectName = path.node.object.name; if (t.isIdentifier(path.node.property)) { stack.unshift(path.node.property.name); } if (objectName) { stack.unshift(objectName); } }, }, }; };
由于直接用逻辑运算自己去构造一个 a.b && a.b.c && a.b.c.d 的ast过于复杂,其实是我不知道到底要怎么去写,所以我就使用了一个上一篇内容没有讲到的一个方法,直接利用babel.template 的API 根据传入的内容直接生成ast
let ast = babel.template(tpl, opts)({});
参考资料: 1.Babel 从入门到插件开发 https://juejin.im/entry/5912ba62a22b9d005819cff7 2.ast 入门(从写babel插件来深入了解ast https://github.com/AnnVoV/blog/issues/26
前言
上一篇写了通过写babel插件来入门ast, 在组内分享的时候,有同学说是不是可以写一个判空的插件呢? 把
a.b
=>a && a.b
呢?我觉得是的,这完全可以做呀!然后就尝试着在分享后写了一个。在线示例:
https://astexplorer.net/#/gist/a54996b88a3fd57b65dbd9f2a14b4c91/fd5dbe0ea9ca616226980861f9d81e0984568753
转换前:
转换后
我只会去转换带有babelCheckEmpty 包裹的方法,这样避免影响其他方法的调用, 代码我贴在下面
由于直接用逻辑运算自己去构造一个 a.b && a.b.c && a.b.c.d 的ast过于复杂,其实是我不知道到底要怎么去写,所以我就使用了一个上一篇内容没有讲到的一个方法,直接利用babel.template 的API 根据传入的内容直接生成ast
放入工程里的截图
参考资料: 1.Babel 从入门到插件开发 https://juejin.im/entry/5912ba62a22b9d005819cff7 2.ast 入门(从写babel插件来深入了解ast https://github.com/AnnVoV/blog/issues/26