Typescript教程_Typescript视频教程 ts入门实战视频教程-2021年更新 包含Vue3+Ts
https://www.bilibili.com/video/BV1yt411e7xV?from=search&seid=9050004695350176192
https://www.itying.com/category-85-b0.html
https://blog.csdn.net/z591391960/article/details/105667767
npm install -g yarn
yarn -v
自动编译ts方法二
2.数据类型
布尔类型(boolean)
数字类型(number)
字符串类型(string)
数组类型(array)
元组类型(tuple)
枚举类型(enum)
任意类型(any)
null和undefined
void类型
never类型
let arr:number[]=[3,3,3]
泛型
let arr:Array
元组类型(tuple)
let arr:[string,number,boolean]=['ts',33,true]
enum 枚举名{
标识符[=整型常数],
标识符[=整型常数],
....
标识符[=整型常数],
};
3.----------------------------------------
var num:any=1123;
num='str';
num=true;
console.log(num)
let num:undefined;
console.log(num)
var num:number | undefined;
console.log(num)
var num:null;
num=null;
var num:number | undefined | null;
num=333;
console.log(num)
void类型:typescript中的void表示没有任何类型,一般用于定义方法的时候方法役有返回值
function fn():void{
}
never类型:是其他类型(包括null和undefined)的子类型,代表从不会出现的值。
这意味着声明never的变量只能被never类型所赋值。
var a:never;
//a=33;//错误
a=(()=>{
throw new Error('错误')
})()
let arr:any[]=['333',33,true]
4.函数
let fun=function():number{
return 33;
}
function getInfo(name:string,age?:number):string{//?可选参数 可以不传
if(age){
return ${name}----${age}
}else{
return ${name}----保密
}
}
// console.log(getInfo("koo",55))
console.log(getInfo("koo"))
//默认参数
function getInfo(name:string,age:number=20):string{
if(age){
return ${name}----${age}
}else{
return ${name}----保密
}
}
console.log(getInfo("koo"))
/三点运算符接受新参传过来的值
function sum(...result:number[]):number{
var sum=0;
for(var i=0;i<result.length;i++){
sum+=result[i]
}
return sum
}
alert(sum(3,3,4))
/ts中的重载
function getInfo(name:string):string;
function getInfo(age:number):string;
function getInfo(str:any):any{
if(typeof str==='string'){
return 'name:'+str;
}else{
return 'age:'+str;
}
}
alert(getInfo('koo'))
箭头函数 箭头函数里面的this指向上下文
setTimeout(() => {
alert('44')
}, 1000);
5.es5类和静态方法,继承
function Person(){
this.name='koo';
this.age=33;
this.run=function(){alert(this.name;)}
}
var p=new Person();
alert(p.name)
p.run()
原型链上面的属性会被多个实例共享 构道函数不会
Person.prototype.sex='男';
Person.prototype.work=function(){alert(this.name);}
p.work();
web类 维承Person类 原型链+对象冒充的组合继承模式
function Web(){
Person.call(this);//对象冒充实现继承
}
var w=new Web();
w.run();
w.work();//对象冒充可以继承构造函数里面的属性和方法 但是没法继承原型链上面的属性和方法
function Web(){}
Web.prototype=new Person();//原型链实现继承
var w=new Web();
w.run()
w.work()
6.es6类和静态方法,继承 修饰符
constructor
class Person{
name:string; 属性 前面省略了public关键词
constructor(n:string){ 构造函数 实例化类的时候触发的方法
this.name=n;
}
run():void{
alert(this.name)
}
}
let p=new Person('koo');
p.run()
class Person{
name:string;
constructor(name:string){
this.name=name;
}
getName():string{
return this.name;
}
setName(name:string):void{
this.name=name;
}
}
let p=new Person('koo');
alert(p.getName())
p.setName('john')
alert(p.getName())
ts中实现继承
class Person{
public name:string;
static age:number; static属性
constructor(name:string){
this.name=name;
}
run():string{ //实例方法
return ${this.name}在运动
;
}
static print(){
alert(静态方法${Perosn.age}
) 里面没法直接调用类里面的属性 要设置static属性调用
}
}
Person.print();//静态方法调用
// let p=new Person('koo')
// alert(p.run())
class Web extends Person{
constructor(name:string){
super(name) 初始化父类的构造函数
}
work(){
alert(${this.name}在工作
)
}
}
let w=new Web('john');
alert(w.run())
w.work()
类里面的修饰符 typescript里面定义属性的时候给我们提供了三种修饰符
public 公有 在类里面、子类、类外面都可以访问
protected 保护类型 在类里面、子类里面可以访问,在类外部没法访问
private 私有 在类里面可以访问,子类、类外部都没法访问
属性如果不加修饰符默认就是公有(public)
7.类中的静态属性 静态方法 抽象类 多态
function Person(){
this.run1=function(){}
}
Person.name='33' 静态属性
Person.run2=function(){}//静态方法
var p=new Person()
Person.run2;//静态方法的调用
'typescript中的抽象类:它是提供其他类继承的基类,不能直接被实例化
用abstract关键字定义抽象英和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。
abstract
abstract抽象方法只能放在抽象类里面
abstract class Animal {
public name:string;
constructor(name:string){
this.name=name;
}
abstract eat():any;
}
class Dog extends Animal{
constructor(name:any){
super(name)
}
// 抽象类的子类必须实现抽象类里面的抽象方法
eat(){
console.log(${this.name}在吃粮食
)
}
}
let d=new Dog('小狗')
d.eat()
8.接口的用途 属性类型接口
接口的作用,在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用.
口定义了某一批共所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要.typescrip中的接口类似于java,同时还增加了更灵活的接口类型,包括属性、函数、可索引和类等
属性类接口
函数类型接口
可索引接口
类类型接口
接口扩展
interface FullName{
firstName:string;
secondName:string;
}
function printName(name:FullName){
console.log(${name.firstName}------${name.secondName}
)
}
// printName({firstName:'john',secondName:'koo'})
var obj={ 传入的参数必须包含 参数的顺序可以不一样
age:26,
firstName:'joo',
secondName:'koo'
}
printName(obj)
// printName({
// age:26, 错误报错
// firstName:'joo',
// secondName:'koo'
// })
可选参数
interface FullName{
firstName:string;
secondName?:string;
}
function printName(name:FullName){
console.log(${name}
)
}
printName({
firstName:'koo'
})
9.属性类型接口 封装ts-ajax
interface Config{
type:string;
url:string;
data?:string;
dataType:string;
}
function ajax(config:Config){
var xhr=new XMLHttpRequest();
xhr.open(config.type,config.url,true)
xhr.send(config.data)
xhr.onreadystatechange=function(){
if (xhr.readyState&&xhr.status200) {
console.log('成功')
if (config.dataType'json') {
console.log(JSON.parse(xhr.responseText))
} else {
console.log(xhr.responseText)
}
}
}
}
ajax({
type:'get',
data:'name=zhangsan',
url:'http://www.baidu.com',
dataType:'json',
})
10.函数类型接口 加密方法约束
interface encrypt{
(key:string,value:string):string;
}
var md5:encrypt=function(key:string,value:string):string{
//模拟操作
return key+value;
}
console.log(md5('koo','john'))
11.可索引接口 类类型接口
可索引接口:数组、对象的约束(不常用)
数组约束
interface UserArr{
[index:number]:string
}
var arr:UserArr=['ff','ffff']
console.log(arr[0])
对象的约束
interface UserObj{
[index:string]:string
}
var arr:UserObj={name:'zhangsan'}
,类类型接口:对类的约束 和 抽象类有点相似
implements
interface person{
sayHi:()=>void
sing:(name:string)=>void
sum:(num1:number,num2:number)=>number
}
interface Animal{
name:string;
// eat:(str:string)=>void
eat(str:string):void;
}
class Dog implements Animal{
name:string;
constructor(name:string){
this.name=name;
}
eat(food){
console.log(this.name+food)
}
}
let d=new Dog('小黑')
d.eat('粮食')
12.接口扩展 接口的继承
{
interface Animal{
eat():void;
}
interface Person extends Animal{
work():void;
}
class Programmer {
public name:string;
constructor(name:string) {
this.name=name;
}
coding(code:string){
console.log(this.name+code)
}
}
class Web extends Programmer implements Person{
constructor(name:string){
super(name)
}
eat(){
console.log(this.name+'喜欢吃馒头')
}
work(){
console.log(this.name+'写代码')
}
}
let w=new Web('koo')
w.eat()
w.work()
w.coding('写ts代码')
}
13.泛型 泛型变量 泛型类
泛型,软件工程中,我们不仅要创建一致的定义良好的APT,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
在像CH和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据,这样用户就可以以自己的数据类型来使用组件。
通俗理解:泛型就是解决类接口方法的复用性、以及对不特定数据类型的支持
泛型,可以支持不特定的数据类型 要求,传入的参数和返回的参数一直
T表示泛型,具体什么类型是调用这个方法的时候决定的
也可以是任意字母
function fn
return value;
}
fn
泛型类,比如有个最小堆算法,需要同时支持返回数字和字符串两种类型,通过类的泛型来实现
class MinClas
public list:T[]=[];
add(value:T):void{
this.list.push(value)
}
min():T{
var minNum=this.list[0]
for (let i = 0; i < this.list.length; i++) {
if (minNum>this.list[i]) {
minNum=this.list[i]
}
}
return minNum
}
}
let m1=new MinClas
m1.add(2)
m1.add(33)
alert(m1.min())
14.泛型接口 泛型类接口
1.
interface ConfigFn{
}
var getData:ConfigFn=function
return value;
}
getData
interface ConfigFn
(value:T):T;
}
function getData
return value;
}
var myGetData:ConfigFn
myGetData('ffff')
15.泛型类 把类作为参数类型的泛型类
class User {
username:string | undefined;
password:string | undefined;
}
class MysqlDb {
add(user:User):boolean{
console.log(user)
return true;
}
}
var u=new User();
u.username='koo'
u.password='123456'
var Db=new MysqlDb();
Db.add(u)
class User {
username:string | undefined;
password:string | undefined;
}
class MysqlDb
add(user:T):boolean{
console.log(user)
return true;
}
}
var u=new User();
u.username='koo'
u.password='123456'
var Db=new MysqlDb
// Db.add('fff') 错误
Db.add(u)
16.综合应用
TypeScript类型、接口、类、泛型
综合使用--TypeScript封装统一操作
Mysql Mongodb Mssql的底层库
注意:更实现泛型接口这个类也应该是一个泛型类
{
interface DBI
add(info:T):boolean;
update(info:T,id:number):boolean;
delete(id:number):boolean;
get(id:number):any[];
}
class MysqlDb
add(info: T): boolean {
console.log(info)
return true;
}
update(info: T, id: number): boolean {
throw new Error("Method not implemented.");
}
delete(id: number): boolean {
throw new Error("Method not implemented.");
}
get(id: number): any[] {
var list=[
{
title:'xxxx',
desc:'xxxxxxxxxxxxxx'
},
{
title:'xxxx',
desc:'xxxxxxxxxxxxxx'
}
]
return list;
}
}
class MsSqlDb
constructor(){
console.log('数据库建立连接')
}
add(info: T): boolean {
throw new Error("Method not implemented.");
}
update(info: T, id: number): boolean {
throw new Error("Method not implemented.");
}
delete(id: number): boolean {
throw new Error("Method not implemented.");
}
get(id: number): any[] {
throw new Error("Method not implemented.");
}
}
class User{
username:string|undefined;
password:string|undefined;
}
var u=new User()
u.username='koo'
u.password='123345'
var oMysql=new MysqlDb
oMysql.add(u)
var data=oMysql.get(4);
console.log(data)
}
17.模块 模块化封装
模块的的概念(官方):关于术语的一点说明:请务必注意一点,Typescript 1.5里术语名已经发生了变化,"内部模块"现在称做"命名空间"
“外部模块“现在则简称为"模块”模块在其自身的作用城里执行,而不是在全局作用城里,立意味着定义在一个模块里的变量,函t,英等等在模块外部是不可见的,除非你明确地使用export形式之一导出它们.
相反,如果想使用其它模块导出的变量,因数,类,按口等的时候,你必须要导人它们,可以使用1mport形式之一。
模块的概念(自己理解)
我们可以把一些公共的功能单独抽离成一个文件作为一个模块。
模块里面的变量函数类等默认是私有的,如果我们硬在外部访问模块里面的数据(变量、函数、类),我们需要通过export暴露模块里面的数据(变量、函数、类.….)。
暴露后我们通过import引入模块就可以使用模块里面暴露的数据(变量、函数、类..)。
node test.js
db.ts
{
export var dbUrl='xxxxxxxxxxx'
export function getData():any[]{
console.log('获取数据库的数据')
return [
{
title:'xxxxxx'
},
{
title:'xxxxxxxxxx'
}
]
}
export function save(){
console.log('保存数据成功')
}
}
{
var dbUrl='xxxxxxxxxxx'
function getData():any[]{
console.log('获取数据库的数据')
return [
{
title:'xxxxxx'
},
{
title:'xxxxxxxxxx'
}
]
}
function save(){
console.log('保存数据成功')
}
export {dbUrl,getData,save}
}
test.ts
{
import {dbUrl, getData,save } from "./modules/db";
getData()
save()
console.log(dbUrl)
}
import {dbUrl, getData as get,save } from "./modules/db";
//as 起别名
get()
save()
console.log(dbUrl)
每个模块都可以有一个default导出,默认导出使用default关键字标记,并且一个被块只能够有一个default导出,需要使用一种特殊的导入形
default
{
var dbUrl='xxxxxxxxxxx'
function getData():any[]{
console.log('获取数据库的数据')
return [
{
title:'xxxxxx'
},
{
title:'xxxxxxxxxx'
}
]
}
function save(){
console.log('保存数据成功')
}
//default 一个模块只能出现一次
export default getData;
}
import getData from "./modules/db";
getData()
暴露类
export class lei{
}
import {lei} from './modules/db'
var u=new lei()
18.命名空间 命名空间块化
命名空间:在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数、类、接口等放置到命名空间内同Java的包、.Net的命名空间一样,Typeseript的命名空间可以将代码包裹起来,只对外暴露需要在外部访问的对象。命名空间内的对象通过export
命名空间和模块的区别:命名空间:内部模块,主要用于组织代码,避免命名冲突。
模块:ts的外部模块的简称,侧重代码的复用,一个模块里可能会有多个命名空间。
namespace A{
interface Animal
export class Dog{}
}
namespace B{
interface Animal
}
内容可以同样
var d=new A.Dog('狗')
d.eat()
export namespace A{
export class Dog{
eat(){
console.log('fffff')
}
}
}
import {A} from './modules/a'
let d=new A.Dog()
d.eat()
官网
www.typescriptlang.org/docs/handbook/namespaces.html
19.装饰器定义 类装饰器 属性装饰器 装饰器工厂
装饰器:装饰器是一种特殊类型的声明,它能够被附力到洪声明,方法,属性或参数上,可以修改类的行为。
通俗的讲装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。
常见的装饰器有:类装饰器、属性装饰器、方法装饰器、参数装饰器
装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可传参)
装饰器是过去几年中js最大的成就之一,已是Es7的标准特性之一
类装饰器:英装饰器在类声明之前被声明(紧案看类声明),类装饰器应用于类构洁团数,可以用来监视,修改或替描类定义。传入一个参数
普通装饰器(无法传参
function logClass(params:any){
console.log(params)
params.prototype.apiUrl='动态扩展的属性'
params.prototype.run=function(){
console.log('我是一个run方法')
}
}
@logClass
class HttpClient {
constructor() {
}
getData(){
}
}
var http:any=new HttpClient()
console.log(http.apiUrl)
http.run()
装饰器工厂(可传参)
function logClass(params:string){
return function(target:any){
console.log(target) //fn
console.log(params) //http://baidu.com
target.prototype.apiUrl=params
}
}
@logClass('http://baidu.com')
class HttpClient {
constructor() {
}
getData(){
}
}
var http:any=new HttpClient()
console.log(http.apiUrl)//http://baidu.com
function logClass(target:any){
console.log(target)
return class extends target{
apiUrl:any='我是修改后的数据'
getData(){
this.apiUrl=this.apiUrl+"------"
console.log(this.apiUrl)
}
}
}
@logClass
class HttpClient {
public apiUrl:string|undefined;
constructor() {
this.apiUrl='我是构造函数里面的apiUrl'
}
getData(){
console.log(this.apiUrl)
}
}
let http=new HttpClient()
http.getData()
属性装饰器
//类装饰器
function logClass(params:string){
return function(target:any){}
}
//属性装饰器
function logProperty(params:any){
return function(target:any,attr:any){
console.log(target)//fn2
console.log(attr)//url
target[attr]=params
}
}
@logClass
class HttpClient {
@logProperty('http://baidu.com')
public url:any|undefined;
constructor(){
}
getData(){
console.log(this.url)
}
}
var http=new HttpClient()
http.getData()
20.方法装饰器 方法参数装饰器 装饰器的执行顺序
3、方法装饰器
它会被应用到方法的属性描述符上,可以用来监视,修改或者替换方法定义。
方法装饰会在运行时传入下列3个参数:
1、对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
2、成员的名字。
3、成员的属性描述符。
方法装饰器
{
function get(params:any){
return function(target:any,methodName:any,desc:any){
console.log(target)
console.log(methodName)
console.log(desc)
target.apiUrl='xxxxxxx'
target.run=function(){
console.log('run')
}
}
}
class HttpClient {
public url:any|undefined;
constructor(){
}
@get('http://baidu.com')
getData(){
console.log(this.url)
}
}
var http:any=new HttpClient()
http.getData()
console.log(http.apiUrl)
http.run()
}
{
function get(params:any){
return function(target:any,methodName:any,desc:any){
console.log(target)
console.log(methodName)
console.log(desc)
var oMethod=desc.value;
desc.value=function(...args:any[]){
args=args.map((value)=>{
return String(value)
})
console.log(args)
oMethod.apply(this,args)
}
}
}
class HttpClient {
public url:any|undefined;
constructor(){
}
@get('http://baidu.com')
getData(...args:any[]){
console.log(args)
console.log('我是getData里面的方法')
}
}
var http:any=new HttpClient()
http.getData(555,'fff')
}
方法参数装饰器
{
function logParams(params:any){
return function(target:any,methodName:any,paramsIndex:any){
console.log(params)
console.log(target)
console.log(methodName)
console.log(paramsIndex)
target.apiUrl=params;
}
}
class HttpClient {
public url:any|undefined;
constructor(){
}
getData(@logParams('uuid') uuid:any){
console.log(uuid)
}
}
var http:any=new HttpClient()
http.getData(12346)
console.log(http.apiUrl)
}
装饰器执行顺序
如果有多个同样的装饰器,它会先执行后面的
属性》方法》方法参数》类
{
function logClass1(params:string){
return function(target:any){
console.log('类装饰器1')
}
}
function logClass2(params:string){
return function(target:any){
console.log('类装饰器2')
}
}
function logAttribute(params?:string){
return function(target:any,attrName:any){
console.log('属性装饰器')
}
}
function logMethod(params?:string){
return function(target:any,attrName:any,desc:any){
console.log('方法装饰器')
}
}
function logParams1(params?:string){
return function(target:any,attrName:any,desc:any){
console.log('方法参数装饰器1')
}
}
function logParams2(params?:string){
return function(target:any,attrName:any,desc:any){
console.log('方法参数装饰器2')
}
}
@logClass1('http://baidu.com')
@logClass2('xxxxxx')
class HttpClient {
@logAttribute()
public url:any|undefined;
constructor(){
}
@logMethod()
getData(){
return true;
}
setData(@logParams1() attr1:any,@logParams2() attr2:any){
}
}
var http:any=new HttpClient()
http.getData()
}
21.vue简介 搭建环境 运行项目 分析目录解构
cnpm install -g @vue/cli
vue -V
vue -v
vue create vuedemo01
npm run serve
yarn serve
vue3 -V 多版本安装
vue/cli vite俩脚手架
vite
npm init vite-app project-name
cd project-name
npm install
npm run dev
yarn
yarn create vite-app project-name
cd project-name
yarn
yarn dev
yarn create vite-app project-name
cnpm i
npm run dev
22.数据绑定 绑定html 绑定属性 循环数据
24
https://www.itying.com/themes/itying/images/logo.gif
{ 绑定对象:{{userinfo.username}}---{{userinfo.age}}
{{h2}}
绑定html:
{{msg}}
<ul>
<li v-for="(item,index) in list3" :key="index">
{{item.cart}}
<ol>
<li v-for="(x,y) in item.list" :key="y">
{{x.name}}
</li>
</ol>
</li>
</ul>
<ul>
<li v-for="(value,key,index) in object" :key="index">
{{key}}==={{value}}---{{index}}
</li>
</ul>
}
23.事件方法入门 模板语法 模板中的类和样式绑定
{
{{msg}}
class绑定多个动态属性
div
div
div
三目运算符class
red
多个style
对象绑定style
对象绑定style
}
24.事件方法详解 事件监听 方法传值 事件对象 多事件处理程序 事件修饰符 按键修饰符
{
<h2>{{title}}</h2>
<button @click="setTitle('5555')">setTitle</button>
<br>
<button data-aid='123' @click="eventFn($event)">事件对象</button>
<!-- <button @click="setMSg(),getMsg()">一次触发多个方法</button> -->
<a @click="afn1($event)" href="http://www.baidu.com" target="_blank">gotobaidu</a>
<a @click.prevent="afn2()" href="http://www.baidu.com" target="_blank">gotobaidu</a>
<input type="text" @keyup="doSearch1($event)">
<input type="text" @keyup.enter="doSearch2()">
}
25.Dom操作$refs 表单input checkbox radio select textarea实现在线预约
27
{
}
{
}
</li>
<li>备注:
<textarea v-model="userinfo.mark" cols="30" rows="10"></textarea>
</li>
</ul>
<button @click="doSubmit()" class="submit">获取表单的内容</button>
<pre>
{{userinfo}}
</pre>
26.使用javascript表达式 条件判断 计算属性 watch侦听
{
{{a+4}}
{{flag?"this is true":"this is false"}}
{{message.split('').reverse().join('')}}
v-if v-else v-else-if v-show
A
B
not A/B
v-if是dom操作,v-show只是css的显示隐藏
v-show
<h3>计算属性</h3>
<div>{{reverseMsg}}</div>
<button @click="setMsg()">改变msg</button>
<h3>watch监听数据变化</h3>
<input type="text" v-model="firstName" placeholder="firstName">
<input type="text" v-model="lastName" placeholder="lastName">
{{fullName}}
<hr>
{{fullNameFn}}
}
27.待办事项 京东app搜索缓存数据功能
默认不支持sass
安装
npm install -D sass-loader node-sass
lang可以配置scss,scoped表示这里写的css只有当前组件有效
v-if v-for 不能一块用 v-show代替
{
Vue实现TodoList
todolist
正在进行
已经完成
}
28.封装storage 实现todolist待办事项 已完成的持久化
{
Vue实现TodoList
todolist
正在进行
已经完成
}
import storage from './models/storage';
{
const storage={
set(key,value){
localStorage.setItem(key,JSON.stringify(key,value))
},
get(key){
return JSON.parse(localStorage.getItem(key))
},
remove(key){
localStorage.removeItem(key)
}
}
export default storage;
}
{
Vue实现TodoList
todolist
正在进行
已经完成
}
29.单文件组件 定义组件 注册组件 组件使用
31
components/Hemo.vue
首字母大写
{
{{msg}}
3.使用
}
components:{
"v-header":Header
}
30.父组件给子组件传值 Props Props验证 单向数据流
父
{
}
子
{
{{title}}
{{msg}}
{{count}}
<!-- {{userinfo.username}}---{{userinfo.age}} -->
<button @click="getParentTitle()">获取父组件的数据
{{home.title}}
<button @click="runParentFn()">执行父组件方法
}
31.父组件主动获取子组件的数据和执行子组件的方法
子组件主动获取父组件的数据和执行父组件的方法
子
{
我是头部组件
msg:{{msg}}
<button @click="getParentMsg">获取父组件里面的数据
<button @click="getParentFn">执行父组件的方法
<button @click="setParentMsg">修改父组件的数据
}
父
{
我是Home组件
<button @click="getChildMsg">获取子组件里面的数据
<button @click="getChildFn">执行子组件的方法
<button @click="setChildMsg">修改子组件的数据
msg:{{msg}}
}
32.组件自定义事件 mitt实现非父子组件传值
34
@send='xxx'
自定义事件
$emit
github.com/developit/mitt
cnpm install --save mitt
{
<v-header @send="getChild">
<v-login @submit="doLogin">
}
{
头部组件
--- <button @click="sendParent">执行父组件的自定义事件
--- <button @click="sendLogin">触发登录组件里面的事件 实现传值
}
{
<button @click="doLogin">执行登录
}
import mitt from 'mitt'
const event =mitt()
export default event
33.自定义组件使用v-model 双向数据绑定 slots prop的Attrbute继承 禁用Attrbute继承
{
我是一个Home组件
{{keyword}}
username组件
{{firstName}}----{{lastName}}
自定义Attribute继承
}
{
}
{
}
{
<input @input="$emit('update:keyword',$event.target.value)" type="text" :value="keyword" placeholder="请输入内容">
}
{
<input @input="$emit('update:firstName',$event.target.value)" type="text" :value="firstName" placeholder="firstName">
<input @input="$emit('update:lastName',$event.target.value)" type="text" :value="lastName" placeholder="lastName">
}
34.组件的生命周期函数lifecycle this.$nextTick 动态组件keep-alive vue实现tab切换
beforeCreate
created
beforeMount
Mounted
beforeUpdate
updated
beforeUnmount
unmounted
{
我是一个Home组件
<button @click="isShow=!isShow">挂载/卸载组件
}
{
生命周期演实
<button @click="msg='改变后的msg'">改变msg
{{msg}}
<li v-for="(item,index) in posts" :class="{'active':currentIndex===index}" :key="index" @click="currentIndex=index">
{{item.title}}
<div class="tab_content">
<span v-html="content"></span>
</div>
</div>
</div>
}
35.全局绑定属性 使用axios和fetchJsonp请求真实api接口数据 函数防抖实现百度搜索
37
cnpm install axios --save
http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1
github.com/camsong/fetch-jsonp
1> npm install fetch-jsonp
加 --save 别人可以npm i 不加只有自己用
https://spo.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=php
箭头函数 指向 上下文
{
const storage={
set(key,value){
localStorage.setItem(key,JSON.stringify(value))
},
get(key){
return JSON.parse(localStorage.getItem(key))
},
remove(key){
localStorage.removeItem(key)
}
}
export default storage
}
{
<button @click="getData()">axios获取数据
}
main.js
{
import { createApp } from 'vue'
import App from './App.vue'
import Axios from 'axios'
import Storage from './models/storage'
import fetchJsonp from 'fetch-jsonp'
//原来的代码
// createApp(App).mount('#app')
//修改后的代码
const app=createApp(App);
app.config.globalProperties.Axios=Axios;//this.Axios 全局调用
app.config.globalProperties.Storage=Storage;//this.Storage
app.config.globalProperties.fetchJsonp=fetchJsonp;
app.mount('#app')
}
{
<button @click="getData()">获取百度数据----baidu
<input type="text" v-model="keyword" @click="getData()">
</div>
}
36.Mixin实现组件功能的复用 全局配置Mixin
38
main.js
{
import { createApp } from 'vue'
import App from './App.vue'
import Axios from 'axios'
import fetchJsonp from 'fetch-jsonp'
import baseMinxin from './mixin/baseMixin'
//原来的代码
// createApp(App).mount('#app')
//修改后的代码
const app=createApp(App);
app.config.globalProperties.Axios=Axios;//this.Axios 全局调用
app.config.globalProperties.fetchJsonp=fetchJsonp;
//全局配置mixins
app.mixin(baseMinxin)
app.mount('#app')
}
{
首页模板----{{apuUrl}}
<button @click="success">执行mixin里面的方法
{{msg}}
}
37.Teleport.使用Teleport自定义一个模态对话框的组件
39
{
<button @click="isVisible=true">弹出一个模态对话框
<modal :visible='isVisible' title="用户登录" @close-model="isVisible=false">
}
{
<button class="close" @click="$emit('close-model')">X
{{title}}
}
38.Composition API setup ref reactive toRefs详解(上)
没有Composition API之前yue相关业务的代码需要配置到option的特定的区域,]
中小型项目是没有问题的,但是在大型项目中会导致后期的维护性比较复杂,
同时代码可复用性不高。Vue3x中的composition-api就是为了解决这个问题而生的。
{
Home组件---{{msg}}
<button @click="run">run
{{title}}
{{userinfo.username}}---{{userinfo.age}}
<button @click="getUserName">getUserName
<button @click="getTitle">getTitle
<button @click="setUserName">setUserName
<button @click="setTitle">setTitle
{{description}}
}
39.Composition API setup ref reactive toRefs computed watch
{
{{fullName}}
{{obj.username}}
}
{
search----num:{{num}}
count:{{count}}
}
{
{{keyword}}
}
{
Home组件
}
40.Composition API 以及Provider inject
42
1.
{
Location组件---{{title}}
}
{
{{title}}
}
provider inject实现父子组件传值的时候,子组件改变数据也会影响父组件
{
Location组件----{{title}}
{{userinfo.username}}---{{userinfo.age}}
}
{
{{title}}
}
41.Vue3+Typescript vue3.x中集成typescript 使用typescript上
npm install --global @vue/cli
vue create demo
vue add typescript
加入ts 就用 defineComponent
{
News---{{newData.title}}
}
{
home组件---{{title}}
<button @click="setTitle">setTitle
}
42.vue3集成typescript composition api中使用typescript
多类型
count:string|number
模板没办法约束类型
{
username:{{username}}
<button @click="setUsername('john')">setUsername
{{count}}
{{reverseUsername}}
}
43.vue3中的路由 路由配置
45
next.router.vuejs.org/
1.npm install vue-router@next --save
2.准备组件
3.配置路由
{
import { createRouter,createWebHashHistory } from "vue-router";
//引入组件
import Home from './components/Home.vue'
import News from './components/News.vue'
import User from './components/User.vue'
//配置路由
const router=createRouter({
history:createWebHashHistory(),
routes:[
{path:'/',component:Home},
{path:'/news',component:News},
{path:'/user',component:User},
]
})
export default router
}
4.挂载路由
{
import { createApp } from 'vue'
import App from './App.vue'
import route from './routes'
const app=createApp(App)
app.mount('#app')
//挂载路由
app.use(route)
}
5.使用
{
}
44.vue3中的路由 vue动态路由 get传值 js跳转路由
动态路由
{
import { createRouter,createWebHashHistory } from "vue-router";
//引入组件 路由要带后缀.vue
import Home from './components/Home.vue'
import News from './components/News.vue'
import User from './components/User.vue'
import NewsContent from './components/NewsContent.vue'
//配置路由
const router=createRouter({
history:createWebHashHistory(),
routes:[
{path:'/',component:Home},
{path:'/news',component:News},
{path:'/user',component:User},
//:aid 动态路由
{path:'/newscontent/:aid',component:NewsContent}
]
})
export default router
}
{
News组件
}
{
NewContent组件
}
笔记本工具下载用
{
import { createRouter,createWebHashHistory } from "vue-router";
//引入组件 路由要带后缀.vue
import Home from './components/Home.vue'
import News from './components/News.vue'
import User from './components/User.vue'
import NewsContent from './components/NewsContent.vue'
//配置路由
const router=createRouter({
history:createWebHashHistory(),
routes:[
{path:'/',component:Home},
{path:'/news',component:News},
{path:'/user',component:User},
{path:'/newscontent',component:NewsContent}
]
})
export default router
}
{
News组件
}
{
home组件---{{title}}
<button @click="setTitle">setTitle
<button @click="this.$router.push({path:'/newscontent',query:{aid:12}})">跳转到新闻详细get传值
}
{
NewContent组件
<button @click="goHome">js跳转路由
}
45.vue3中的路由 路由模式 命名路由 路由重定向 路由别名
47
{
import {
createRouter,
createWebHashHistory,
createWebHistory
} from "vue-router";
//引入组件 路由要带后缀.vue
import Home from './components/Home.vue'
import News from './components/News.vue'
import User from './components/User.vue'
import UserInfo from './components/UserInfo.vue'
import NewsContent from './components/NewsContent.vue'
//配置路由
const router=createRouter({
// history:createWebHashHistory(),//hash模式 url带#号
history:createWebHistory(),//h5 history模式 不带# url
routes:[
{path:'',redirect:'/home'},//路由重定向
{path:'/home',component:Home},
{path:'/news',component:News,name:'news',alias:['/n','/c']},//name给路由起名字
{path:'/user',component:User,alias:'/people'},//alias 起别名 还可多个arr
{path:'/userinfo/:id',name:'userinfo',alias:'/u/:id',component:UserInfo},
{path:'/newscontent',name:'content', component:NewsContent}
]
})
export default router
}
{
}
{
User
用路由名字跳转 并且动态路由传值
<button @click="this.$router.push({name:'userinfo',params:{id:233}})">js跳转到userinfo
<button @click="this.$router.push({name:'content',query:{aid:233}})">js跳转到content
}
{
News组件
用路由名字跳转 并且get传值
}
46.vue3中的路由 路由嵌套 父子路由
npm install node-sass sass-loader style-loader --save
vscode ctrl+shirt+f 格式化
{
import {
createRouter,
createWebHashHistory,
createWebHistory
} from "vue-router";
//引入组件 路由要带后缀.vue
import Home from './components/Home.vue'
import News from './components/News.vue'
import NewsAdd from './components/News/NewsAdd.vue'
import NewsList from './components/News/NewsList.vue'
import User from './components/User.vue'
import UserAdd from './components/User/UserAdd.vue'
import UserList from './components/User/UserList.vue'
//配置路由
const router=createRouter({
// history:createWebHashHistory(),//hash模式 url带#号
history:createWebHistory(),//h5 history模式 不带# url
routes:[
{path:'',redirect:'/home'},//路由重定向
{path:'/home',component:Home},
{path:'/news',component:News,name:'news',
children:[
{path:'',redirect:'/news/newslist'},
{path:'newslist',component:NewsList},
{path:'newsadd',component:NewsAdd},
]
},//name给路由起名字
{path:'/user',component:User,
children:[ //父子路由
{path:'',redirect:'/user/userlist'},
{path:'userlist',component:UserList},
{path:'useradd',component:UserAdd},
]
},
]
})
export default router
}
{
}
47.vuex的使用State Mutation mapState 实现多个页面共享状态
49
Vuex是一个专为Vue.js应用程序开发的状态管理模式。
Vuex的几个核心概念:
State 数据
Getters
Mutations 方法 木tei省
Actions
Modules
主要功能:
1,vuex可以实现vue不同组件之间的状态共享(解决了不同组件之间的数据共享)
2.可以实现组件里面数据的持久化
返回页面
localStorage
keep-alive
vuex
安装 npm install vuex@next --save
src/vuex/store.js
{
import {createStore} from 'vuex'
const store = createStore({
state(){//数据
return {
count:1
}
},
mutations:{//方法
incCount(state){
state.count++
},
setCount(state,num){
state.count=num
}
}
})
export default store;
}
main.js
{
import { createApp } from 'vue'
import App from './App.vue'
import route from './routes'
import store from './vuex/store'
const app=createApp(App)
app.mount('#app')
//挂载路由
app.use(route)
//挂载vuex
app.use(store)
}
使用
store.state.count
this.$store.state.count
{
home组件---{{num}}
<button @click="incCount">执行vuex里面的方法
<button @click="setCount">执行vuex里面的方法 传值
}
48.vuex中的State Mutation Getters mapGetters Actions Modules
setTimeOut异步操作
{
home组件---{{num}}
<button @click="incCount">执行vuex里面的方法
<button @click="setCount">执行vuex里面的方法 传值
{{revMsg}}
$store.dispatch('incCount') vuex中的Actions方法
<button @click="$store.dispatch('incCount')">incCount
}
{
import {createStore} from 'vuex'
const store = createStore({
state(){//数据
return {
count:1,
msg:"你好vue"
}
},
mutations:{//方法
incCount(state){
state.count++
},
setCount(state,num){
state.count=num
}
},
getters:{//相当computed
reverseMsg(state){
return state.msg.split("").reverse().john('')
}
},
actions:{ //执行mutations里面的方法 异步操作放在actions
incCount(context){
context.commit('incCount');//执行mutations incCount
},
incSetMsg(context,msg){
setTimeout(() => {
context.commit('setMsg',msg)
}, 1000);
}
}
})
export default store;
}
modules vuex
{
let newsStore={
state(){//数据
return {
count:2,
msg:"你好vue"
}
},
}
export default newsStore
}
{
import {createStore} from 'vuex'
import newsStore from './newsStore';
import userStore from './userStore'
const store = createStore({
modules:{
'user':userStore,
'news':newsStore
}
})
export default store;
}
{
home组件
vuex modules
{{$store.state.user.count}}
<button @click="incCount">改变user模块里面的数据
}
49.vuex结合composition api的使用
{
home组件
{{count}}
{{num}}
<button @click="incCount">执行方法
<button @click="setActionCount">setActionCount
}
{
import {createStore} from 'vuex'
const store = createStore({
state(){//数据
return {
count:1,
msg:"你好vue"
}
},
mutations:{//方法
incCount(state){
state.count++
},
setCount(state,num){
state.count=num
}
},
getters:{//相当computed
reverseMsg(state){
return state.msg.split("").reverse().john('')
}
},
actions:{ //执行mutations里面的方法 异步操作放在actions
incCount(context){
context.commit('incCount');//执行mutations incCount
},
incSetMsg(context,msg){
setTimeout(() => {
context.commit('setMsg',msg)
}, 1000);
},
setCount({commit},num){
commit('setCount',num)
}
}
})
export default store;
}
50.vue+vuex+ts vuex composition api和非composition api中结合typescript的使用
{
import {createStore} from 'vuex'
// 让vuex支持ts 引入
import { Store } from 'vuex'
import { ComponentCustomProperties } from 'vue'
//配置vue+ts的项目里面使用vuex 官网查 记不得
declare module '@vue/runtime-core'{
interface State{
count:number,
list:string[],
msg:string
}
interface ComponentCustomProperties{
$store:Store<State>
}
}
const store = createStore({
state(){//数据
return {
count:1,
list:['koo','john'],
msg:"你好vue"
}
},
mutations:{//方法
incCount(state:any){
state.count++
},
setCount(state:any,num:number){
state.count=num
}
},
getters:{//相当computed
reverseMsg(state){
return state.msg.split("").reverse().john('')
}
},
actions:{ //执行mutations里面的方法 异步操作放在actions
incCount(context){
context.commit('incCount');//执行mutations incCount
},
incSetMsg(context,msg){
setTimeout(() => {
context.commit('setMsg',msg)
}, 1000);
},
setCount({commit},num){
commit('setCount',num)
}
}
})
export default store;
}
{
home组件
{{count}}
msg:{{msg}}
}
51.Vue3+Serverless项目 基于Serverless的Egg.js+MYSQL+vue无人点餐无人收银全栈项目介绍
Serverless架构介绍
Serverless又名无服务器,所谓无服务器并非是说不需要依赖和依靠服务器等资源,而是开发者再也不用过多考虑服务器的问题,可以更专注在产品代码上,狭义的Serverless是Faas和Baas组成。
52.Vue3+Serverless项目 初识Serverless 三分钟搭建部署自己的Serverless应用
npm install -g serverless
serverless -v
使用
serverless
53.TypeScript+ Angular系列教程 angular介绍 安装angular cli 创建angular项目
npm install -g @angular/cli
ng v
创建项目
ng new 项目名称
ng new angulardemo --skip-install 跳过npm i
npm install 一样
运行
ng serve --open
vscode angular 插件 大
54.Angular目录结构分析 核心文件分析 以及创建使用组件
创建组件
ng g
ng g component components/news
'es3',
'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'esnext'.
https://segmentfault.com/a/1190000020355506
三. 运行显示空白页面的问题
我之前一直都很疑惑,直到公司大佬发现了问题的原因,大概是兼容性问题导致的。
需要修改根目录下面的tsconfig.json文件
"target": "es2015",
修改为
"target": "es5",
重新运行下项目,就可以正常显示了
es2017==es5
55.Angular模板ts定义属性 绑定数据 绑定属性 绑定html 数据循环 循环多维数组
public userinfo:object={
name:'koo',
age:22
}
public student:string='koo'
张三public content='
我是一个html标签
' {{content}}{{1+2}}
public arr:number[]=[1111,2222222222,33333333];
- {{item}}
public items:Array
嵌套 循环多次
56.Angular绑定数据 条件判断 加载图片 ngClass ngStyle
app.html
ng g component components/home
home==app-home
scss
其他管道:
http://bbs.itying.com/topic/sbf519657e9f5911d41f2a34
旧版直接modelx 新版引入v
import {FormsModule} from '@angular/forms';
app.module.ts
{
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
//双向数据绑定 引入
import { AppComponent } from './app.component';
import { NewsComponent } from './components/news/news.component';
import { HomeComponent } from './components/home/home.component';
@NgModule({
declarations: [
AppComponent,
NewsComponent,
HomeComponent
],
imports: [
BrowserModule,
FormsModule //双向数据绑定 声明
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
}
home.component.ts
{
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
public keywords:string | undefined;
public url='https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png'
public list:any[]=[
{
'title':'我是新闻1'
},
{
'title':'我是新闻2'
},
{
'title':'我是新闻3'
},
]
public flag:boolean=true;
public orderStatus:number=1;//1.表示已经支付 2支付并且确认订单 3、表示已经发货 4表示已经收获 其他、无效
public attr:string='red';
public today=new Date();
constructor() { }
ngOnInit(): void {
}
run(){
alert(this.attr)
}
keyDown(e:any){
if(e.keyCode==13){
console.log('按了一下回车')
}else{
console.log(e.keyCode)
console.log(e.target.value)//获取dom对象
}
}
}
}
home.component.html
{
引入图片
循环数据 显示数据的索引(key)
- {{key}}---{{item.title}}
条件判断语句 *ngIf
条件判断语句 ngswitch
1.表示已经支付 2支付并且确认订单 3、表示已经发货 4表示已经收获 其他、无效属性[ngClass] [ngStyle]
属性[ngClass]- {{key}}---{{item.title}}
我是一对数据
我是一对数据
管道:{{today|date:'yyyy-MM-dd HH:mm:ss'}}
双向数据绑定 MVVM 只针对表单
{{keywords}} }57.Ng中的Dom操作 以及表单(input checkbox radio select textarea)
xxx.component.ts
selector:'app-xxx'
xxx.component.html
style.scss 全局css
{
人员登记系统
- 姓名:
- 性别:
- 城市:
- 爱好:
- 备注:
{{peopleInfo | json}}
}
{
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {
public peopleInfo:any={
username:'',
sex:'1',
cityList:['北京','广州','上海'],
city:'北京',
hobby:[
{
title:'吃饭',
checked:false
},
{
title:'睡觉',
checked:false
},
{
title:'敲代码',
checked:true
},
],
mark:''
}
constructor() { }
ngOnInit(): void {
}
doSubmit(){
//jquery dom操作
/*
let usernameDom:any=document.getElementById('username')
console.log(usernameDom.value)
*/
console.log(this.peopleInfo)
}
}
}
58.Ng实现一个完整的toDoList(待办事项) 以及类似京东App搜索缓存数据功能[前面知识综合练习]
60
{
todolist
待办事项
- {{item.title}}------
已完成事项
- {{item.title}}------
}
{
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-todolist',
templateUrl: './todolist.component.html',
styleUrls: ['./todolist.component.scss']
})
export class TodolistComponent implements OnInit {
public keyword:string|undefined;
public todolist:any[]=[];
constructor() { }
ngOnInit(): void {
}
doAdd(e:any){
console.log(e)
if(e.keyCode13){
this.todolist.push({
title:this.keyword,
status:0 //0表示代办事项 1表示已完成事项
})
}
}
deleteData(key:number){
this.todolist.splice(key,1)
}
doSearch(){
// if(this.todolist.indexOf(this.keyword)-1){
if(!this.todolistHasKeyword(this.todolist,this.keyword)){
this.todolist.push({
title:this.keyword,
status:0 //0表示代办事项 1表示已完成事项
})
}else{
alert('数据已经存在')
this.keyword=''
}
this.keyword=''
}
//如果数组里面有keyword返回true 否则返回false
todolistHasKeyword(todolist:any,keyword:any){
//异步 会存在问题
// todolist.forEach(value=>{
// if(value.title==keyword){return true;}
// });
if(!keyword)return false;
for(let i=0;i<todolist.length;i++){
if(todolist[i].title==keyword){
return true;
}
}
return false;
}
}
}
35x
8v
59.Angular中的服务 以及自定义服务 以及完善toDoList(待办事项案例)
服务 公共方法 属性使用
创建服务命令
ng g service my-new-service
ng g service services/storage
app.module.ts
{
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { SearchComponent } from './components/search/search.component';
import { TodolistComponent } from './components/todolist/todolist.component';
//引入并且配置服务
import {StorageService} from './services/storage.service'
@NgModule({
declarations: [
AppComponent,
SearchComponent,
TodolistComponent,
],
imports: [
BrowserModule,
FormsModule
],
providers: [StorageService],//引入并且配置服务
bootstrap: [AppComponent]
})
export class AppModule { }
}
storage.service.ts
{
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class StorageService {
constructor() { }
get(){
return 'this is a service'
}
}
}
search.component.ts
{
import { Component, OnInit } from '@angular/core';
import {StorageService} from '../../services/storage.service'
// var storage=new StorageService();
// //constructor里面用 不推荐
// console.log(storage.get)
@Component({
selector: 'app-search',
templateUrl: './search.component.html',
styleUrls: ['./search.component.scss']
})
export class SearchComponent implements OnInit {
public keyword:string|undefined;
public historyList:any[]=[];
constructor(public storage:StorageService) {
console.log(this.storage.get())
}
ngOnInit(): void {
}
doSearch(){
if(this.historyList.indexOf(this.keyword)==-1){
this.historyList.push(this.keyword)
}
this.keyword=''
}
deleteHistory(index:number){
this.historyList.splice(index,1)
}
}
}
ngOnInit(): void {
console.log('页面刷新会触发这个生命周期函数')
}
60.Ng中的Dom操作以及@ViewChild Angular调用css3动画(侧边栏 actionSheet)
62
ng10 12 插件
{
{
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
public flag:boolean=true
constructor() { }
ngOnInit(): void {
// 组件和指令初始化完成 并不是真正的dom加载完成
// let oBox=document.getElementById('box') as HTMLDivElement
let oBox:any=document.getElementById('box')
console.log(oBox.innerHTML)
oBox.style.color='red'
//获取不到dom节点
// let oBox1:any=document.getElementById('box1')
// console.log(oBox1.innerHTML)
// oBox1.style.color='blue'
}
//生命周期函数 视图加载完成以后触发的方法 dom加载完成 建议把dom操作放在这个里面
ngAfterViewInit():void{
let oBox1:any=document.getElementById('box1')
console.log(oBox1.innerHTML)
oBox1.style.color='blue'
}
}
}
{
<app-header #header>
<button (click)='childrenFn()'>childrenFn
}
{
import { Component, OnInit,ViewChild } from '@angular/core';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.scss']
})
export class NewsComponent implements OnInit {
//获取dom节点
@ViewChild('myBox') myBox:any;
//获取一个组件实例
@ViewChild('header') header:any;
constructor() { }
ngOnInit(): void {
}
ngAfterViewInit(): void {
console.log(this.myBox)
this.myBox.nativeElement.style.width='100px'
this.myBox.nativeElement.style.height='100px'
this.myBox.nativeElement.style.background='red'
console.log(this.myBox.nativeElement.innerHTML)
}
childrenFn(){
//调用子组件里面的方法
this.header.run()
}
}
}
{
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
run(){
console.log('我是header的run方法')
}
}
}
aside{
width: 200px;
height: 100%;
position: absolute;
right: 0px;
top: 0px;
background: #000;
color: #fff;
transform: translate(100%,0);
transition: all 2s;
}
{
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-transition',
templateUrl: './transition.component.html',
styleUrls: ['./transition.component.scss']
})
export class TransitionComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
showside(){
var asideDom:any=document.getElementById('aside')
asideDom.style.transform='translate(0,0)'
}
hideside(){
var asideDom:any=document.getElementById('aside')
asideDom.style.transform='translate(100%,0)'
}
}
}
{
内容区域}
61.Angular父子组件以及组件之间通讯@input@Ouput @ViewChild
父
<app-header [title]='title'>
public title:any='首页的title'
子
{{title}}
import { Component, OnInit ,Input} from '@angular/core'; @Input() title:any;//类里面用父
<app-header [title]='title' [run]='run'>
run(){
alert('parentFn')
}
子
<button (click)='parentFn()'>parentFn
import { Component, OnInit ,Input} from '@angular/core';
@Input() run:any;
parentFn(){
this.run()
}
整个
<app-header [title]='title' [run]='run' [home]='this'>
<button (click)='parentFn()'>parentFn
import { Component, OnInit ,Input} from '@angular/core';
@Input() home:any;
parentFn(){
this.home.run()
}
以上父传子
以下子传父
父
<app-footer #footer>
我是一个新闻组件
import { Component, OnInit,ViewChild } from '@angular/core';
@ViewChild('footer') footer:any;
childrenFn(){
//调用子组件里面的方法
this.footer.run()
this.footer.msg;//属性
}
子
public msg:string='chrildrenMsg'
run(){
alert('chrildrenFn')
}
localstorage
服务service
事件驱动
以下子传父
父
<app-footer #footer (outer)='run($event)'>
run(e:any){
alert(e)
}
子
<button (click)="sendParent()">通过@output父组件广播数据
import { Component, OnInit,Output,EventEmitter } from '@angular/core';
@Output() private outer=new EventEmitter();
sendParent(){
this.outer.emit('我是子组件的数据')
}
62.Angular中的生命周期函数--动态挂载销毁组件
64
官方文档:https://www.angular.cn/guide/lifecycle-hooks
生命周期函数通俗的讲就是组件创建、组件更新、组件销毁的时候会触发的一系列的方法。
constructor 第一个执行
ngOnChanges
ngOnInit 请求网络数据在这
ngDoCheck()
ngAfterContentInit()
ngAfterContentChecked()
ngAfterViewInit() Dom操作
ngAfterViewChecked()
ngOnDestroy() 销毁
63.Rxjs6.x异步数据流编程 Angular Rxjs快速入门教程
参考手册:https://www.npmjs.com/package/rxjs
中文手册:https://cn.rx.js.org
目前常见的异步编程的几种方法:
1、回调函数
2、事件监听/发布定阅
3.Promise
4、Rxjs
ng g service services/request
app.module.ts
{
import { RequestService } from './services/request.service';
providers: [StorageService,RequestService],//引入并且配置服务
}
request.service.ts
home.component.ts
import {RequestService} from '../../services/request.service'
constructor(public request:RequestService) { }
setTimeout 1次
setInterval 多次
Rxjs异步编程解决方案
home.component.ts
{
import { Component, OnInit } from '@angular/core';
import {RequestService} from '../../services/request.service'
//rxjs6.x 方法
import {map,filter} from 'rxjs/operators';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
constructor(public request:RequestService) { }
ngOnInit(): void {
//1.同步方法
let data=this.request.getData();
console.log(data)
//2.callback获取异步数据
// this.request.getCallbackData((data:any)=>{
// console.log(data)
// });
//3.promise获取异步数据
var promiseData=this.request.getPromiseData();
promiseData.then((data)=>{
console.log(data)
})
//4.rxjs获取异步方法里面的数据
var rxjsData=this.request.getRxjsData();
rxjsData.subscribe((data)=>{
console.log(data)
})
//5.过一秒以后撤回刚才的操作
var streem=this.request.getRxjsData();
var d=streem.subscribe((data)=>{
console.log(data)
})
setTimeout(() => {
d.unsubscribe();//取消订阅
}, 1000);
//6.promise执行多次(没有这个能力)
var intervalData=this.request.getPromiseIntervalData()
intervalData.then((res)=>{
console.log(res)
})
//7.rxjs执行多次
var streemInterval=this.request.getRxjsIntervalData()
streemInterval.subscribe((data)=>{
console.log(data)
})
//8.用工具方法对返回的数据进行处理
/*
var streemNum=this.request.getRxjsIntervalNum()
streemNum.pipe(
// filter((value:any)=>{
// if(value%2==0){
// return true;
// }
// })
)
.subscribe((data)=>{
console.log(data)
})
*/
var streemNum=this.request.getRxjsIntervalNum()
streemNum.pipe(
//filter map 一块用 ,号隔开
map((value:any)=>{
return value*value
})
)
.subscribe((data)=>{
console.log(data)
})
}
}
}
request.service.ts
{
import { Injectable } from '@angular/core';
//Rxjs 需要用到地方 引入
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class RequestService {
constructor() { }
//同步
getData(){
return 'this is service data'
}
// getCallbackData(cb){
// setTimeout(() => {
// var username='张三';
// // return useername
// cb(username)
// }, 2000);
// }
getPromiseData(){
return new Promise((resolve)=>{
setTimeout(() => {
var username='张三---Promise'
resolve(username)
}, 2000);
})
}
getRxjsData(){
return new Observable((observer)=>{
setTimeout(() => {
var username='张三---Observable'
observer.next(username)
// observer.error('数据')
}, 3000);
})
}
//多次执行
getPromiseIntervalData(){
return new Promise((resolve)=>{
setInterval(() => {
var username='张三---Promise---interval'
resolve(username)
}, 2000);
})
}
getRxjsIntervalData(){
let count=0;
return new Observable((observer)=>{
setInterval(() => {
count++;
var username='张三---Observable'+count
observer.next(username)
// observer.error('数据')
}, 3000);
})
}
getRxjsIntervalNum(){
let count=0;
return new Observable((observer)=>{
setInterval(() => {
count++;
observer.next(count)
// observer.error('数据')
}, 1000);
})
}
}
}
64.ng中的数据请求 内置模块HttpClient实现(get post jsonp 以及第三方模块axios)
66
constructor
ngOnInit
ngAfterViewInit
ngOnDestroy
1.使用HttpClient在
app.module.ts 引入
//引入HttpClientModule
import {HttpClientModule} from '@angular/common/http'
imports: [
HttpClientModule,//注入
],
2.使用到地方
new.component.ts
//当作一个服务
import { HttpClient } from '@angular/common/http';
constructor(public http:HttpClient) { }
post 在使用到地方
new.component.ts 多加httpheaders
import { HttpClient,HttpHeaders } from '@angular/common/http';
通过jsonp获取服务器数据(跨域的一种解决方案)
app.module.ts 引入
import {HttpClientModule,HttpClientJsonpModule} from '@angular/common/http'
imports: [
BrowserModule,
HttpClientModule,//注入
HttpClientJsonpModule,//注入
FormsModule //双向数据绑定 声明
],
npm install axios --save
app.module.ts
{
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
//双向数据绑定 引入
import {FormsModule} from '@angular/forms';
//引入HttpClientModule
import {HttpClientModule,HttpClientJsonpModule} from '@angular/common/http'
import { AppComponent } from './app.component';
import { NewsComponent } from './components/news/news.component';
import { HomeComponent } from './components/home/home.component';
import { HeaderComponent } from './components/header/header.component';
import { TransitionComponent } from './components/transition/transition.component';
import { FooterComponent } from './components/footer/footer.component';
//引入服务
import { HttpserviceService } from './services/httpservice.service';
@NgModule({
declarations: [
AppComponent,
NewsComponent,
HomeComponent,
HeaderComponent,
TransitionComponent,
FooterComponent
],
imports: [
BrowserModule,
HttpClientModule,//注入
HttpClientJsonpModule,
FormsModule //双向数据绑定 声明
],
providers: [HttpserviceService],//注入服务
bootstrap: [AppComponent]
})
export class AppModule { }
}
httpservice.service.ts
{
import { Injectable } from '@angular/core';
//哪里用就引入axios
import axios from 'axios';
@Injectable({
providedIn: 'root'
})
export class HttpserviceService {
constructor() { }
axiosGete(api:any){
return new Promise((resolve,reject)=>{
axios.get(api).then(function(response){
resolve(response)
})
})
}
}
}
new.component.ts
{
import { Component, OnInit,ViewChild } from '@angular/core';
//当作一个服务
import { HttpClient,HttpHeaders } from '@angular/common/http';
//引入服务
import { HttpserviceService } from '../../services/httpservice.service';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.scss']
})
export class NewsComponent implements OnInit {
public list:any[]=[]
constructor(public http:HttpClient,public httpService:HttpserviceService) { }
ngOnInit(): void {
}
ngAfterViewInit(): void {
}
ngOnDestroy(): void {
}
getData(){
//服务器必须允许跨域
let api='http://a.itying.com/api/productlist';
//rxjs
this.http.get(api).subscribe((response:any)=>{
console.log(response)
this.list=response.result
})
}
doLogin(){
//固定写法/手动设置请求的类型
const httpOptions={headers:new HttpHeaders({'Content-Type':'application/json'})}
//存在跨域
let api='http://127.0.0.1:3000/dologin';
this.http.post(api,{'username':'koo','age':22},httpOptions).subscribe((response)=>{
console.log(response)
})
}
getJsonpData(){
//jsonp请求 服务器必须支持jsonp 测试在后面加入callback=xxx 本地方法服务器执行jsonp
//http://a.itying.com/api/productlist?callback=xxx 返回xxx()ok
//http://a.itying.com/api/productlist?cb=xxx 一些叫cb
let api='http://a.itying.com/api/productlist';
this.http.jsonp(api,'callback').subscribe((response)=>{
console.log(response)
})
}
getAxiosData(){
let api='http://a.itying.com/api/productlist';
this.httpService.axiosGete(api).then(res=>{
console.log(res)
})
}
}
}
new.component.html
{
<button (click)='getData()'>get请求数据
<button (click)='doLogin()'>post请求数据
<button (click)='getJsonpData()'>通过jsonp获取服务器数据(跨域的一种解决方案)
<button (click)='getAxiosData()'>通过第三方模块获取服务器的数据
- {{item.title}}
65.Angular中的路由 路由概述 配置路由 路由重定向 路由选中 默认路由(1)
ng new project
router y
app.html
app.module.ts
import { AppRoutingModule } from './app-routing.module';
imports: [
BrowserModule,
AppRoutingModule
],
app-routing.module.ts
{
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
//使用路由 引入组件
import { HomeComponent } from './components/home/home.component';
import { NewComponent } from './components/new/new.component';
import { ProductComponent } from './components/product/product.component';
//配置路由
const routes: Routes = [
{path:'home',component:HomeComponent},
{path:'new',component:NewComponent},
{path:'product',component:ProductComponent},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
}
ngrouter-link 快捷键
跳转
html
{
//匹配不到路由的时候加载的组作或者跳转的路由
{path:'',component:HomeComponent},//任意的路由
// {path:'',redirectTo:'home'},
ngrouter**active
<a [routerLink]="[ '/home' ]" routerLinkActive="active">首页
<a [routerLink]="[ '/new' ]" routerLinkActive="active">新闻
<a [routerLink]="[ '/product' ]" routerLinkActive="active">商品
routerLinkActive选中状态
66.Angular中路由传值(get传值 动态路由) 以及通过js跳转路由(2)
get传值
new.component.ts
{
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-new',
templateUrl: './new.component.html',
styleUrls: ['./new.component.scss']
})
export class NewComponent implements OnInit {
public list:any[]=[]
constructor() { }
ngOnInit(): void {
for(var i=0;i<10;i++){
this.list.push(这是第${i}条数据
)
}
}
}
}
new.component.html
{
new works!
<a [routerLink]="[ '/newcontent' ]">新闻详情 }
newcontent.component.ts
{
import { Component, OnInit } from '@angular/core';
//获取get传值
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-newcontent',
templateUrl: './newcontent.component.html',
styleUrls: ['./newcontent.component.scss']
})
export class NewcontentComponent implements OnInit {
constructor(public route:ActivatedRoute) { }
ngOnInit(): void {
// console.log(this.route.queryParams)
this.route.queryParams.subscribe((data)=>{
console.log(data)
})
}
}
}
动态路由
app-routing.module.ts
{path:'newcontent/:aid',component:NewcontentComponent},
{
import { Component, OnInit } from '@angular/core';
//获取get传值
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-newcontent',
templateUrl: './newcontent.component.html',
styleUrls: ['./newcontent.component.scss']
})
export class NewcontentComponent implements OnInit {
constructor(public route:ActivatedRoute) { }
ngOnInit(): void {
//get传值
this.route.queryParams.subscribe((data)=>{
console.log(data)
})
//动态路由
this.route.params.subscribe((data)=>{
console.log(data)
})
}
}
}
js跳转
{path:'productcontent/:pid',component:ProductcontentComponent},
product.component.html
{
product works!
跳转到商品详情
<button (click)="goNews()">get传值跳转路由
}
product.component.ts
{
import { Component, OnInit } from '@angular/core';
//js跳转需要模块
import { Router,NavigationExtras } from '@angular/router';
@Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.scss']
})
export class ProductComponent implements OnInit {
constructor(public router:Router) { }
ngOnInit(): void {
// constructor ngOnInit ngAfterViewINit ngOnDestroy
}
goNewsContent(){
//路由跳转 普通路由和动态路由
this.router.navigate(['/newcontent/','1234'])
}
goHome(){
this.router.navigate(['/home'])
}
goNews(){
//跳转并且进行get传值
let queryParams:NavigationExtras={
queryParams:{'aid':123}
}
this.router.navigate(['/new'],queryParams)
}
}
}
67.Angular路由的嵌套 父子路由(3)
69
app-routing.module.ts
import { WelcomeComponent } from './components/home/welcome/welcome.component';
{path:'home',component:HomeComponent,
children:[
{path:'welcome',component:WelcomeComponent},
{path:'setting',component:SettingComponent},
{path:'**',redirectTo:'welcome'}
]
},
html
{
系统设置 右侧
}
68.更多实战访问《IT营官网》
没资料 看下 see