编程杂谈

说明插槽:可以理解为占一块位置,然后可以插入组件,当有数据传入待插入组件时,再展示出来,没有数据时,插槽位置为空有数据时没有数时注册组件//留有插槽的组件模板里关联有待插入组件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 623 0
奇巧淫技

jsvmp特点jsvmp有一个最大的特点,就是有一长串字符串._$jsvmprt(...),算法代码的具体细节都在这个一节长字符串里,所有在算法的扣取上就很不友好,本案例采取补环境的方式实现。(glb="undefined"==typeofwindow?global:window)._$jsvmprt(.....)逻辑分析定位加密入口添加XHR断点,然后向下滑动,断点短住搜索_signature,在关键位置下断点,然后在刷新页面断点位置r变量,来自于S(n,e)函数计算,该S函数就是入口函数分析加密得值逻辑进入S函数,分析这一段逻辑,其实调用的就是//o是{'url':'xxxx'}window.byted_acrawler.sign(o)进入window.byted_acrawler.sign函数,来到acrawler.js文件,也就是jsvmp的Js文件补环境把acrawler.js文件全部复制下来,代码起始有一句(varglb;glb="undefined"==typeofwindow?global:window),这是检查当前是什么环境的,是node还是浏览器有两种处理办法使用jsdom补充window使用window=global当然还有其他更好的方式,这里采用第二次这样就和浏览器一样了加上一个输出,尝试使用node,浏览器执行,查看两者的区别浏览器正常得值,node报错,说明node缺少一些条件在浏览器添加条件断点,查看referrer是什么//referrer来自于document,继续添加环境document={referrer:''}node继续执行,发现没有sign,说明node还被检查着经过分析,发现这些代码,exports、module,这是node才存在的东西,直接改成undefined当然也有更好的方式直接过滤这些特征//nodetrue浏览器false"undefined"!=typeofexports//nodetrue浏览器false"undefined"!=typeofmodule继续执行,缺少href,就根据浏览器的插装输出补充就好了然后是缺少‘protocol’location={href:'',protocol:'https:'}然后是缺少userAgentnavigator={userAgent:'Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/86.0.4240.198Safari/537.36'}再次执行,出现结果因为校验的不严格,所以这个短Cookie也是可以过的,长Cookie需要添加一些Cookie才行长Cookie需要加上其他的Cookie,这个cookie位置需要靠后,不然会被清空如果是自己写的环境框架,就不需要担心cookie的位置为了稳定,请求头部还需要带一个随机Cookie完整结构

Python极客

ORM说明SQLAlchemy是Python中,通过ORM操作数据库的框架。简单点来说,就是帮助我们从烦冗的SQL语句中解脱出来,从而不需要再去写原生的SQL语句,只需要用Python的语法来操作对象,就能被自动映射为SQL语句。安装SQLAlchemy:pip3installSQLAlchemy使用本文以sqlite数据为例,当然sqlalchemy也支持其他数据,MySQL、PostgreSQL、Oracle、MSSQL...连接引擎任何SQLAlchemy应用程序的开始都是一个Engine对象,此对象充当连接到特定数据库的中心源,提供被称为connectionpool的对于这些数据库连接。"""配置连接数据库database.py"""fromsqlalchemyimportcreate_engineDATABASE_URL='sqlite:///orm.db'#sqlite://数据库路径engine=create_engine(#创建引擎DATABASE_URL,encoding='utf-8',echo=True,#引擎将用repr()函数记录所有语句及其参数列表到日志connect_args={'check_same_thread':False},#【使用sqlite数据库才配置】sqlalchemy是多线程的,'check_same_thread':False来让建立的任意线程都可以使用)声明映射Python中的一个类,对应一个表,类的每个属性对应表的字段名。每个映射类都需要继承declarative_base()"""配置连接数据库database.py"""fromsqlalchemy.ormimportdeclarative_baseBase=declarative_base()创建两张表,我们不需要事先在数据库创建表"""ORM操作的模型类models.py"""fromsqlalchemyimportColumn,Integer,String,Enum,DateTime,func,ForeignKeyfromdatabaseimportBase,engineclassClassRoom(Base):__tablename__='orm_classroom'#表名id=Column(Integer,primary_key=True,index=True,autoincrement=True)classroom_num=Column(Integer,unique=True,nullable=False,comment='几班')teacher=Column(String(100),unique=False,nullable=False,comment='班主任')student_num=Column(Integer,unique=False,nullable=False,comment='班级人数')create_at=Column(DateTime,server_default=func.now(),comment='创建时间')update_at=Column(DateTime,server_default=func.now(),onupdate=func.now(),comment='更新时间')def__repr__(self):#方便显示returnf'id={self.id}classroom_num={self.classroom_num}teacher={self.teacher}student_num={self.student_num}'classStudent(Base):__tablename__='orm_student'#表名id=Column(Integer,primary_key=True,index=True,autoincrement=True)#主键自增name=Column(String(100),unique=False,nullable=False,comment='姓名')#字符串不唯一不为空备注sex=Column(Enum('男','女'),comment='性别')classroom_num=Column(Integer,ForeignKey('orm_classroom.classroom_num'),comment='所属班级')create_at=Column(DateTime,server_default=func.now(),comment='创建时间')update_at=Column(DateTime,server_default=func.now(),onupdate=func.now(),comment='更新时间')def__repr__(self):#方便显示returnf'id={self.id}name={self.name}sex={self.sex}classroom_num={self.classroom_num}'Base.metadata.create_all(engine)#创建表运行models.py文件创建会话参数autoflush、autocommit的说明,推荐博客:https://zhuanlan.zhihu.com/p/48994990"""配置连接数据库database.py"""#在SQLAlchemy中,CRUD都是通过会话(session)进行的,所以我们必须要先创建会话SessionLocal=sessionmaker(bind=engine,autoflush=False,#关闭flush()函数的调用,flush()作用是发送语句到数据库,但数据库不一定执行写入磁盘操作autocommit=False,#关闭commit()函数调用,commit()作用是提交事务,将变更保存到数据库文件expire_on_commit=True)进行crud操作封装"""对数据库增删改查crud.py""""""对数据库增删改查crud.py"""fromsqlalchemy.ormimportSessionfromstoragesimportmodels,schemas#增defcreate_student(db:Session,student:schemas.CreateStudent):"""传入BaseMode实例"""db_student=models.Student(**student.dict())db.add(db_student)db.commit()#提交事务db.refresh(db_student)#刷新returndb_student#增defcreate_class_room(db:Session,classroom:schemas.CreateClassRoom):"""传入BaseMode实例"""db_classroom=models.Student(**classroom.dict())db.add(db_classroom)db.commit()#提交事务db.refresh(db_classroom)#刷新returndb_classroom#查defget_student_by_id(db:Session,student_id:int):"""通过id查询学生表"""returndb.query(models.Student).filter(models.Student.id==student_id).first()#查defget_student_by_name(db:Session,name:str):"""通过name查询学生表"""returndb.query(models.Student).filter(models.Student.name==name)#删defdel_student_by_id(db:Session,student_id:int):student=get_student_by_id(db,student_id)db.delete(student)#先查询再删除db.commit()returnstudent#改defupdate_student_name_by_id(db:Session,student_id:int,name:str):student=get_student_by_id(db,student_id)student.name=name#查询结果修改提交事务db.commit()returnstudent使用"""主文件main.py"""fromstorages.databaseimportSessionLocal,Base,enginefromstorages.crudimportcreate_student,get_student_by_id,del_student_by_id,update_student_name_by_idfromstorages.schemasimportCreateStudentBase.metadata.create_all(engine)#创建表db=SessionLocal()student=CreateStudent(name='Bob',sex='男',classroom_num=1)create_student(db=db,student=student)print('查询结果',get_student_by_id(db=db,student_id=1))#print('删除结果',del_student_by_id(db=db,student_id=2))#print('修改结果',update_student_name_by_id(db=db,student_id=3,name='Aoa'))查询数据query()的使用query()可以理解为SQL的selectdb.query(models.Student).filter()过滤db.query(models.Student).filter_by()根据关键字过滤db.query(models.Student).all()返回全部【列表】db.query(models.Student).first()返回第一个元素db.query(models.Student).one()有且只有一个元素时才正确返回db.query(models.Student).one_or_none(),类似one,但如果没有找到结果,则不会引发错误db.query(models.Student).scalar(),调用one方法,并在成功时返回行的第一列db.query(models.Student).count()计数db.query(models.Student).order_by()排序filter()与filter_by()过滤filter()使用#等于db.query(models.Student).filter(Student.name=='Bob')#不等于db.query(models.Student).filter(Student.name!='Bob')#like和ilikedb.query(models.Student).filter(Student.name.like('%Bob%'))db.query(models.Student).filter(Student.name.ilike('%Bob%'))#不区分大小写#isdb.query(models.Student).filter(Student.name==None)#isnotdb.query(models.Student).filter(Student.name!=None)#andfromsqlalchemyimportand_db.query(models.Student).filter(and_(Student.name=='Bob',Student.id==2))db.query(models.Student).filter(Student.name=='Bob',Student.fullname==2)db.query(models.Student).filter(Student.name=='Bob').filter(Student.fullname==2)#orfromsqlalchemyimportor_db.query(models.Student).filter(or_(Student.name=='Bob',Student.name=='Aoa'))#matchdb.query(models.Student).filter(Student.name.match('Bob'))filter_by()使用#id是模型的字段db.query(models.Student).filter_by(id=student_id,name='Bob').first()jion()连接查询db.query(models.Student).join(models.ClassRoom).\filter(\models.Student.classroom_num==models.ClassRoom.classroom_num\).all()

编程杂谈

说明泛型的使用:当定义类型时(函数、变量、接口、类),只有在使用的时候,才只是具体是什么类型时,就可以使用泛型定义引入实现生成传入指定元素,指定长度的数组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 589 0
2022-3-13 582 0
编程杂谈

说明对于传统的JavaScript程序我们会使用函数和基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员使用这些语法就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来的。从ECMAScript2015,也就是ES6开始,JavaScript程序员将能够使用基于类的面向对象的方式。使用TypeScript,我们允许开发者现在就使用这些特性,并且编译后的JavaScript可以在所有主流浏览器和平台上运行,而不需要等到下个JavaScript版本。类的结构类的主要元素:属性、构造器、方法classCat{//属性name:stringage:number//构造函数constructor(name:string,age:number){this.name=name;this.age=age;}//普通方法eat():void{console.log(`${this.name}吃玉米`)}}letcat:Cat=newCat('O_O',12);cat.eat()继承&多态关键字extendsclassAnimal{//属性name:stringage:numberconstructor(name:string,age:number){this.name=name;this.age=age;}run(distance:number):void{console.log(`Animalrun${distance}m`)}}classCatextendsAnimal{//继承type:string//构造函数constructor(name:string,age:number){super(name,age)//调用父类构造函数}//普通方法eat():void{console.log(`${this.name}吃玉米`)}//重写父类方法run(distance:number):void{console.log(`${this.name}run${distance}m`)}}letcat:Cat=newCat('O_O',12);cat.run(15)权限修饰符默认公共public,实例对象,类内部,子类都可以访问私有private,只有类内部可以访问保护protected,类内部、子类之类可以访问classAnimal{//属性protectedname:string//当前类内部子类publicage:number//公共constructor(name:string,age:number){this.name=name;this.age=age;}run(distance:number):void{console.log(`Animalrun${distance}m`)}}classCatextendsAnimal{//继承privatetype:string//当前类内部//构造函数constructor(name:string,age:number){super(name,age)//调用父类构造函数}//普通方法eat():void{console.log(`${this.name}吃玉米`)}//重写父类方法run(distance:number):void{console.log(`${this.name}run${distance}m`)}}letcat:Cat=newCat('O_O',12);cat.run(15)console.log(cat.age)//12readonly修饰符readonly修饰属性为可读,只能在定义时或者构造函数初始化classPerson{readonlyname:string='abc'constructor(name:string){this.name=name}}letjohn=newPerson('John')参数属性TypeScript不一样的地方,作用简化代码不止能写readonly,其他权限public,private,protected//与上一个代码效果一样classPerson{constructor(readonlyname:string){}}letjohn=newPerson('John')静态属性不用实例化就能获取的属性classDog{staticname_:string='O_O'}console.log(Dog.name_)//'O_O'抽象类抽象类和抽象方法用abstract关键字抽象类作为其它类继承使用。抽象类不能被实例化。不同于接口,抽象类的普通方法可以有方法体,但抽象方法不能有方法体抽象方法必须在抽象类里abstractclassAnimal{abstracteat():void;//抽象方法没有实现细节run(x:number){//继承后普通方法可以不用实现console.log(`xxrun${x}m`)}}classDogextendsAnimal{eat(){//必须实现全部抽象方法的方法体console.log(`dogeatxx`)}}letdog:Dog=newDog()dog.run(15)//xxrun15m

2022-3-12 647 0
编程杂谈

接口说明接口是对象的状态(属性)和行为(方法)的抽象(描述),简单理解就是规范结构,接口不能初始化属性TypeScript的核心原则之一是对值所具有的结构进行类型检查。我们使用接口(Interfaces)来定义对象的类型。接口结构结构关键字interfaceinterfaceIPersion{id:numbername:stringage:string}constperson:IPersion={id:1,name:'o_o',age:14};可选属性interfaceIPersion{id:numbername:stringage?:string//该属性可以不存在}constperson:IPersion={id:1,name:'o_o'};只读属性关键字readonly该值只能在初始化时被改变,除此之外不能被改变interfaceIPersion{id:numberreadonlyname:string//只读age?:number}letperson:IPersion={id:1,name:'o_o'};person.id=2;//person.name='*_*';//报错不呢被改变readonlyvsconstreadonly修饰属性const修饰变量接口规范函数类型看着可能有点奇怪,这里明确一个概念,函数的必要元素:参数列表、返回值。(匿名没有函数名,所以函数名非必要)//定义函数类型interfaceIFunType{//参数列表:返回值(s1:string,s2:string):string}//变量类型为函数letfun:IFunType=function(s1:string,s2:string):string{return`${s1}_${s2}`}console.log(fun('kk','xx'));类接口作用于Java、C#里面一样,类需要实现接口interfaceIAnimal{type:stringeat():void}classCatimplementsIAnimal{type:string='猫'eat(){console.log(`${this.type}吃${this.type}粮`)}}letcat:Cat=newCat();cat.eat()接口继承接口接口间叫继承interfaceIAnimal{//动物接口type:stringeat():void}interfaceIFelidaeextendsIAnimal{//猫科接口继承动物接口leg_num:number}类实现多个接口interfaceIAnimal{//动物接口type:stringeat():void}interfaceIPerson{name:stringage:number}classPersonimplementsIAnimal,IPerson{type:string='person'name:stringage:numbereat(){console.log(`${this.type}吃玉米`)}}letperson:Person=newPerson();person.eat()//person吃玉米

2022-3-10 668 0
编程杂谈

说明TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型布尔值letmsg:boolean=true;数字TypeScript里的所有数字都是浮点数。这些浮点数的类型是number。letn1:number=12;//十进制letn2:number=0b1010;//二进制letn3:number=0o12;//八进制letn4:number=0xa;//十六进制字符串单引号双引号都可以lets:string='xxx';undefined和null它们的本身的类型用处不是很大letund:undefined=undefined;letnu:null=null;数组TypeScript像JavaScript一样可以操作数组元素。有两种方式可以定义数组。第一种,let变量名:类型[]=[];letarr:number[]=[1,2,3,4];第二种泛型定义,Array<类型>letarr:Array<number>=[1,2,3,4];元组元组类型允许表示一个已知元素数量和类型的数组lettu:[number,string,boolean]=[1,'咪咪',true];枚举enum类型是对JavaScript标准数据类型的一个补充enumColor{Red,//0Green=10,Blue//11}letcolor:Color=Color.Blue;console.log(Color)//0any当不知定义什么类型比较合适时使用leta:any;a=12;a='12';letb:any=12;b='a';console.log(a,b)//'12''a'object所有对象的基类leto:object={'a':12};letoo:object=newString('oo');联合类型表示取值为多种类型中的一种functionfun(s:number|string):number|string{returns}类型断言当使用联合类型时,编译器可能不知道,现在我们处理的时候什么类型,而出现报错,因此就需要告诉编译现在处理的是什么。/*两种定义方式:第一种:(<类型>变量)第二种:(变量as类型)*/functionfun(s:number|string):number{//返回参数的长度if((<string>s).length){return(<string>s).length;}else{return(sasnumber).toString().length;}}类型推断当不定义类型是,TypeScript会自动推断类型,如果只是定义,不初始化变量,则类型为anyletn=123;//推断类型为number//n='a';//报错letm;//推断类型为anym=12;m='a';