我的typescript学习心得
文章目录
- 1. ts基本语法
- 数值
- 布尔
- 枚举
- void null undefined
- Never
- Symbol
- const
- 2 数组和元组
- 数组
- 数组方法
- 数组解构
- 数组遍历
- 多维数组
- 元组
- 元组特点
- 3 迭代器和生成器
- 迭代器
- 生成器
- 4 函数
- 变量提升
- 箭头函数和普通函数的区别
- 构造函数
- 函数参数化
- 函数重载
- 5 对象
- 类
- 继承
- 多态
- static
- 访问修饰符
- abstract
- 6 装饰器
- 类装饰器
- 方法装饰器
- 属性装饰器
- 装饰器调用顺序
- 7 接口
- 8 namespace
- 外部模块
- AMD
- CMD
- CommonJS
- UMD
- SystemJS
- ES6
- 9 模块解析策略
- Classic
- Node
- 10 声明合并
- 11 泛型
- 类型断言
- 泛型定义
- TS扩展语法
- A 扩展全局对象
- B 扩展外部模块
- C 扩展当前函数或类
- D 特别注意
- 原型
用于静态类型检验,通俗讲就是定义的各种变量和数据类型都需要一个 类型
去限定,包括但不限于使用:内置类型 Array
和自定义类型 interface XX{}
,对于未定义类型,默认为 Any
1. ts基本语法
语句使用;
分割,建议显示加上。文件后缀为.ts
声明变量:let a:string = "pp"
,使用:类型
来限定
需要特别注意的是,形如string类型和String类类型是两个不同类型!!
ts类型分为:
- any:不写类型就是这个默认
- 原始类型:number boolean string symbol void null undefined enum(8类)
- 对象类型:
{}
- 联合类型:
类型1 | 类型2
,类型为其中一种:let x: t1 | t2 = <t1 | t2>{}
,x只能访问t1和t2中公有的属性方法,可以使用类型断言来使用独有方法。 - 交叉类型:
类型1 & 类型2
,类型为两者的并集:let x: t1 & t2 = <t1 & t2>{}
- 类型参数
类型别名:type 别名 = 类型or表达式
type a = ()=>void;
type b = string | number;
特殊的:|
如果可以用于表示值为其中之一
type a = 'x' | 'y' | 'z';
function m(s:a){} // 表明,s只能接受xyz中的任一个字符
null和 undefined是所有类型的子类
any是所有类型的父类
数值
二进制:0b1010
八进制:0o744
十六进制:0xf00d
Number和number两种类型不相同!!
布尔
只有true和false,且不可用1和0来代替
let a:boolean = new Boolean(1) // 错误
let a:boolean = Boolean(1) // 正确
直接调用Boolean()方法会将入参转换为布尔值
枚举
一个对js类型的补充,默认从0开始编号,没显式编号的顺接前面的编号+1
enum Days {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
let today: Days = Days.Mon;
let today: Days = 1; // 和上面含义相同
枚举有常量枚举,这种会在编译期删除,直接替换成数字。非常量枚举会被编译成一个对象,属性为枚举名和枚举值的双向映射
const enum D{a,b,c};
let x:D = D.a;// 编译后结果只有let x = 0;enum B{a,b,c};
// 编译后生成
var B;
(function (B){B[B['a']=0]='a';B[B['b']=1]='b';B[B['c']=2]='c';
}(B||B={})
void null undefined
void:用于声明函数的返回值
undefined:用于表示值没有初始化
null:表示初始化为null
Never
表示不会出现值,用于无限循环函数和异常出错函数中
function error(msg:string):never{throw new Error(msg);
}
function ilop():never{while(true){}
}
Symbol
Symbol函数接收一个字符串作为参数,只是作为一个描述,用于区分Symbol实例。相同参数返回的值不相等。
该函数不能使用new,因为返回值是一个值,不能添加属性。
let s = Symbol('name')
const
用于声明常量类型,声明的基础类型变量不可改变,声明的引用类型变量地址不可改变
特殊的,如果想让引用类型变量内容也不可变,可以使用Object.freeze()
Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。
2 数组和元组
数组
数组中的元素类型,必须是与定义类型一致!
- 数组声明
// 简单声明
let a:string[] = ['a','b']
let b:(string|number)[] = [1,'a']
// 复杂声明
let c:Array<string> = ['a','b']
let d:Array<string|number> = [1,'a']// 特殊的any,不限制类型
let e:any[] = [1,'a',false]
- 初始化
静态初始化:let a = [1,2,3]
,默认推断类型为number
对象初始化:let a = new Array()
let a = new Array(); // 创建一个any类型空数组
let b = new Array(2); // 创建一个长度为2的any类型空数组
let c = new Array(1,2); // 创建一个[1,2]类型为number的数组
let d = new Array<number>(5); // 创建一个长度为5的number类型空数组
数组未初始化时,默认为undefined
删除元素
使用delete a[0]
删除,只会将该索引处元素删除,数组长度不变!给数组添加属性
declare global{interface Array<T>{run():void;}
}
Array.prototype.run = ()=>console.log('run');
- 判断数组
let a = [1,2]
Array.isArray(a) // true 该方法是ES5的方法
a instanceof Array // true
Object.prototype.toString.call(a) // [object Array]
数组方法
- concat:
数组1.concat(数组2)
返回连接结果,原数组不变 - every:检测每个元素是否都满足条件,全满足返回true,否则返回false
- filter:按条件过滤元素,返回过滤后数组,原数组不变
- forEach:遍历元素
- indexOf:从左到右匹配元素,返回第一个索引
- lastIndexOf:从右向左
- join:使用入参字符将数组连接成字符串
- map:遍历元素并返回等长数组,不可break
- pop:删除最后一个元素,长度-1
- push:增加一个新元素,长度+1
- reduce:累加器,
[1,2,3].reduce((x,y)=>x+y,1)
接收一个回调函数,还有一个初值。回调函数接收两个值:第一个为初值或上一次累加返回的值,第二个为当前遍历的值。 - reduceRight
- reverse:反转数组,改变原数组
- sort:排序,入参为排序器函数,该函数返回值>0则会交换位置,改变原数组
- shift:删除并返回第一个元素,长度-1
- unshift:从头增加n元素,长度+n
- slice:切片,返回新数组,
slice(start,end)
,start和end可为正负,截取方向取决于第二个参数,第二个参数为正则往右截取,原数组不变 - some:检测数组中是否有满足条件的元素,有就返回true
- find:检测数组是否存在满足条件元素,有就立刻返回该值并结束
- splice:增删数组,
splice(index,del_num[,a,b,c..n])
,从何处起,删除多少个,新增元素序列,改变原数组 - toString:用逗号连接数组输出字符串
数组解构
let [a,b,c] = [1,2,3];
let [a,[b],c] = [1,[2],3];
let [a,b] = [1]; // b为undefined
let [a,b=2] = [1];let x=1,y=2;
[x,y]=[y,x]; // 解构交换
数组遍历
for()
循环遍历for(let i in a)
,遍历对象中的可枚举属性for(let v of a)
,使用对象的迭代器遍历forEach
,无返回值,不可breakmap
,返回等长数组,不可break
多维数组
- 定义
let a:string[][];
let b:Array<Array<string>>;
- 初始化
// 空值初始化
let a:string[][] = [];
let b:string[][] = new Array<Array<string>>();
// 静态初始化
let a:string[][] = [['1'],['2']]
let b:string[][] = new Array<Array<string>>(['1'],['2']);
元组
特点:数据类型不要求统一,相当于固定了每个位置的类型
定义时[]
不可省略,且初始化个数和声明中类型个数一致,如果访问越界,编译报错
let a:[string,number,number] = ['1',1,1]
元组特点
元组定义后无法通过索引来新增元素,只能调用方法,且插入的元素类型需要和定义时兼容,且不能越界解构,其余和数组一样。
3 迭代器和生成器
迭代器
是一种特殊对象,包括一个next()方法,调用该方法可以返回一个对象,包括value和done两个属性。value表示当前迭代的值,done表示当前是否迭代完成。当一个对象包含Symbol.iterator属性,则表明该对象可迭代(该属性调用后要求返回一个迭代器对象)。
// 迭代器对象
{[Symbol.iterator]:function(){return{next(){return {value:1,done:true}}}}
}
// 示例
function getIt(arr:number[]){...return {next:function(){...return {done:,value:}}}
}
// 调用
let it = getIt([1,2,3])
it.next(); // 每次调用返回一个值,且下次调用返回下一个值,直到内部done为true结束
生成器
生成器通过在函数名上加*
来实现,使用yield
来返回,并且下次从返回处恢复继续执行。调用生成器会返回一个迭代器。
// 定义
function* a () {}
function *a () {}
let a = function* () {}// 示例
function *genIt(){yield 1;yield 2;yield 3;
}let it = genIt(); // 获得一个迭代器
it.next() // {value:1,done:false}
it.next() // {value:2,done:false}
it.next() // {value:3,done:false}
it.next() // {value:undefined,done:true}
注意:不可以使用箭头函数创建生成器
让对象可迭代:
let obj = {*[Symbol.iterator](){...yield ...;...}
}
4 函数
先看函数的一个典型定义:
function func(a:string,b:string|number,c:boolean=true,d?:number):string{return '1'} // ?:表示可选参数,可传可不传,必须放在最后,类似的有剩余参数:...a
let func = (a:string,b:string|number,c:boolean=true,d?:number):void=>{}
函数名称:如果使用function定义,函数名就是定义时的,如果使用表达式定义,则函数名就是变量名,即使function后有函数名(该函数名只能内部使用)。
函数名一经定义不能被重新赋值
返回类型可以省略
function a(){} // 函数名为a
let b = function a(){} // 函数名为b
b.name = 'c' // 无效
变量提升
使用var声明的变量会被提升到代码顶部,使用function定义的函数也会提升,但是函数表达式不会提升,即只作为变量被提升,编译器不知道其为函数,所以如果在定义前调用会报错。
箭头函数和普通函数的区别
普通函数:function a(){}
包含length,name,caller,arguments四个属性还有一个prototoye
属性,this动态绑定到调用者(如果函数独立调用,在严格模式下this为undefined,非严格模式下为window)
箭头函数:let a = ()=>{}
只包含lenght,name属性,this绑定为定义环境中的this
箭头函数和普通函数的__proto__
都指向Function的原型
构造函数
构造函数常用来创建一个类对象,创建的该对象的构造函数===定义的构造函数,使用new来创建:new Func()
普通函数也可以被new,如果有返回值则被忽略。
new的过程即调用该构造函数的过程,如果其中包括this等,会在创建的类中进行属性赋值初始化等
函数参数化
即将函数作为参数进行传递,也很简单,看示例就懂:
function a(x:string,y:(msg:string)=>number){}
函数重载
js不支持函数重载,ts中通过不同声明来控制函数重载,实际调用的为同一个函数,只是内部做了判断
function a(x:number);
function a(x:number,y:number);function a(x:number,y?:number){}a(1)
a(1,2)
5 对象
生成一个对象,并给对象添加属性,这个是js中常见做法,如:
// js
let obj = {}
obj.name = "pp"
// ts中不支持直接添加属性,因为生成的obj模板是Object,不存在name属性
// ts中需要动态添加属性,则必须定义一个同名接口类型(在查询时先查接口?)
let obj = {}
interface obj{[key:string]:any;
}
obj.name = "pp"
duck-typing鸭子类型。即,如果某部分表现形式或结果相同,我们把他们看作同一种类型,相当于按某种特征归类
let type_a = [] function getA(x){if(x.xxx ===xxx){type_a.push(x)} // 只要满足某个条件就视为一类 }
类
和js相同,只不过在定义类属性时需要加上类型
// 定义
class xxx {a:string;b:number;constructor(a:string){this.a = a}funca():string{return this.a}funcb():void{console.log(this.b)}
}// 实例化
let XXX = new xxx(1);
注意:构造函数只有一个!
继承
// 继承,只支持单继承
class xxx extends yyy{}
注意:在构造中访问this前一定要先调用super
子类继承父类后可以定义子类独有的方法,也可以重写父类的方法,也可以定义和父类相同的属性,不过属性类型必须相同或为any
多态
由于ts不能直接实现多态,所以,对于父类引用如果想指向子类对象,必须使用断言:as
或<>
let parent = child as Parent;
let parent = <Parent>child;
断言后的对象只能调用该类型包含的方法和属性,无法使用子类方法和属性
和Java不同,对于Java来说,父类引用指向子类对象时,实际调用的规则为:父类的成员变量和静态方法,子类的重写方法。口诀为:成员变量,静态方法看左边;非静态方法:编译看左边,运行看右边。
重载overload和重写override
重载:函数名相同,参数不同,与返回值无关(发生在同一个类中)
重写:函数名、参数和返回值都相同(发生在继承类中)
static
使用static定义的类属性为静态属性,无需实例化,直接使用类名调用。
访问修饰符
ts有三种访问修饰符:
- public:默认
- protected:只能自己和被子类访问,在类中访问,不能通过示例对象访问
- private:只能自己访问
abstract
抽象类可以包含签名也可以包含实现体,可以使用访问修饰符控制,不可以使用private,而且不可以缩小访问权限
抽象方法不能有实现体
abstract class A{protected abstract x: number;public abstract run():void;a:string='1';
}
6 装饰器
类装饰器
在类前定义,在执行到该类时就调用注解对应函数,接收构造函数作为参数,返回值如果是函数会替换原来的构造函数,否则不替换。
不能在声明文件中使用,不能在外部上下文使用(declare的类)
@log
class A{constructor(){console.log("3")}
}
function log(constructor:Function):any{console.log(1)console.log(constructor.name);return function(){console.log("log-log");}}
console.log(2)
new A();// 1
// A
// 2
// log-log
方法装饰器
用于监听和修改方法,定义在类中方法上,接收
- 对于静态成员为构造函数,对于实例成员为类原型对象
- 成员名称
- 成员属性描述符,具备一些属性,可以用于控制该属性的访问和其他
在定义类时就会调用该注解返回的函数
class A{@m(100)greet(){console.log("4")}
}
function m(n:number):any{return function(target:any,propertyKey:string,descriptor:PropertyDescriptor){console.log("1")console.log(target,propertyKey,descriptor,n)}
}console.log("2")
let a = new A();
console.log("3");
a.greet();// 1
// {constructor: ƒ, greet: ƒ} greet {value: ƒ, writable: true, enumerable: false, configurable: true} 100
// 2
// 3
// 4
属性装饰器
声明在属性上,在解析到改行代码时就会调用装饰器函数,接收两个参数
function n(target:any,key:string){console.log(target,key)
}@log
class A{@nage:number=1;
}
let a = new A();
console.log(a.age);
装饰器调用顺序
属性和方法装饰器按照声明顺序调用,最后调用类装饰器。都在解析类的时候就被调用,无需实例化!!
7 接口
接口作用是给出类型约束:interface xxx{}
,接口不能加初始值和实现体,不能加访问修饰符
// 使用接口创建一个类型
interface IPerson{name:string;age:number;
}
// 作用1:限制入参类型
function a(person:IPerson){person.age++}
// 作用2:类实现接口
class Person implements IPerson{name='pp';age=1;
}
// 特殊的:接口也可以继承类,即把类当作接口使用,只使用其方法和属性签名
interface SuperPerson extends Person{fly:()=>void;
}
// 特殊的:类也可以实现类,原理同上
对于类来说,只能单继承类,但是可以多实现接口
对于接口来说,可以多继承接口,但是注意:如果多继承中包含同名属性,类型不同,则无法同时继承
接口继承类时,对于private和protected访问修饰符的属性也会继承。则该接口只能被该类的子类所实现!
接口中有一个特殊的关键字:readonly,限制一个属性只在构造中可修改,其余均只读
interface IPerson{name:string;readonly age:number;
}
class Person implements IPerson{name='pp';readonly age=0; // 此处不可省略readonlyconstructor(age:number){this.age = age}
}
ts具有
ReadonlyArray<T>
类型,与Array<T>
相似,只不过数组创建后不能被修改
只读属性不能使用const只能使用readonly,限定变量使用const,限定属性使用readonly
8 namespace
命名空间类似于java的包,现在ts对于内部模块称作命名空间,外部模块称作模块。
// 命名空间名称可以使用.来分割
namespace xxx.xxx{export class A{}export function B(){}// 嵌套export namespace xxx{export class C{}}
}
new xxx.xxx.xxx.C();
如果需要在命名空间外部调用内部的属性,则需要export导出才行
命名空间引入:一个namespace分布在多个文件中,可以使用///<reference path="xxx.ts"/>
来引入
tsc --outFile n_all.js .\xxx.ts
可以将xxx.ts命名空间中引入的所有命名空间合并输出
命名空间别名:import x_x_x = xxx.xxx.xxx;
然后可以直接调用:new x_x_x()
外部模块
如果一个文件不带顶级import或者export声明,则该文件内容被视为全局可见
模块加载器包含多种规范
AMD
典型的浏览器实现的AMD规范的库:requireJS
- 定义模块
采用define
函数来定义模块,接收一个或两个参数:
// a模块
// 一个参数:接收一个函数返回一个对象
define(function(){return{}})
// b模块
// 两个参数:接收一个依赖项数组,接收一个函数,参数为依赖项,返回一个对象
define(['a'],function(a){return{}})
其中:a和b表示当前模块以来的其余两个模块,依赖项和入参是一一对应的
- 使用
使用require.config()
来接收一个配置项,配置各种库位置(如果模块名和文件名相同,则可以不配置,会自动寻找),然后使用require()
函数来接收依赖项和回调函数
main.js文件内容:
// 如果引入远程外部库需要先配置地址,否则就应该放在本地
require.config({path:{jq:"http://xxx/jquery-1.11.1.min"}
});
require(['jq','a','b'],function($,a,b){// 待执行脚本内容
})
注意:只有依赖项全部加载完毕才会执行脚本
需要通过引入require模块并提供data-main参数来引入入口js文件!!
index.html文件内容:
<script type="text/javascript" src="require.js" data-main="main.js"></script>
CMD
国内发展而来,典型浏览器实现库:SeaJS,功能类似requireJS,定义和加载稍有不同
CMD认为一个js就是一个模块:define(id?,d?,factory)
,其中:
id为模块id,省略默认为文件名,
d为依赖,省略默认就近查找,
factory为函数:function(require,exports,module){}
- 定义模块
// a模块
define(function(require,exports,module){module.exports = {name:'pp'}
}
// b模块
define(function(require,exports,module){var a = require('a'); // 获取到a模块module.exports = {age:1}
}
// main.js
define(function(require,exports,module){var b = require('b'); // 获取到b模块// 此处使用了jq,由于没有require引入所以是全局变量,所以必须在index.html中手动引入$("div").html(123+b.age);
}
index.html
<script type="text/javascript" src="http://xxx/jquery-1.11.1.min"></script>
<script type="text/javascript" src="sea.js"></script>
<script>seajs.use(['main.js'],function(main){};)</script>
总结就是:define定义模块,require导入模块,在首页需要自己导入远程依赖,引入sea库,调用seajs.use(依赖数组, 回调函数)
注意:exports就是module.exports的一个拷贝,不能用于给模块赋值
CommonJS
每个文件就是一个模块,加载模块相当于加载module.exports属性,使用require同步加载模块,通过module.exports来导出模块
nodejs按照该规范实现的,由于是同步加载模块所以不适合浏览器端!(可以借助工具转换即可)
// 导出模块
var obj = {name:'pp'}
module.exports = obj;// 导入模块
// main.js
var a = require('./A.js')
直接node运行即可
UMD
整合CommonJS和AMD,用一个工厂函数来统一不同模块定义规范。判断支持commonjs,否则再判断支持amd,否则就暴露到全局。
SystemJS
通用模块加载器,支持nodejs、浏览器、commonjs、amd、全局模块对象和es6模块。语法类似amd
ES6
使用import和export导入导出,比较简单就不赘述了
import a,{aa} from './a';
...
export {};
export default xxx;
可以使用babel-node
来对es6进行转码到commonjs
9 模块解析策略
在导入模块时,目录有相对路径:"./a"
或非相对路径"axios"
ts有两种解析策略:Node和Classic,使用--moduleResolution
来指定,未指定则在使用--module AMD|System|ES2015
时为Classic,其他为Node
Classic
import a from './a';
// 查找路径为
/root/src/a.ts
/root/src/a.d.tsimport a from 'a';
// 查找路径为
/root/src/a.ts
/root/src/a.d.ts
/root/a.ts
/root/a.d.ts
/a.ts
/a.d.ts
Node
import x from 'x';
查找规则:
- x为内置模块,直接返回该模块
- x以
/
、./
或../
开头,将x当作文件依次查找:x.js x.json x.node,将x当作目录依次查找:x/package.json中的main字段 x/index.js x/index.json x/indexnode - x不带路径,查找当前路径下的node_module中,然后依次向上遍历每层的node_module
- not found
10 声明合并
在ts编译时会将同名的两个单独声明合并为一个声明,支持:namespace、interface、class
- 接口合并
接口合并,后面同名接口的属性会出现在合并后的靠前位置 - 命名空间合并
由于涉及导出和非导出的属性,对于非导出成员仅在原命名空间可见 - 命名空间和类合并
必须将类定义放在命名空间之前!合并后既是命名空间也是类 - 命名空间和函数合并
同上面相似,合并后可调用
11 泛型
类型断言
<类型>x
或者x as 类型
:表明x的类型为这种,断言后可调用该类型的方法
function a(x:string|number){if((<string>a).length){}
}
泛型定义
<T1,T2,T3>
中个数不限,符号可以多个,表示有多种类型
示例:
// 泛型函数
function func<T>(a:string,b:T):void{}
// 泛型类
class C<T>{}
// 泛型接口
interface i<T> {}
对于泛型变量,如果要使用其属性或方法,需要进行断言。
<T,K extends keyof T>
其中K表示,T中公共属性名的集合中的一个元素,即K是T的一个属性
TS扩展语法
A 扩展全局对象
declare global {interface Number{run():void;}
}Number.prototype.run = ()=>console.log("run");let a = 1;
a.run();
B 扩展外部模块
import {Person} from './Person';
let person = new Person("pp",1);
declare module './Person'{interface Person{run():void;}
}Person.prototype.run = ()=>console.log("run");
person.run()
C 扩展当前函数或类
不能对箭头函数进行扩展,因为没有prototype
// 构造函数
function C(name:string){this.name = name;
}
let c = new C("pp");
console.log(c.name)
// 新增属性方法,直接操作prototype
C.prototype.run = ()=>console.log("run");
c.run();// 普通函数
function b(){}
// 新增属性方法,直接操作prototype
b.prototype.age=1
new b().age // 1// 类
class D{}
let d = new D();// 新增属性方法,定义接口
interface D{run():void;
}
D.prototype.run = ()=>console.log("D");
d.run();
D 特别注意
ts中无法给空对象动态添加属性和方法,如果非要使用,可以:
let a = {}
a.name = "pp" //报错// 定义一个接口,使用任意类型
interface E{[key:string]:any;
}
let obj:E = {}obj.run = ()=>console.log("run")
原型
定义的函数和类等对象都包含一个prototype
(只有定义出的对象拥有)和__proto__
(定义和实例对象拥有),称为当前对象的两个原型属性。
一般而言,对象中查找属性,是沿着__proto__
一层一层往上查
prototype:是一个对象,包含constructor:指向定义对象本身__proto__指向Object.prototype==={}.__proto__,再往下遍历就指向null__proto__:是一个对象指向当前定义对象所属实例的原型
对于一个对象的__proto__
如果是函数就指向Function原型,如果是类指向父类原型,如果没有父类指向Function原型,Function原型的原型指向Object原型,Object原型指向null。
我的typescript学习心得相关推荐
- Java EE学习心得
–Java EE学习心得 1. 称为编程专家的秘诀是: 思考-----编程--------思考------编程--.. 编程不能一步到位,不能一上来就编,必须先思考如何写,怎样写?然后再编程 ...
- Assembly学习心得
http://blog.csdn.net/etmonitor/ Assembly学习心得 说明: 最近开始准备把学到的.NET知识重新整理一遍,眼过千遍不如手过一遍,所以我准备记下我的学习心得,已备参 ...
- 对于mysql存储过程感想_存储过程学习心得
存储过程学习心得 (2014-12-28 17:28:06) 标签: it 我使用过几次SQL Server,但所有与数据库的交互都是通过应用程序的编码来实现的.我不知到在哪里使用存储过程,也不了解实 ...
- 好程序员Web前端教程分享Vue学习心得
为什么80%的码农都做不了架构师?>>> 好程序员Web前端教程分享Vue学习心得,Vue是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向 ...
- 大学计算机课英语心得体会,关于计算机网络辅助大学英语教学的思考学习心得...
关于计算机网络辅助大学英语教学的思考学习心得 [摘要]计算机网络辅助教学可以增强学生的学习兴趣,提高他们自觉学习的能力,因而得到了大多数学生的认可,取得了比较显著的成效.计算机网络辅助教学也对大学英语 ...
- RUST直接升钢指令_[译]参照TypeScript学习Rust-part-1
[译]参照TypeScript学习Rust-1 · 前端在线regx.vip 对于前端,笔者比较认可Rust作为前端开发技术栈投资的,本文系列翻译旨在分享.学习Rust这门语言. Rust常常被认为 ...
- 我的MYSQL学习心得(十六) 优化
原文:我的MYSQL学习心得(十六) 优化 我的MYSQL学习心得(十六) 优化 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看 ...
- Spring Framework------version4.3.5-----Reference学习心得-----总结
1.Spring Framework概述: 有很多可用版本,网址http://projects.spring.io/spring-framework/ 2.Spring Framework ...
- 计算机基础与应用(上)笔记总结,计算机基础学习心得体会范文(通用3篇)
计算机基础学习心得体会范文(通用3篇) 当我们对人生或者事物有了新的思考时,好好地写一份心得体会,这样可以记录我们的思想活动.那么要如何写呢?以下是小编精心整理的计算机基础学习心得体会范文(通用3篇) ...
最新文章
- linux下用js生成xml,js2xml:将javascript字符串转换为xml
- RabbitMQ(二):RabbitMQ高级特性
- stl_config.h基本宏
- 学习Kotlin(三)类和接口
- android 定时器5秒执行一次,如何在android中每30秒执行一次查询?
- 访问IIS时,名称以无效字符开头。。。解决方案
- 中石油训练赛 - Count the Even Integers(Java高精度运算+找规律)
- html, xhtml和xml
- Java Thread Status(转)
- codeforces 940E Cashback 有趣的dp
- 浅谈离线化方案的探索,跨容器
- LeetCode 807. 保持城市天际线
- linux java socket编程_深入学习socket网络编程,以java语言为例
- C++ Primer学习笔记(一)
- java se环境变量_Windows 7中配置JDK(Java SE)环境变量
- (转载)tomcat5下jsp出现getOutputStream() has already been called for this
- 刘海I关于iPhone X 的适配
- 天正多条线段长度lisp下载_如何快速计算cad中多条多段线的总长
- 计算机技术领域当前的主流技术及其社会需求调查报告
- 手机短信校验(前端js)