最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • @babel/types深度应用

    正文概述 掘金(JS老狗)   2021-07-18   1442

    前文说过,types已经集成到@babel/core里,当然也可以单独安装:

    npm i -D @babel/types
    

    概述

    @babel/types的用途主要有3种:

    类型集合

    当你在ts中使用babel时,types可以为你提供全部节点对应的类型。

    let n1: types.Identifier
    let n2: types.ExpressionStatement
    

    类型判断

    每一种节点类型,都有对应的类型判断方法:

    if(types.isIdentifier(n1)) {
        // ...
    }
    
    if(types.isExpressionStatement(n2)) {
        // ...
    }
    

    每个类型判断方法,都实现了类型保护,顺道聊一下

    TypeScript 类型保护。

    先定义一个泛型的类型保护函数:

    type IsType<T> = (target: any) => target is T
    

    然后实现一下string类型保护:

    const isString: IsType<string> = (target): target is string => {
        return typeof target === 'string'
    }
    
    if(isString(abc)) {
        // 当此处调用abc时,vscode会按照string类型给予足够提示
        abc.slice
    }
    

    当然,原生值类型的类型判断比较简单,上面的代码和

    if(typeof abc === 'string') {
        // ...
    }
    

    效果一样。下面对自定义复杂类型做一下类型保护:

    type TComplex = {
        name: string
        age: number
    }
    
    const isComplex: IsType<TComplex> = (target): target is TComplex => {
        return (
            target
            && typeof target.name === 'string'
            && typeof target.age === 'number'
            && !isNaN(target.age)
        )
    }
    

    至于isComplex内部如何实现,完全看场景和需求。这一段的关键是:通过类型保护实现的判断,在判断的内部,完全按照该变量类型结构进行提示,开发体验非常棒。

    创建节点

    每一种节点类型,都有对应的创建方法:

    const id = types.identifier('abc')
    const str = types.stringLiteral('Hello World')
    const num = types.numericLiteral(10e3)
    

    实践

    先写个log方法

    import * as types from '@babel/types'
    import gen from '@babel/generator'
    
    const log = (node: types.Node) => {
        console.log(gen(node).code)
    }
    

    创建值类型

    log(types.stringLiteral('string'))
    log(types.numericLiteral(10e4))
    log(types.booleanLiteral(0.5 > Math.random()))
    log(types.regExpLiteral('\\.jsx?$', 'g'))
    
    % ts-node gen.ts
    "string"
    100000
    false
    /\.jsx?$/g
    

    创建Array

    log(
        types.arrayExpression([
            types.stringLiteral('string'),
            types.numericLiteral(10e4),
            types.booleanLiteral(0.5 > Math.random()),
            types.regExpLiteral('\\.jsx?$', 'g')
        ])
    )
    
    % ts-node gen.ts
    ["string", 100000, false, /\.jsx?$/g]
    

    创建Object

    log(
        types.objectExpression([
            types.objectProperty(
                types.identifier('a'),
                types.nullLiteral()
            ),
            types.objectProperty(
                // 字符串类型 key
                types.stringLiteral('*'),
                types.arrayExpression([]),
            ),
            types.objectProperty(
                types.identifier('id'),
                types.identifier('id'),
                false,
                // shorthand 对 { id: id } 简写为 { id }
                true
            ),
            types.objectProperty(
                types.memberExpression(
                    types.identifier('props'),
                    types.identifier('class')
                ),
                types.booleanLiteral(true),
                // 计算值 key
                true
            )
        ])
    )
    
    % ts-node gen.ts
    {
      a: null,
      "*": [],
      id,
      [props.class]: true
    }
    

    创建具名 function

    log(
        types.functionDeclaration(
            types.identifier('foo'),
            [types.identifier('arg1')],
            types.blockStatement([
                types.expressionStatement(
                    types.callExpression(
                        types.identifier('console.log'),
                        [types.identifier('arg1')]
                    )
                )
            ])
        )
    )
    
    % ts-node gen.ts
    function foo(arg1) {
      console.log(arg1);
    }
    

    创建箭头函数

    log(
        // 无实体代码块
        types.arrowFunctionExpression(
            [types.identifier('arg1')],
            types.callExpression(
                types.identifier('console.log'),
                [types.identifier('arg1')]
            )
        )
    )
    
    % ts-node gen.ts
    arg1 => console.log(arg1)
    
    log(
        // 有实体代码块
        types.arrowFunctionExpression(
            [types.identifier('arg1')],
            types.blockStatement([
                types.expressionStatement(
                    types.callExpression(
                        types.identifier('console.log'),
                        [types.identifier('arg1')]
                    )
                )
            ])
        )
    )
    
    % ts-node gen.ts
    arg1 => {
      console.log(arg1);
    }
    

    JSX绑定值

    log(
        types.jsxExpressionContainer(types.identifier('props.name'))
    )
    
    % ts-node gen.ts
    {props.name}
    

    JSX节点

    log(
        types.jsxElement(
            types.jsxOpeningElement(types.jsxIdentifier('Text'), []),
            types.jsxClosingElement(types.jsxIdentifier('Text')),
            [types.jsxExpressionContainer(types.identifier('props.name'))]
        )
    )
    
    % ts-node gen.ts
    <Text>{props.name}</Text>
    

    JSXFragment

    log(
        types.jsxFragment(
            types.jsxOpeningFragment(),
            types.jsxClosingFragment(),
            [
                types.jsxElement(
                    types.jsxOpeningElement(types.jsxIdentifier('Text'), []),
                    types.jsxClosingElement(types.jsxIdentifier('Text')),
                    [types.jsxExpressionContainer(types.identifier('props.name'))]
                ),
                types.jsxElement(
                    types.jsxOpeningElement(types.jsxIdentifier('Text'), []),
                    types.jsxClosingElement(types.jsxIdentifier('Text')),
                    [types.jsxExpressionContainer(types.identifier('props.age'))]
                )
            ]
        )
    )
    
    % ts-node gen.ts
    <><Text>{props.name}</Text><Text>{props.age}</Text></>
    

    综合应用:生成React函数式组件

    log(
        types.program([
            types.importDeclaration(
                [types.importDefaultSpecifier(types.identifier('React'))],
                types.stringLiteral('react')
            ),
            types.exportDefaultDeclaration(
                types.arrowFunctionExpression(
                    [types.identifier('props')],
                    types.jsxElement(
                        types.jsxOpeningElement(types.jsxIdentifier('Component'), [
                            types.jsxAttribute(
                                types.jsxIdentifier('onClick'),
                                types.jSXExpressionContainer(
                                    types.identifier('handleClick')
                                )
                            )
                        ]),
                        types.jsxClosingElement(types.jsxIdentifier('Component')),
                        [
                            types.jsxElement(
                                types.jsxOpeningElement(types.jsxIdentifier('Image'), [
                                    types.jsxAttribute(
                                        types.jsxIdentifier('src'),
                                        types.stringLiteral('https://image1.suning.cn/uimg/cms/img/159642507148437980.png')
                                    )
                                ]),
                                types.jsxClosingElement(types.jsxIdentifier('Image')),
                                [],
                                true
                            )
                        ],
                        false
                    )
                )
            )
        ])
    )
    
    % ts-node gen.ts
    import React from "react";
    export default (props => <Component onClick={handleClick}><Image src="https://img.qiyuandi.com/images/5/@babebcdigegxjot.jpg"></Image></Component>);
    

    主要是经验总结的流水账,多用多试就对了。

    以上。


    起源地下载网 » @babel/types深度应用

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元