Document Object Model (DOM) 为文档对象模型, 它使用对象的表示方式来表示对应的文档结构及其中的内容。
下面为一个样例 p 元素在文档中的对象所包含的所有属性。
控制台:
p#dom accessKey: "" align: "" assignedSlot: null attributeStyleMap: StylePropertyMap {size: 0} attributes: NamedNodeMap {0: id, id: id, length: 1} autocapitalize: "" baseURI: "file:///E:/yuanli.html" childElementCount: 0 childNodes: NodeList [text] children: HTMLCollection [] classList: DOMTokenList [value: ""] className: "" clientHeight: 26 clientLeft: 0 clientTop: 0 clientWidth: 713 contentEditable: "inherit" dataset: DOMStringMap {} dir: "" draggable: false firstChild: text firstElementChild: null hidden: false id: "dom" innerHTML: "查看我自己都有哪些属性" innerText: "查看我自己都有哪些属性" inputMode: "" isConnected: true isContentEditable: false lang: "" lastChild: text lastElementChild: null localName: "p" namespaceURI: "http://www.w3.org/1999/xhtml" nextElementSibling: script nextSibling: text nodeName: "P" nodeType: 1 nodeValue: null nonce: "" offsetHeight: 26 offsetLeft: 8 offsetParent: body offsetTop: 20 offsetWidth: 713 onabort: null onauxclick: null onbeforecopy: null onbeforecut: null onbeforepaste: null onblur: null oncancel: null oncanplay: null oncanplaythrough: null onchange: null onclick: null onclose: null oncontextmenu: null oncopy: null oncuechange: null oncut: null ondblclick: null ondrag: null ondragend: null ondragenter: null ondragleave: null ondragover: null ondragstart: null ondrop: null ondurationchange: null onemptied: null onended: null onerror: null onfocus: null onfullscreenchange: null onfullscreenerror: null ongotpointercapture: null oninput: null oninvalid: null onkeydown: null onkeypress: null onkeyup: null onload: null onloadeddata: null onloadedmetadata: null onloadstart: null onlostpointercapture: null onmousedown: null onmouseenter: null onmouseleave: null onmousemove: null onmouseout: null onmouseover: null onmouseup: null onmousewheel: null onpaste: null onpause: null onplay: null onplaying: null onpointercancel: null onpointerdown: null onpointerenter: null onpointerleave: null onpointermove: null onpointerout: null onpointerover: null onpointerup: null onprogress: null onratechange: null onreset: null onresize: null onscroll: null onsearch: null onseeked: null onseeking: null onselect: null onselectionchange: null onselectstart: null onstalled: null onsubmit: null onsuspend: null ontimeupdate: null ontoggle: null onvolumechange: null onwaiting: null onwebkitfullscreenchange: null onwebkitfullscreenerror: null onwheel: null outerHTML: "<p id="dom">查看我自己都有哪些属性</p>" outerText: "查看我自己都有哪些属性" ownerDocument: document parentElement: body parentNode: body prefix: null previousElementSibling: null previousSibling: text scrollHeight: 26 scrollLeft: 0 scrollTop: 0 scrollWidth: 713 shadowRoot: null slot: "" spellcheck: true style: CSSStyleDeclaration {alignContent: "", alignItems: "", alignSelf: "", alignmentBaseline: "", all: "", …} tabIndex: -1 tagName: "P" textContent: "查看我自己都有哪些属性" title: "" translate: true __proto__: HTMLParagraphElement
通过使用 DOM 提供的 API (Application Program Interface) 可以动态的修改节点(node),也就是对 DOM 树的直接操作。 浏览器中通过使用 JavaScript 来实现对于 DOM 树的改动。
DOM 包含
<!DOCTYPE html> <html lang="en"> <head> <title>My title</title> </head> <body> <a href="">My Link</a> <h1>My header</h1> </body> </html>
节点遍历
在元素节点中提取自己所需的节点,并予以操作。
节点类型
常用节点类型
不同节点对应的NodeType类型
此值可以通过 Node.nodeType 来获取。
1元素,2属性,3文本,8注释,9文档等比较常用。还有平常说的元素 其实指的是节点中得元素节点,所以说节点包含元素,节点还包括文本节点、实体节点等。
T之家 2 月 10 日消息,华为技术有限公司的江英杰为大家揭晓了关于开源鸿蒙 OpenHarmony 3.1 Beta 版中的一个关键特性,也就是 ArkUI 开发框架中的 canvas 画布。
据介绍,canvas 是 ArkUI 开发框架里的画布组件,常用于自定义绘制图形。因为其轻量、灵活、高效等优点,被广泛应用于 UI 界面开发中。本期,我们将为大家介绍 ArkUI 开发框架中 canvas 组件的使用。
1.1 什么是 canvas?
IT之家了解到,在 Web 浏览器中,canvas 是一个可自定义 width、height 的矩形画布,画布左上角为坐标原点,以像素为单位,水平向右为 x 轴,垂直向下为 y 轴,画布内所有元素都基于原点进行定位。
如下图所示,我们可以通过 <canvas> 标签,创建了一个 width=1500px,height=900px 的空白画布,我们还需要“画笔”才能绘制图形。canvas 采用轻量的逐像素渲染机制,以 JS 为“画笔”直接控制画布像素,从而实现图形绘制。
1.2 Canvas 的“画笔”
canvas 本身虽不具备绘制能力,但是提供了获取“画笔”的方法。开发者可通过 getContext ('2d') 方法获取 CanvasRenderingContext2D 对象完成 2D 图像绘制,或通过 getContext ('webgl') 方法获取 WebGLRenderingContext 对象完成 3D 图像绘制。
目前,ArkUI 开发框架中的 WebGL1.0 及 WebGL2.0 标准 3D 图形绘制能力正在完善中,所以本文将着重介绍 2D 图像的绘制。如下图所示,是 CanvasRenderingContext2D 对象提供的部分 2D 图像绘制方法,丰富的绘制方法让开发者能高效地绘制出矩形、文本、图片等。
除此之外,开发者还可以通过获取 OffscreenCanvasRenderingContext2D 对象进行离屏绘制,绘制方法同上。当绘制的图形比较复杂时,频繁地删除与重绘会消耗很多性能。
这时,开发者可以根据自身的需求灵活选取离屏渲染的方式,首先通过创建 OffscreenCanvas 对象作为一个缓冲区,然后将内容绘制在 OffscreenCanvas 上,最后再将 OffscreenCanvas 绘制到主画布上,以提高画布性能,确保绘图的质量。
通过上节对 canvas 组件的基本介绍,相信大家对 canvas 组件已经有了一定的认识,下面我们将为大家实际演示 canvas 组件在 ArkUI 开发框架中的使用方法。ArkUI 开发框架参考了 Web 浏览器中 canvas 的设计,并在“类 Web 开发范式”及“声明式开发范式”两种开发范式中进行提供,接下来我们将分别介绍这两种开发范式中 canvas 的绘制方法。
2.1 类 Web 开发范式中 canvas 的绘制方法
类 Web 开发范式,使用 HML 标签文件进行布局搭建、CSS 文件进行样式描述,并通过 JS 语言进行逻辑处理。目前,JS 语言的 canvas 绘图功能已经基本上完善,下面我们将通过两个示例,展示基于 JS 语言的 canvas 组件基础使用方法。
2.1.1 矩形填充
CanvasRenderingContext2D 对象提供了 fillRect (x, y, width, height) 方法,用于绘制一个填充的矩形。如下图所示,在画布内绘制了一个黑色的填充矩形,x 与 y 指定了在 canvas 画布上所绘制的矩形的左上角(相对于原点)的坐标,width 和 height 则设置了矩形的尺寸。
示例代码如下:
//创建一个width=1500px,height=900px的画布<!-- xxx.hml --><div> <canvas ref="canvas" style="width: 1500px; height: 900px; "></canvas></div>
//xxx.jsexport default { onShow() { const el =this.$refs.canvas;//获取2D绘制对象 const ctx = el.getContext('2d');//设置填充为黑色 ctx.fillStyle = '#000000';//设置填充矩形的坐标及尺寸 ctx.fillRect(200, 200, 300, 300); }}
2.1.2 缩放与阴影
CanvasRenderingContext2D 对象提供了 scale (x,y) 方法,参数 x 表示横轴方向上缩放倍数,y 表示纵轴方向上缩放的倍数,值得注意的是缩放过程中定位也会被缩放。如下图所示,是将上个示例中的填充矩形通过 scale (2,1.5) 缩放,并通过 shadowBlur 方法加上阴影后的效果。
示例代码如下:
//xxx.jsexport default { onShow() { const el =this.$refs.canvas; const ctx = el.getContext('2d');//设置绘制阴影的模糊级别 ctx.shadowBlur = 80; ctx.shadowColor = 'rgb(0,0,0)'; ctx.fillStyle = 'rgb(0,0,0)'; // x Scale to 200%,y Scale to 150% ctx.scale(2, 1.5); ctx.fillRect(200, 200, 300, 300); }}
2.2 声明式开发范式中 canvas 的绘制方法
声明式开发范式,采用 TS 语言并进行声明式 UI 语法扩展,从组件、动效和状态管理三个维度提供了 UI 绘制能力,目前已经提供了 canvas 组件绘制能力,但功能仍在完善中。下面我们将通过两个示例展示声明式开发范式中 canvas 组件的基础使用方法。
2.2.1 图片叠加
如下图所示,是三张图片叠加的效果,顶层的图片覆盖了底层的图片。通过依次使用 drawImage (x,y, width, height) 方法设置图片坐标及尺寸,后面绘制的图片自动覆盖原来的图像,从而达到预期效果。
扩展的 TS 语言采用更接近自然语义的编程方式,让开发者可以直观地描述 UI 界面,示例代码如下:
@Entry@Componentstruct IndexCanvas1 { private settings:RenderingContextSettings = new RenderingContextSettings(true);//获取绘图对象 private ctx: RenderingContext = new RenderingContext(this.settings);//列出所要用到的图片 private img:ImageBitmap = new ImageBitmap("common/bg.jpg"); build() { Column() { //创建canvas Canvas(this.ctx) .width(1500) .height(900) .border({color:"blue",width:1,}) .backgroundColor('#ffff00') //开始绘制 .onReady(() => { this.ctx.drawImage( this.img,400,200,540,300); this.ctx.drawImage( this.img,500,300,540,300); this.ctx.drawImage( this.img,600,400,540,300); }) } .width('100%') .height('100%') }}
2.2.2 点击创建线性渐变
如下图所示,是一个线性渐变效果。基于 canvas 扩展了一个 Button 组件,通过点击“Click”按钮,触发 onClick () 方法,并通过调用 createLinearGradient () 方法,绘制出了一个线性渐变色。
示例代码如下:
@Entry@Componentstruct GradientExample { private settings: RenderingContextSettings = new RenderingContextSettings(true); private context: RenderingContext = new RenderingContext(this.settings); private gra: CanvasGradient = new CanvasGradient(); build() { Column({ space: 5 }) {//创建一个画布 Canvas(this.context) .width(1500) .height(900) .backgroundColor('#ffff00 ') Column() {//设置按钮的样式 Button('Click').width(250).height(100).backgroundColor('#000000') .onClick(() => {//创建一个线性渐变色 var grad = this.context.createLinearGradient(600, 200, 400, 750) grad.addColorStop(0.0, 'red'); grad.addColorStop(0.5, 'white'); grad.addColorStop(1.0, 'green'); this.context.fillStyle = grad; this.context.fillRect(400, 200, 550, 550); }) }.alignItems(HorizontalAlign.center) } } }
如下图所示,是一款”飞机大战”小游戏,通过控制战机的移动摧毁敌机。如何使用 ArkUI 开发框架提供的 canvas 组件轻松实现这个经典怀旧的小游戏?实现思路及关键代码如下:
1. 首先列出游戏所用到的图片
private imgList:Array<string> = ["xx.png","xx.png"…];
2. 将图片渲染到 canvas 画布上
let img:ImageBitmap = new ImageBitmap("图片路径(如common/images)/"+this.imgList[数组下标]);this.ctx.drawImage( img,150/* x坐标*/, 150/* y坐标*/, 600/*宽*/, 600/*高*/)
3. 绘制背景图片和战机向下移动的效果
this.ctx.drawImage(this.bg, 0, this.bgY);this.ctx.drawImage(this.bg, 0, this.bgY - 480);this.bgY++ == 480 && (this.bgY = 0);
4. 使用 Math.round 函数随机获取敌机图片并渲染到画布上,并且改变敌机 y 轴坐标,使它向下运动。
Efight = Math.round(Math.random()*7);//前七张为敌机图片。let img:ImageBitmap = new ImageBitmap("common/img"+this.imgList[Efight]);this.ctx.drawImage(img, 0, this.Eheight + 50);//渲染敌机
5. 在页面每隔 120s 出现一排子弹,之后减小或增大(x,y)轴的坐标达到子弹射出效果。
let i= 0;setInterval(()=>{ this.ctx.drawImage(this.bulImg1,image.x – 10 – (i *10) , image.x + (i *10)) this.ctx.drawImage(this.bulimg2, this. bulImg1,image.x – (i *10) , i image.x + (i *10)) this.ctx.drawImage(this.bulimg3, image.x + 10 + (i *10), image.x + (i *10))i ++;},120)
6. 使用 onTouch 方法获取战机移动位置,获取拖动的坐标后重新设置战机的图片坐标,使战机实现拖动效果。
.onTouch((event)=>{ var offsetX = event.localX ||event.touches[0].localX; var offsetY = event.localY ||event.touches[0].localY; var w = this.heroImg[0].width, h = this.heroImg[0].height; var nx = offsetX - w / 2, ny = offsetY - h / 2; nx < 20 - w / 2 ? nx = 20 - w / 2 : nx > (this.windowWidth - w / 2 - 20) ? nx = (this.windowWidth - w / 2 - 20) : 0; ny < 0 ? ny = 0 : ny > (this.windowHeight - h / 2) ? ny = (this.windowHeight – h/2) : 0; this.hero.x = nx; this.hero.y = ny; this.hero.count = 2;
注:本示例引用了部分开源资源,感兴趣的开发者可参考此开源资源,结合文中的实现思路补全代码。(https://github.com/ xs528 / game)
以上就是本期全部内容,期待广大开发者能通过 canvas 组件绘制出精美的图形,更多 canvas 组件的详细使用方法,请参考文档进行学习:
https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-components-canvas-canvas-0000000000621808
架
Angular及Ionic
Angular
概述
what?
一套框架,多种平台 移动端 & 桌面端 在学完了Angular框架的使用之后, 可以使用NativeScript做跨平台开发, 使用ionic做移动端的开发, 使用material或者ngZorro来实现PC端的开发
why?
angular内置的丰富的class ts(typeScript)是es6的超集,强类型约束的语言 支持组件化 更好的可读性和可维护性 更好的社区支持和文档支持 体积更小 强大的cli(command line interface)支持
when?
用在中大型SPA
how?
搭建环境
npm install -g @angular/cli ng new my-app cd my-app ng serve --open
编程方式
angular: ①采用模块来作为容器,封装组件、指令、管道等,基本单位 ②采用组件来封装可复用的视图 ③采用服务来封装可复用的数据和方法 ④采用装饰器和元数据来完成类的具体描述和配置 ⑤采用指令来增强模板的功能
装饰器与元数据的整理
@Component
@Component({ selector:'', templateUrl:'', styleUrls:[] })
@Directive
@Directive({ selector:[''] })
@Pipe
@Pipe({ name:"" })
@Injectable
@Injectable({ providedIn:'root' })
@NgModule
@NgModule({ declarations:[组件类、指令类、管道类], imports:[依赖的模块类] })
@Input @Output
@ViewChild
使用
组件的创建和使用
创建
ng g component demo01
import {Component} from '@angular/core' @Component({ selector:'app-demo01', templateUrl:"", styleUrls:[''] }) export class Demo01Component{}
调用
<app-demo01></app-demo01>
基本语法
{{}}
<any>{{expression}}</any>
内置的指令
*ngFor
*ngIf
()
[]
[(ngModel)]
前提:让当前所属的模块 依赖于FormsModule
自定义的指令
创建
ng g directive test
使用
<any appTest></any>
进阶知识
①获取调用指令的元素
ElementRef
②获取指令调用时所传递的参数
Input
内置的管道
uppercase/lowercase
json
percent
number
slice
currency
。。。
自定义的管道
创建
ng g pipe test
配置
实现管道类中的transform方法
@Pipe({ name:'' }) export class TestPipe implements PipeTransform{ transform(value:any,...args:Array<any>){ //根据管道的需要,实现数据的处理 return 处理后的结果 } }
调用
在组件的模板中 调用自定义管道, 自定义管道和内置的管道用法是一致的
服务
服务:将不同的组件要复用的数据和方法 封装在一个类中 以方便给组件进行复用
实现
创建
ng g service user
注意:@Injectable({ providedIn:'root' }) 等价于在app.module.ts中 直接指定providers
配置
在服务的类中 定义业务所需要用到的 数据和方法
调用
import {UserService} from '****'
constructor(private myService:UserService){}
this.myService.***
组件间通讯
props down
发送
<son myName='123'></son>
子组件接收
import {Input} from '@angular/core'
@Input() myName=""
this.myName
events up
绑定
handleEvent(msg){}
<son (myEvent)="handleEvent($event)"></son>
触发
import {Output,EventEmitter} from '@angular/core'
@Output myEvent=new EventEmitter()
this.myEvent.emit(123)
补充
local variable
适合:父组件在模板中 主动的读取子组件中 的数据或者方法
<son #zhangsan></son> {{zhangsan.**}}
viewChild
适合:父组件在组件类中 操作子组件
用法
import {ViewChild} from '@angular/core'
如果找子,指定了本地变量 @ViewChild('zhangsan') mySon
如果找子,没有指定本地变量 import {Son} from '***' @ViewChild(Son) mySon
service
网络通讯
HttpClient
用法
步骤1:让根模块依赖于HttpClientModule
app.module.ts
import {HttpClientModule} from '@angular/common/http'
@NgModule({ imports:[HttpClientModule] })
步骤2:在组件中调用HttpClient
import {HttpClient} from '@angular/common/http'
constructor(private myHttp:HttpClient){}
this.myHttp.get('').subscribe((result)=>{ //result就是服务器端在本次请求中返回的结果 })
路由模块
基本用法
步骤1:创建一个用来配置路由的自定义的模块 ng g module my-router --routing 步骤2:指定一个盛放组件的容器 <router-outlet></router-outlet> 步骤3: 创建组件 ng g component demo14-login ng g component demo14-register 步骤4:路由词典 路由词典:是一个多个路由对象构成的数组 在新建的模块中my-route.routing.module.ts const routes:Routes=[ {path:"",component:**} ] 步骤5:调用路由词典 在新建的模块中my-route.routing.module.ts @NgModule({ imports:[RouterModule.forRoot(routes)] }) 步骤6:让根模块调用刚配置过的自定义模块 import {MyRouterRoutingModule} from '**' app.module.ts @NgModule({ imports:[MyRouterRoutingModule] }) 步骤7:测试 localhost:4200 localhost:4200/login localhost:4200/register
跳转和传参
跳转
Router
import {Router} from '@angular/router'
constructor(private myRouter:Router){}
this.myRouter.navigateByUrl('')
RouterLink
<any routerLink="/detail"></any>
传参
配置接收方的路由地址 /detail --> /detail/:id
发送参数
this.myRouter.navigateByUrl('detail/10')
<any routerLink="/detail/10"></any>
this.myRouter.navigateByUrl('detail/'+this.id)
<any [routerLink]="'/detail/'+id"></any>
接收参数
import {ActivatedRoute} from '@angular/router'
constructor(private myRoute:ActivatedRoute){}
this.myRoute.params.subscribe((result)=>{ //result.id })
嵌套
比如A,需要根据不同的url嵌套B或者C
实现
给A组件的模板指定一个容器 router-outlet
在A组价的路由对象中,配置子路由
{ path:'a', component:A, children:[ {.....} ] }
守卫
在访问一个路由地址的时候,通过一个守卫来保护 该地址所对应的组件是否可被访问
实现
创建一个服务
ng g service my-guard
在该服务中实现一个CanActivate接口
import {CanActivate} from '@angular/router'
export class MyGuardService implements CanActivate{ canActivate() { return true/false } }
调用路由守卫
import {MyGuardService} from '****' { path:'admin', component:AdminComponent, canActivate:[MyGuardService] }
。。。
Ionic
概述
ionic=angular + 封装的ui组件库+icon+phonegap
使用
页面类的创建和使用
ionic g page demo01
button
ion-button
color primary/secondary/danger/light/dark
large/small
block
clear/outline
icon-left/right
<ion-icon name="home/cog"></ion-icon>
list
基础用法
普通列表
<ion-list> <ion-item>123</ion-item> </ion-list>
icon列表
<ion-list> <ion-item> <ion-icon item-start/end name=''></ion-icon> </ion-item> </ion-list>
头像avatar列表
<ion-list> <ion-item> <ion-avatar> <img src=""/> </ion-avatar> 123 </ion-item> </ion-list>
缩略图thumbnail列表
<ion-list> <ion-item> <ion-thumbnail> <img src=""/> </ion-thumbnail> 123 </ion-item> </ion-list>
侧滑动列表
<ion-list> <ion-item-sliding> <ion-item></ion-item> <ion-item-options> .... </ion-item-options> </ion-item-sliding> </ion-list>
进阶用法
下拉刷新
调用标签
将ionRefresher放在ionContent的第一个子元素的位置
绑定事件
<ion-refresher (ionRefresh)="handleRefresh($event)"></ion-refresher>
指定事件处理函数
handleRefresh(myRefresher){ //异步操作数据完成之后 //结束刷新动作 myRefresher.complete() }
上拉加载
调用标签
将ionInfiniteScroll放在ionContent的最后一个子元素的位置
绑定事件
绑定一个事件ionInfinite
指定事件处理函数
handleInfinite(myInfinite){ //异步操作 //结束 myInfinite.complete() }
自定义布局
基本用法
<ion-grid> <ion-row> <ion-col></ion-col> <ion-col></ion-col> </ion-row> </ion-grid>
常见配置
col-* 设置列的宽度
align-items-start/center/end 一行中所有列的纵向对齐方式
align-self-start/center/end 当前列内容的纵向对齐方式
justify-content-start/center/end 行中列的横向对齐方式
offset-* 设置当前列距离左边列的位移
push/pull-* 将当前列向右推或者左拉的距离
轮播图
<ion-slides autoplay=2000 loop=true effect="cube/flip/slide" speed=3000 pager=true paginationType="bullets/fraction/progress" direction='vertical' > <ion-slide></ion-slide> <ion-slide></ion-slide> <ion-slide></ion-slide> </ion-slides>
card
<ion-card> <ion-card-header></ion-card-header> <ion-card-content></ion-card-content> </ion-card>
窗口
交互窗口有着相似的 使用方法
引入
实例化
创建
显示
loading(一个活动正在进行)
import {LoadingController} from 'ionic-angular'
constructor(private loadingCtrl:LoadingController){}
var myLoading=this.loadingCtrl.create({ spinner:'', content:"", duration:3000 })
myLoading.present() myLoading.dismiss()
actionSheet (从多个选项中让用户选择)
create({ title:'', message:'', buttons:[ { text:'', handler:()=>{}, role:'destructive/cancel' } ] })
toast(显示操作的结果)
create({ message:"", position:'top/middle/bottom', duration:1500, showCloseButton:true, closeButtonText:'', ... })
alert (警告、确认、输入提示)
create({ title:'', message:'', inputs:[ {type:'password'} ], buttons:[ {text:'',handler:(data)=>{ //data是一个数组 data[0] 获取第0个输入框的值 }} ] })
modal (自定义窗口)
create(Demo22Page)
进阶知识
在模态窗内部如何关闭
import {ViewController} from 'ionic-angular'
constructor(private viewCtrl:ViewController){}
this.viewCtrl.dismiss()
关闭时完成参数的传递和接收
this.viewCtrl.dismiss(1000)
var myModal=this.modelCtrl.create(**) myModal.onDidDismiss((data)=>{ //data就是传来的数据 })
tabs
标签页栏,实现底部的导航工具条
用法
在页面类中 引入每一个tab被选中时要 用到的页面类
import {SettingsPage} from 'ionic-angular'
在当前的页面类中 定义变量保存上一步引入的页面类(目的是到模板中可以使用)
tabSettings=SettingsPage
<ion-tabs> <ion-tab tabTitle="" tabIcon="" [root]=tabSettings></ion-tab> <ion-tab></ion-tab> <ion-tab></ion-tab> </ion-tabs>
导航
跳转
方案1
import {NavController} from 'ionic-angular'
import {DetailPage} from '**'
constructor(private navCtrl:NavController){}
this.navCtrl.push(DetailPage)
方案2
import {DetailPage} from '**'
detail=DetailPage
<any [navPush]="detail"></any>
传参
发送
this.navCtrl.push(DetailPage,{id:10})
<any [navPush]="detail" [navParams]="{id:20}"></any>
接收
import {NavParams} from 'ionic-angular'
constructor(private navParams:NavParams){}
this.navParams.get('id')
支持滚动的容器
<ion-scroll scrollX=true scrollY=true></ion-scroll>
表单
通过ionList和ionItem来管理表单
实现
<ion-list> <ion-item> <ion-label></ion-label> <ion-input></ion-input> <ion-toggle></ion-toggle> <ion-checkbox></ion-checkbox> <ion-radio></ion-radio> .... </ion-item> </ion-list>
生命周期
会被执行很多次
守卫
ionViewCanEnter
ionViewCanLeave
普通
ionViewWillEnter
ionViewDidEnter
ionViewWillLeave
执行一次
ionViewDidLoad
ionViewWillUnload
React及ReactNative
ReactJS
概述
what?是一个以组件化的方式来构建ui层的js库
when? 数据操作比较频繁的场景
why?
历史背景
浏览器性能瓶颈
VDOM
开发和维护
单向数据流
how?
引入3个js文件
cli
npx create-react-app my-app cd my-app npm start
demo01
<script src="js/react.js"></script> <script src="js/react-dom.js"></script> <script src="js/browser.min.js"></script>
<div id="example"></div>
<script type='text/babel'></script>
ReactDOM.render( <h1>123</h1>, document.getElementById('example') )
核心思想
everything is component
核心概念
jsx
jsx需要通过babel转换为浏览器能识别的语法, 是reactjs开发推荐使用,不强制使用
两个基本语法
<
首字母是小写--》html
首字母是大写--》组件
{
执行表达式
优缺点
优点
方便的封装组件
提高代码的可读性
缺点
现有的html标签有些属性不能用 class-->className for-->htmlFor
将数据和视图合在一起,增加代码的耦合度
component
组件:可被反复使用的,带有特定功能的视图
创建和使用
创建
var MyComponent=React.createClass({ render(){ return ** } })
调用
<MyComponent></MyComponent>
注意事项
有开始有结束
全驼峰
放在一个顶层标签
render方法return时,第一个标签不要直接换行
props
知识点1
props down(父--》子)
实现
<Son myName='zhangsan'></Son>
this.props.myName
知识点2
子--》父
实现
save(msg){}
<Son myFunc={this.save}></Son>
this.props.myFunc(123)
知识点3
this.props.children 获取 当前组件作为标签去使用时,内部的子标签
React.Children.map(this.props.children,(child)=>{})
state
管理数据
初始化
getInitialState:function(){ return {count:1,age:10} }
读
this.state.count
写
this.setState({count:2})
this.setState({count:2},()=>{ //状态修改成功之后的回调函数 })
绑定
将状态中的值 给视图去使用, 状态发生了变化,视图就会更新 比如: <p>{this.state.count}</p> <h2 style={{opacity:this.state.opacityValue}}></h2>
ref
reference 引用 参考 参照
ref是可以让在父组件中直接找到子组件的实例, 或者找到一个标签
实现
<any ref="mySon"></any>
this.refs.mySon.***
生命周期
react中组件的生命周期分为3个阶段
阶段
mount
componentWillMount
componentDidMount
update
componentWillUpdate
componentDidUpdate
componentWillReceiveProps
unmount
componentWillUnmount
注意事项
①通过ref寻找元素或者组件,必须等到 componentDidMount或者之后
②componentWill/DidUpdate(是在props或者state中值变化时), 中不允许执行状态的修改操作 会陷入死循环
③componentWillRecevieProps是允许修改状态的
④不允许修改props对象中的值(read only)
受控表单元素
前提:在react中不是所有的表单元素都是受控表单元素
只有指定了value/checked/selected等属性的表单元素才需要特殊处理
处理
方案1:defaultValue
方案2:
基于状态具有绑定的特性
步骤1:初始化状态
getInitialState:function(){ return {myAddr:'bj'} }
步骤2:读
<input value={this.state.myAddr}/>
步骤3:绑定事件,在事件 处理函数中写状态
handleChange(e){ this.setState({myAddr:e.target.value}) }
<input onChange={this.handleChange} value={this.state.myAddr}/>
进阶知识
1、事件处理函数自定义传值?
<button onClick={()=>this.handleClick(123)}></button>
2、循环
{ this.state.list.map((value,index)=>{ return <li key={index}></li> }) }
3、条件判断
判断条件比较简单: 逻辑与
{ expression && <标签></标签> }
判断条件相对复杂: 方法的封装和调用
isShow(){ //执行运算,得到判断条件需要的数据 //判断,如果符合条件,返回要显示的元素否则不显示 if(){ return <标签></标签> } }
{ this.isShow() }
ReactNative
概述
what?
构建原生app的,由fb所推出的,可以使用react和js 进行编程的框架
how?
搭建环境
npm install -g expo-cli expo init AwesomeProject cd AwesomeProject npm start
如何编程
使用react中的组件化的核心思想,以及核心概念; 来完成rn中封装的组件的调用,构建属于自己的组件(页面) 借助第三方的工具react-navigation来完成路由和导航, 实现一个完成的app
基础
组件化
创建
import React,{Component} from 'react' import {Text} from 'react-native' export default class Demo01Component extends Component{ render(){ return <Text></Text> } }
使用
import Demo01Component from '***'
<Demo01Component></Demo01Component>
AppRegistry.registerComponent("myapp",()=>Demo01Component)
通过路由访问
注意
①不允许调用html标签 ②组件先引入 再使用 ③类的名称要遵循全驼峰 ④类的导出方式的区别 export default --> 引入时,不需要加花括号;类的名称可以和导出不一致 export class --> 引入时,必须加上花括号,类的名字必须和导出时保持一致
样式
目的:在rn中是支持常见的html的style属性
import {StyleSheet} from 'react-native'
const myStyles=StyleSheet.create({ myText:{ fontSize:20, color:'red' } })
<Text style={myStyles.myText}></Text>
数据
初始化
constructor(){ super() this.state={count:0} }
读
this.state.count
写
this.setState({count:10})
自定义布局
flexDirection
justifyContent
alignItems
网络通讯
fetch("") .then((response)=>response.json()) .then((result)=>{ //result就是服务器端数据反序列化之后的结果 })
常见组件
容器
View
实现一个容器
步骤
import {View} from 'react-native'
<View> 嵌套一些其他的标签 </View>
ScrollView
实现一个支持滚动的容器
使用
import {ScrollView} from 'react-native'
<ScrollView> ... </ScrollView>
实现页脚的技巧
<View style={{flex:1}}> <ScrollView></ScrollView> <View> 页脚中的东西 </View> </View>
FlatList
高性能的列表
步骤
import {FlatList} from 'react-native'
//有参数有返回值的 showItem(info){ //info是一个对象,item属性对应的数组的临时变量, index属性对应的当前遍历时下标 return <渲染的列表项></渲染的列表项> }
<FlatList renderItem={this.showItem} data={[100,200,300]}></FlatList>
TouchableOpacity
实现一个容器,放在此容器中的组件 支持点按时 透明度变化效果
使用
import {TouchableOpacity} from 'react-native'
<TouchableOpacity onPress={}> <Text>123</Text> </TouchableOpacity>
Text
显示一段内容
步骤
import {Text} from 'react-native'
<Text>渲染的内容</Text>
Switch
滑动开关(默认的受控组件)
使用
import {Switch} from 'react-native'
constructor(){ super(); this.state={myValue:true} }
handleValueChange(value){ this.setState({myValue:value}) }
<Switch value={this.state.myValue} onValueChange={this.handleValueChange}></Switch>
TextInput
文本输入框
使用
import {TextInput} from 'react-native'
handleChangeText(msg){ //msg就是输入框的数据 }
<TextInput placeholder="" secureTextEntry={true} onChangeText={this.handleChangeText}></TextInput>
Button
按钮
步骤
import {Button} from 'react-native'
handlePress(){ }
<Button title="clickMe" onPress={this.handlePress}></Button>
Image
显示图片
使用
import {Image} from 'react-native'
//本地 <Image source={require("加载的图片路径")}></Image> //网络资源 <Image source={{uri:""}}></Image>
注意事项
本地资源图片路径不允许做运算
网络资源图片 要指定宽高
ActivityIndicator
实现一个加载中的指示器
使用
import {ActivityIndicator} from 'react-native'
<ActivityIndicator size="" color=""></ActivityIndicator>
Python及Django
Python
学习目标
目标: ①熟练掌握python基本语法、常见的标准库的使用、面向对象、异常处理 ②第三方的库django:ORM、模板语法、基本用法。。 ③采用python和django框架编写出后台的api
概述
Python是一门编程语言, 用在很多领域中,比如web、GUI、科学分析和数据处理、系统集成 (爬虫、系统运维、人工智能、数据分析。。)
常识
注释
行注释: #注释内容
块注释: """ 块注释内容 """
输入输出
输入:input('提示信息')
输出:print("信息1","信息2")
缩进
python是通过缩进和冒号来组织一个代码块
进入到python的命令解析模式
py/python
exit() quit()
查看帮助信息
help('keywords')
help('modules')
help('print')
....
基本使用
变量的定义、调用、释放
定义
a=3
调用
print(a)
释放
del a
常见数据类型以及api
number
int
a=10
float
a=10.2
bool
a=True/False
complex
a=2+3j
string
定义
myName='zhangsan'
myName="zhangsan"
myName='''zhangsan'''
myName="""zhangsan"""
拼接
myName+myName
重复输出
myName*3
list
定义一个数组
myList=[10,20,30]
数组基本操作
增
myList.append(11)
myList.insert(0,1)
删
myList.pop() 删除最后一个元素
myList.pop(2) 删除指定下标为2的元素
改
myList[0]=100
查
myList[0]
myList[2]
myList[-2]
补充
len(myList)
max(myList)
min(myList)
myList.sort() myList.sort(reverse=True)
myList.reverse()
tuple(带了枷锁的数组)
元组是带了枷锁的数组,不支持修改元组中的数据
定义
myTuple=(100,200,300)
myTuple=tuple([100,200,300])
myTuple=(1,)
读取元组的中
myTule[0]
set(不会重复的元素)
存储是不会重复的数据集合
定义
mySet=set([100,200,300,300])
mySet.add()
mySet.remove()
dict
存储是一些键值对,查找和插入的速度比较快
字典的常用操作
myDict={"uname":"zhangsan",'upwd':123456}
myDict.get('uname')
myDict['uname']='johnReese'
myDict.keys()
myDict.values()
myDict.items()
数据类型的转换
显示类型转换
list
list(myTuple)
set
set(myList)
tuple
tuple(myList)
int
int('10')
float
float('10.3')
str
str(10)
异常处理
基本用法
try: print(myName) except NameError: print('异常处理流程') finally: 执行最终一定要执行的代码
进阶用法
捕获多个错误
try: print(myName) except NameError: print('异常处理流程1') except ValueError: print('异常处理流程2') finally: 执行最终一定要执行的代码
try: print(myName) except (NameError,ValueError): print('异常处理流程1') finally: 执行最终一定要执行的代码
try: print(myName) except Exception:#捕获所有的错误 print('异常处理流程1') finally: 执行最终一定要执行的代码
手工触发错误并自定义错误消息内容
try: raise(ValueError('错误消息1')) except ValueError as msg: print(msg) finally: 执行最终一定要执行的代码
支持的运算符
算术运算
+-*/ ** % //
关系运算
> >=< <===!=
逻辑运算
and
两者为真,结果是真
or
一个为真,结果为真
not
取反
位运算
& | ~ ^ << >>
赋值运算
+=-+ [num1,num2,num3]=[1,2,3] ... 不支持自增 自减
身份运算
in /not in
id
is
控制语句
条件判断
if expression: pass else: pass
if expression1: pass elif expression2: pass elif expression3: pass else: pass
循环控制
for
for tmp in myList: tmp#遍历数组时的临时变量
range(start,stop,step)
range(5)
0 1 2 3 4
range(5,8)
5 6 7
range(1,8,3)
1 4 7
for index in range(0,len(myList)): index#下标 myList[index]#得到指定下标的元素
while
while expression: pass
continue
直接进入到下一次循环
break
跳出循环
方法
基础知识
创建一个方法 def myFunc(): 方法体
调用方法 myFunc()
参数
参数的值传递和引用传递
# 值传递:修改参数,原始数据不受影响 number/string/tuple # 引用传递:修改参数,原始数据也会变化 list/set/dict
关键字参数
关键字参数,在方法的调用过程中, 是可以通过keyValue指定关键字参数,调整参数顺序
示例
def myFunc(arg1,arg2): print("arg1 is ",arg1) print("arg2 is ",arg2)
myFunc(10,20) myFunc(arg2=30,arg1=15) myFunc(16,arg2=20)
可变长参数
写法1
# 可变长参数:是以元组中的数据进行存储的 def test(*myArgs): print(myArgs) test() test(1) test(1,2,3)
写法2
# 可变长参数的第二种写法: def testFunc(**myArgs): print(myArgs,type(myArgs)) # testFunc(1,2,3) 会报错的 testFunc(a=1,b=2,c=3)
默认值参数
# 默认值参数:调用方法,如果传参,以实际参数为准, 如果没有传参,以默认值为调用的数据 def myFunc(arg1,arg2=20): print(arg1,arg2) myFunc(10) myFunc(10,30)
作用域
分类
Local
函数内部的变量
Embedded
被嵌套的函数内部的变量
Global
定义在模块中的变量
使用注意事项
函数内部 修改全局变量,必须 通过Global引入全局变量才可以
num=10 def myFunc(): global num num+=1
嵌套函数内部,修改外层函数变量,必须 通过nonlocal引入才可以
def outer(): count=0 def inner(): nonlocal count count+=1
闭包
允许在一个函数内部 ,嵌套一个函数
①外层函数在调用,创建外层函数作用域对象 ②内层函数在创建时,通过自己__closure__属性 引用外层作用域对象 在外层函数执行之后,无法释放,形成一个闭包的结果(变量依然保留在内存中,可重用)
模块与包
包:一个文件夹,里头可以包含多个py文件
创建
utility/data.py
调用
import utility.data import utility.data as m1
from utility.data import * from utility.data import test
模块:一个py文件
创建
创建一个py文件
调用
import module1 import module1 as m1
from module1 import test from module1 import *
面向对象编程
封装
创建一个类
class Animal: #定义构造函数 def __init__(self,name,age): self.uname=name self.__myAge=age #定义其它方法 def eat(self): pass
调用
a1=Animal() a1.eat()
继承
class Cat(Animal): pass
多态
在python方法 是可以通过重写来实现在不同的情况下,不同的效果
标准库
time
time.localtime
time.strftime
random
random.choice(range(0,100))
math
math.ceil()
math.floor()
math.fabs()
os
os.environ
os.path.exists
os.path.isFile
...
...
第三方库
mysql-connector
功能:mysql在python下的驱动程序
使用步骤:
①安装、引入
pip install mysql-connector
import mysql.connector as conn
②连接指定的数据库服务器
myConnection=conn.connect(host="localhost",user="root",passwd="",database="xz")
③创建一个游标对象
myCursor=myConnection.cursor(dictionary=True)
④执行sql
myCursor.execute("select * from xz_user")
⑤获取执行的结果
myCursor.fetchall() myCursor.lastrowid myCursor.rowcount
数据库连接池
①引入
import mysql.connector.pooling as pooling
②创建一个连接池
config={ "host":"localhost", "user":"root", "passwd":"", "database":"xz" }
myPool=pooling.MySQLConnectionPool(pool_size=5,**config)
③获取一个连接
myConnection=myPool.get_connection()
....
Django
flask
pyqt
tornado
....
Django
概述:
django是一个基于python的全栈类框架, 05年发布,早期可以用做新闻门户; 提供了强大的后台管理系统,实现网站的前后端的所有东西
django
路由系统的搭建
router
接收请求并返回执行的消息
api
ORM
处理后端数据
模板语法
处理前端页面
基础知识
project和app的区分
一个django的project是一个大的站点, 此网站可以包含很多模块,将模块称之为一个django的app
project的准备
django-admin startproject netease
cd netease py manage.py runserver (默认启动开发服务器端口8000)
app的准备
django-admin startapp military
django-admin startapp history
py manage.py startapp fashion
后台管理系统
默认localhost:8000/admin可以访问,但是 登录不了
py mange.py makemigrations
py manage.py migrate
py manage.py createsuperuser
密码的输入是不可见的
路由系统
路由系统就是为了搭建视图和url的映射关系
①创建视图
举例当前有个app:military
找到military/views.py
from django.http import HttpResponse
def handleIndex(request): return HttpResponse("这是首页")
②配置路由
需求:localhost:8000/military/index
实现步骤
配置app内部路由
新建一个文件 military/urls.py
from django.urls import path from . import views
urlpatterns=[ path("index",views.handleIndex) ]
配置project的路由
netease/urls.py
from django.urls import path,include
urlpatterns=[ path("military",include('military.urls')) ]
参数处理
get
#localhost:8000/demo01/detail?id=2 def handleDetail(request): request.GET['id']
post
关闭CSRF(403)
settings/middleware 注释'django.middleware.csrf.CsrfViewMiddleware'
接收
def handleRegister(request): myData=request.body.decode('utf-8') myDic=json.loads(myData) myDic.get()
跨域
安装
pip install django-cors-headers
注册
settings.py中的INSTALLED_APPS:corsheaders
settings.py中的MIDDLWARE的数组添加: corsheaders.middleware.CorsMiddleware
配置
CORS_ORIGIN_WHITELIST=( "http://localhost:8080" )
ORM
Object Relational Mapping 对象关系映射 直接操作对象中的方法,来实现编写sql进行数据操作的同等效果
orm在django的实现方式
举例:当前一个app:military
步骤1:app要注册
netease/settings.py INSTALLED_APPS
步骤2:创建模型类
military/models.py
class Weapon(models.Model): title=models.CharField(max_length=200) #AutoField IntegerField BooleanField DateField
步骤3:将模型类注册 到后台管理系统
military/admin.py
from .models import Weapon
admin.site.register(Weapon)
步骤4:激活数据模型
py manage.py makemigrations
py manage.py migrate
ORM在处理CRUD:
https://docs.djangoproject.com/zh-hans/2.1/ref/models/querysets/
增
from .models import Weapon
方式1
w1=Weapon(title="AK47")
w1.save()
方式2
w1=Weapon()
w.title="AK47"
w1.save()
删
Weapon.objects.all().delete()
Weapon.objects.get(title="AK47").delete()
改
w1=Weapon.objects.get(title="AK47")
w1.title="M16"
w1.save()
查
Weapon.objects.all() Weapon.objects.values("title") Weapon.objects.filter() Weapon.objects.get()
模板
模板层提供了一个对设计者友好的语法 用于渲染向用户呈现的信息
模板的api
创建
在app中 创建一个文件夹templates, 在此文件夹中创建一个和当前app名字一样的文件夹, 在此文件夹中就可以创建模板了 templates/news/newsList.html
加载
from django.template import loader
tpl=loader.get_template("news/newsList.html")
渲染
tpl.render({myId:10})
模板所支持的语法
双花括号
{{myId}}
循环
{% for tmp in myList %} <li>{{tmp}}</li> {% endfor %}
条件
{% if myId > 10 %} <p>id是大于10的</p> {% else %} <p>id是小于等于10的</p> {% endif %}
*请认真填写需求信息,我们会在24小时内与您取得联系。