编程杂谈

types组件types能用于节点类型的判断和节点的生成,但是主要还是用来节点的生成,因为节点类型的判断可以不用该组件,也能实现类型判断//其他类型也是一样type.isIdentifier(path.node)//相当于path.node.type==='Identifier'type.isIdentifier(path.node,{'name':'x'})//相当于path.node.type==='Identifier'&&path.node.name==='x'节点生成生成实例代码constfs=require('fs')consttype=require("@babel/types")constgenerator=require("@babel/generator").default//AST转换为代码letobjPro1=type.objectProperty(key=type.identifier(name="name"),//第一个属性value=type.stringLiteral(value="haha"))//第一个属性值letbojPro2=type.objectProperty(key=type.identifier(name="add"),value=type.functionExpression(//函数节点id=null,params=[type.identifier(name="a"),type.identifier(name="b")],//参数列表body=type.blockStatement(//函数体body=[type.returnStatement(//返回值argument=type.binaryExpression(//二项式operator="+",left=type.binaryExpression(operator="+",left=type.identifier(name="a"),right=type.identifier(name="b")),right=type.numericLiteral(value=1000)))])))letbojPro3=type.objectProperty(key=type.identifier(name="mul"),//第三个属性value=type.functionExpression(//第三个属性值id=null,params=[type.identifier(name="a"),type.identifier(name="b")],body=type.blockStatement(body=[type.returnStatement(argument=type.binaryExpression(operator="+",left=type.binaryExpression(operator="*",left=type.identifier(name="a"),right=type.identifier(name="b")),right=type.numericLiteral(value=1000)))])))letobj=type.objectExpression([objPro1,bojPro2,bojPro3])//变量初始化letletDec=type.variableDeclarator(type.identifier(name="obj"),init=obj)//变量名letlocalAst=type.variableDeclaration("let",[letDec])//声明变量//ast转化为代码letcode=generator(localAst).codefs.writeFile("./output/code.js",code,(err=>{}))上面使用到stringLiteral、numericLiteraltypes还提供了其他字面量,按照语法树来,都是差不多的declarefunctionstringLiteral(value:string):StringLiteral;declarefunctionnumericLiteral(value:number):NumericLiteral;declarefunctionnullLiteral():NullLiteral;declarefunctionbooleanLiteral(value:boolean):BooleanLiteral;declarefunctionregExpLiteral(pattern:string,flags?:string):RegExpLiteral;当界面量太多,太复杂的时候,Bable也提供了一个简便的方式valueToNode()//可以看出valueToNode可以很方便的生成其他类型exportfunctionvalueToNode(value:undefined):IdentifierexportfunctionvalueToNode(value:boolean):BooleanLiteralexportfunctionvalueToNode(value:null):NullLiteralexportfunctionvalueToNode(value:string):StringLiteralexportfunctionvalueToNode(value:number):NumericLiteral|BinaryExpression|UnaryExpressionexportfunctionvalueToNode(value:RegExp):RegExpLiteralexportfunctionvalueToNode(value:ReadonlyArray<undefined|boolean|null|string|number|RegExp|object>):ArrayExpressionexportfunctionvalueToNode(value:object):ObjectExpressionexportfunctionvalueToNode(value:undefined|boolean|null|string|number|RegExp|object):Expressionconsole.log(generator(type.valueToNode(123)).code)console.log(generator(type.valueToNode('mimi')).code)console.log(generator(type.valueToNode(undefined)).code)console.log(generator(type.valueToNode(null)).code)/*123"mimi"undefinednull*/

编程杂谈

parse&generator组件parse作用是代码转化为AST结构解析网站:https://astexplorer.net/constparser=require("@babel/parser");//需要导入letast=parser.parse(js_code)//代码转化为ast结构,与网站上一样letast1=parser.parse(js_code,{sourceType:"module",//如果有importexport关键字,需要使用该参数})console.log(JSON.stringify(ast,null,2))generator作用是AST结构转化为代码letcode=generator(ast).codeletcode1=generator(ast,{retainLines:false,//默认false,是否输出与源代码相同的行号comments:false,//默认true,是否保留注释compact:true//默认false,是否压缩代码}).codetraverse&visitor组件traverse用来遍历AST结构的节点,简单点说就是把所有节点都运行一遍traverse使用的深度优先策略//导入consttraverse=require("@babel/traverse").default;//遍历节点constgenerator=require("@babel/generator").default//AST转换为代码//相关操作letvisitor={}visitor.FunctionExpression=function(path){console.log("mmmmm")}traverse(ast,visitor)/*源码有两个函数节点所以输出两次mmmmmmmm*/visitor三种写法按照自己的喜好选择,最常用的visitor2letvisitor1={FunctionExpression:function(path){console.log('...')}}letvisitor2={FunctionExpression(path){console.log('...')}}letvisitor3={FunctionExpression:{enter(path){console.log('进入->函数节点')},exit(path){console.log('退出<-函数节点')}}}traverse(ast,visitor3)visitor组合写法使用|组合不同的类型letvisitor1={'FunctionExpression|BinaryExpression':function(path){console.log('...')}}letvisitor2={'FunctionExpression|BinaryExpression'(path){console.log('...')}}letvisitor3={'FunctionExpression|BinaryExpression':{enter(path){console.log('进入->节点')},exit(path){console.log('退出<-节点')}}}traverse(ast,visitor3)使用多个函数处理节点,会按照函数顺序执行functionfun1(path){console.log('11')}functionfun2(path){console.log('22')}letvisitor={FunctionExpression:{enter:[fun1,fun2]}}traverse(ast,visitor)traverse并非必须从头遍历//修改函数第一个参数为x,并修改函数内所有用了该参数的地方constupdateParamNameVisitor={Identifier(path){if(path.node.name===this.paramName){path.node.name="x"}}}constvisitor={FunctionExpression(path){//遍历函数节点constparamName=path.node.params[0].name//内部循环path.traverse(updateParamNameVisitor,{paramName//向子循环传递参数})}}traverse(ast,visitor)

编程杂谈

说明思想:用Miniconda管理多个Python版本,在使用poetry创建虚拟环境的时候,指定Miniconda环境里的Py版本使用前的准备安装Miniconda链接:https://docs.conda.io/en/latest/miniconda.html安装poetry链接:https://bigdataboy.cn/post-399.html创建环境使用Miniconda创建多个Py版本的环境创建不同Python版本的虚拟环境condacreate-nPy3.9python=3.9查看环境condaenvlist使用第一步初始化poetry,使用命令:poetryinit,如果不是新项目直接跳到第二步这里有个坑,poetry指定Py版本的时候,只好写成这种格式~3.8(支持3.8.<3.9.0),不然会报版本不一致的错误,原因就是conda下载的版本是3.8.x,两处版本支持范围要严格一直F:\Tools\pyCode\test>poetryinitThiscommandwillguideyouthroughcreatingyourpyproject.tomlconfig.Packagename[test]:Version[0.1.0]:Description[]:Author[‘zbigdataboy‘<876545500@qq.com>,ntoskip]:bigdataboyLicense[]:CompatiblePythonversions[^3.9]:~3.8Wouldyouliketodefineyourmaindependenciesinteractively?(yes/no)[yes]noWouldyouliketodefineyourdevelopmentdependenciesinteractively?(yes/no)[yes]noGeneratedfile[tool.poetry]name="test"version="0.1.0"description=""authors=["bigdataboy"][tool.poetry.dependencies]python="~3.8"[tool.poetry.dev-dependencies][build-system]requires=["poetry-core>=1.0.0"]build-backend="poetry.core.masonry.api"Doyouconfirmgeneration?(yes/no)[yes]yes第二步peotry使用指定的解释器如果报版本不一致的错误,看第一步的坑poetryenvuseD:\ProgramData\miniconda3\envs\Py3.8\python.exe第三步安装相关依赖poetryinstall

编程杂谈

介绍VueRouter是Vue.js的官方路由。它与Vue.js核心深度集成,让用Vue.js构建单页应用变得轻而易举。功能包括:嵌套路由映射动态路由选择模块化、基于组件的路由配置路由参数、查询、通配符展示由Vue.js的过渡系统提供的过渡效果细致的导航控制自动激活CSS类的链接HTML5history模式或hash模式可定制的滚动行为URL的正确编码官网文档:https://router.vuejs.org/zh/introduction.html安装vue-router:npminstallvue-router//默认安装最新稳定版npminstallvue-router@3//安装3.Xvue-routervue2.X使用一个重要概念Vue的是单页程序,路由跳转是把内容展示在<router-view>标签上也能实现页面的条件创建路由管理文件在src里新建router文件夹,在新建index.js//src/router/index.jsimportVuefrom"vue";importVueRouterfrom"vue-router";importLoginfrom'../components/Login'importRegisterfrom'../components/Register'Vue.use(VueRouter)//使用VueRouterexportdefaultnewVueRouter({//导出VueRouter实例routes:[{//登录path:'/login',//请求路径name:'login',//定义名字为了更好的传递参数component:Login,//展示的组件},{//注册path:'/register',name:'register',component:Register,}]})在src/main.js引入路由importVuefrom'vue';importrouterfrom'./router';//自动扫描index.js文件importAppfrom'./App';newVue({el:'#app',router,//添加render:h=>h(App)});路由跳转<router-link>最终会被渲染成<a>标签<router-linkto="/register"><h2>注册</h2></router-link><router-linkto="/login"><h3>登录</h3></router-link><!--路由匹配到的组件将渲染在这里--><router-view></router-view><!--路由定义了名字才能这样传递参数--><router-link:to="{name:'user',params:{userId:123}}">User</router-link>路由模式两种路由方式都不会重新加载页面hash路由模式(默认值):http://localhost:8080/#/registerhistory路由模式:http://localhost:8080/registerexportdefaultnewVueRouter({mode:'history',routes:[...]})路由传参路由参数的传递,设置后,在$route.params获取参数值exportdefaultnewVueRouter({routes:[//动态路径参数以冒号开头{path:'/user/:id',component:User},//设置多段路径参数{path:'/user/:username/post/:id',component:User}]})/*/user/12-->$route.params-->{id:12}/user/Bob/post/2-->$route.params-->{username:'Bob',id:2}*/使用$route.params会造成严重耦合,所有还有一种方式传递路由参数exportdefaultnewVueRouter({mode:'history',routes:[{path:'/user/:id',name:'user',component:User,props:true,//设置props为ture}]})捕获所有路由或404Notfound路由路由是支持正则表达式匹配的,匹配的优先级就是定义路由的顺序当使用通配符路由时,请确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。路由{path:'*'}通常用于客户端404错误。如exportdefaultnewVueRouter({routes:[//动态路径参数以冒号开头{path:'/user/:id',component:User},//设置多段路径参数{path:'/user/:username/post/:id',component:User},{//通配会匹配所有路径path:'*'},{//会匹配以`/user-`开头的任意路径path:'/user-*'}]})重定向exportdefaultnewVueRouter({routes:[{path:'/a',redirect:'/b'},//直接重定向{path:'/c',redirect:{name:'login'}}//可以使用name]})嵌套路由效果其实是在子组件中渲染界面exportdefaultnewVueRouter({routes:[//动态路径参数以冒号开头{path:'/user/:id',component:User,children:[{//当/user/:id/profile匹配成功,//UserProfile会被渲染在User的<router-view>中path:'profile',component:UserProfile},{//当/user/:id/posts匹配成功//UserPosts会被渲染在User的<router-view>中path:'posts',component:UserPosts}]},})

编程杂谈

说明插槽:可以理解为占一块位置,然后可以插入组件,当有数据传入待插入组件时,再展示出来,没有数据时,插槽位置为空有数据时没有数时注册组件//留有插槽的组件模板里关联有待插入组件Vue.component('item',{template:'<div>\<slotname="h4-title"></slot>\<ul>\<slotname="li-slot"></slot>\</ul>\</div>'})//待插入组件Vue.component('h4-title',{props:['title'],template:'<h4>{{title}}</h4>'})//待插入组件Vue.component('li-slot',{props:['item'],template:'<li>{{item}}</li>'})使用item组件<item><!--插槽与待插入组件关联--><h4-titleslot="h4-title":title="title"></h4-title><li-slotslot="li-slot"v-for="(item,index)initems":item='item'></li-slot></item>全部代码<!DOCTYPEhtml><html><head><metacharset="utf-8"/><title></title><!--<scriptsrc="https://unpkg.com/vue@next"></script>--><scriptsrc="js/v2.6.10/vue.min.js"type="text/javascript"charset="utf-8"></script></head><body><divid="app"><item><!--插槽与待插入组件关联--><h4-titleslot="h4-title":title="title"></h4-title><li-slotslot="li-slot"v-for="(item,index)initems":item='item'></li-slot></item></div><script>Vue.component('item',{template:'<div>\<slotname="h4-title"></slot>\<ul>\<slotname="li-slot"></slot>\</ul>\</div>'})Vue.component('h4-title',{props:['title'],template:'<h4>{{title}}</h4>'})Vue.component('li-slot',{props:['item'],template:'<li>{{item}}</li>'})varvue=newVue({el:'#app',data:{counter:'hello',title:'标题',items:['AA','BB','CC']}})</script></body></html>

2022-4-1 478 0
编程杂谈

说明泛型的使用:当定义类型时(函数、变量、接口、类),只有在使用的时候,才只是具体是什么类型时,就可以使用泛型定义引入实现生成传入指定元素,指定长度的数组functioncreatArray(value:any,count:number):any[]{letarr:any[]=[];//需要初始化for(leti=0;i<count;i++){arr.push(value);}returnarr;}console.log(creatArray('XX',5))//['XX','XX','XX','XX','XX']使用泛型functioncreatArray<T>(value:T,count:number):T[]{letarr:T[]=[];//需要初始化for(leti=0;i<count;i++){arr.push(value);}returnarr;}console.log(creatArray<number>(22,5))//[22,22,22,22,22]多个泛型参数的函数泛型常用字母K、V、TfunctioncreatArray<K,V>(x:K,y:V):[K,V]{return[x,y]}console.log(creatArray<number,string>(22,'XX'))//[22,'XX']泛型接口在实现接口时,再定义类型//泛型接口interfaceIbaseCRUD<T>{data:T[]add(t:T):voidgetById(id:number):T}classUser{id?:number;//id主键name:string;age:number;constructor(name:string,age:number){this.name=name;this.age=age;}}classUserCRUDimplementsIbaseCRUD<User>{data:User[]=[]add(user:User):void{user={...user,id:Date.now()}this.data.push(user);console.log('saveuser',user)}getById(id:number):User{returnthis.data[id]}}constuserCRUD=newUserCRUD()userCRUD.add(newUser('XX',16))userCRUD.add(newUser('YY',17))console.log(userCRUD.getById(1))//{name:'YY',age:17,id:1646630710525}泛型类在实例化类时,再定义类型classUser{name:string;age:number;constructor(name:string,age:number){this.name=name;this.age=age;}}classUserCRUD<T>{data:T[]=[]add(user:T):void{this.data.push(user);console.log('saveuser',user)}}constuserCRUD=newUserCRUD<User>();userCRUD.add(newUser('XX',16))//saveuserUser{name:'XX',age:16}泛型约束当使用泛型时,函数逻辑中,可能并不知道该类型有这个方法或属性,而报错,智能提示也不好functionfn<T>(x:T):void{//console.log(x.lenght)//报错:类型“T”上不存在属性“lenght”。}处理:泛型继承某类、某接口一个泛型变量只能继承一个类或者接口classUser{constructor(publicname:string,publicage:number){}}//泛型继承User类functionfn<TextendsUser>(x:T):void{console.log(x.name,x.age)}//传入符合这中类型的值fn(newUser('XX',16))//XX16

2022-3-14 454 0