HTML5 API
cooke
存储小于4k,初次请求由浏览器返回,可过期。不够安全
WebStorage
本地存储localstorage,不过期
let xiejie = {"name":"xiejie","age":18};//对象
localStorage.setItem("info",JSON.stringify(xiejie));//转JSON,以键值对存入
xiejie = JSON.parse(localStorage.info);//读取
会话存储sessionstorage
存储在服务器,安全
storage事件
本地文件无法触发storage事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
let name = localStorage.getItem("name");
let age = localStorage.age;
console.log(`name:${name},age:${age}`);
window.addEventListener("storage",(e)=>{
console.log(`${e.key}:${e.oldValue}→${e.newValue}`);
console.log(`save:${e.storageArea}`);
console.log(`url:${e.url}`);
},true);
</script>
</body>
</html>
JQuery
注意事项
一种JavaScript库,用于更方便的操作dom节点
有两个版本的 jQuery 可供下载:
- Production version - 用于实际的网站中,已被精简和压缩。
- Development version - 用于测试和开发(未压缩,是可读的代码)
这两个版本都可以从 jQuery.com 下载。
或使用cdn(谷歌版)
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js">
</script>
</head>
一般使用 $(document).ready(function(){ 操作函数 }) 来防止加载未完成就进行JQuery读取的错误
如果您的网站包含许多页面,并且您希望您的 jQuery 函数易于维护,那么请把您的 jQuery 函数放到独立的 .js 文件中
如果JQuery的$名称与其他JS库冲突,使用 var jq=jQuery.noConflict(),帮助您使用自己的名称(比如 jq)来代替 $ 符号
获取节点
选择器
$(‘选择器’)即可选取节点进行操作
$("p").hide()
//隐藏所有 <p> 元素。
$("p.intro")// 选取所有 class="intro" 的 <p> 元素。
语法 | 描述 |
---|---|
$(this) | 当前 HTML 元素 |
$(“p”) | 所有 元素 |
$(“p.intro”) | 元素中的所有 class=“intro” 元素 |
$(“ul li:first”) | 每个
|
( " [ h r e f ("[href ("[href=‘.jpg’]") | 所有带有以 “.jpg” 结尾的属性值的 href 属性 |
$(“div#intro .head”) | id=“intro” 的
元素中的所有 class=“head” 的元素
|
过滤器
基本过滤器
selector:first 获取所有已选择到的元素中的第一个元素
selector:last 获取所有已选择到的元素中的最后一个元素
selector:even 获取所有已选择到的元素中的索引为偶数的元素
selector:odd 获取所有已选择到的元素中的索引为奇数的元素
selector:eq(index) 获取所有已选择到的元素中的索引为index的元素
selector:lt(num) 获取所有已选择到的元素中的索引值小于num的元素
selector:gt(num) 获取所有已选择到的元素中的索引值大于num的元素
selector1:not(selector2) 获取所有已选择到的元素中的除了selector2的元素
selector:header 获取所有已选择到的元素中的标题元素(h1~h6)
内容过滤器
selector:contains(text)
获取所有已选择到的元素中文本包含text的元素
selector:empty
获取所有已选择到的元素中的空元素(没有子节点)
selector:parent
获取所有已选择到的元素中的非空元素(有子节点),如$("div:parent");
selector1:has(selector2)
获取所有已选择到的元素中包含selector2的元素,如$("div:has('span')");
可见性过滤器
1)不占据屏幕空间
display:none;
<input type="hidden">
2)占据屏幕空间
visibility:hidden;
opacity:0;//透明度为0
使用:
:visible 选择所有占据屏幕空间的元素
:hidden 选择所有不占据屏幕空间的元素
属性过滤器
selector[attrKey]
获取所有已选择到的元素中具有属性attrKey的元素
selector[attrKey=attrVal]
获取所有已选择到的元素中具有属性attrKey,并且属性值为attrVal的元素
selector[attrKey^=attrVal]
获取所有已选择到的元素中具有属性attrKey,并且属性值为以attrVal开头的元素
selector[attrKey$=attrVal]
获取所有已选择到的元素中具有属性attrKey,并且属性值为以attrVal结尾的元素
selector[attrKey*=attrVal]
获取所有已选择到的元素中具有属性attrKey,并且属性值为包含attrVal的元素
selector[attrKey!=attrVal]
获取所有已选择到的元素中具有属性attrKey,并且属性值不为以attrVal的元素或者没有属性attrVal的元素
后代选择器
selector:nth-child(index)
获取每个selector元素中索引为index的子元素。【注意】index从1开始
selector:first-child
获取每一个selector元素中的第一个子元素(每个父元素的第一个子元素)
selector:last-child
获取每一个selector元素中的最后一个子元素(每个父元素的最后一个子元素)
selector:only-child
获取每一个selector元素中的独生子子元素(每个父元素如果只有一个孩子元素,获取该元素)
selector:first-of-type
获取每个selector元素中每种类型子元素中的第一个
selector:last-of-type
获取每个selector元素中每种类型子元素中的最后一个
表单过滤器
:checked 选取所有被选中的元素,用于复选框、单选框、下拉框
:selected 选取所有被选中的元素,该选择器只适用于<option>
:focus 选取当前获取焦点的元素
:text 选取所有的单行文本框(<input type="text">)
:password 选取所有的密码框
:input 选取所有的<input>,<textarea>,<select>,<button>元素。
*注意,$(":input")是选中可以让用户输入的标签元素;而$("input")是选择名字为input的标签元素。*
:enable 选取所有可用元素,该选择器仅可用于支持disable属性的html元素。(<button>,<input>,<optgruop>,<option>,<select>,<textarea>)
:disable 选取所有不可用元素,该选择器也仅可用于支持disable属性的html元素。
:radio 选取所有的单选框
:checkbox 选取所有的多选框
:submit 选取所有的提交按钮
:image 选取所有的input类型为image的表单元素
:reset 选取所有的input类型为reset的表单元素
:button 选取所有的input类型为button的表单元素
:file 选取所有的input类型为file的表单元素
节点操作
创建
var newTd = $("<td></td>")//创建元素节点:
var newTd = $("<td>文本内容</td>")// 创建文本节点:
插入
1) $A.append(B)
将B追加到A的末尾处,作为它的最后一个子元素
2) $A.appendTo(B)
将A追加到B的末尾,作为它的最后一个子元素
3) prepend()
$A.prependTo(B)
将A追加到B的前面,作为它的第一个子元素
$A.after(B)
在A之后追加B,作为它的兄弟元素
$A.insertAfter(B)
在B之后追加A,作为它的兄弟元素
$A.before(B)
在A之前追加B,作为它的兄弟元素
$A.insertBefore(B)
在B之前追加A,作为它的兄弟元素
删除
remove([selector])
从DOM中删除所有匹配的元素,返回值是一个指向已经被删除的节点的引用,可以在以后再使用这些元素。
该方法会移除元素,同时也会移除元素内部的一切,包括绑定的事件及与该元素相关的jQuery数据。
detach([selector])
与remove()类似,但是detach()保存所有jQuery数据和被移走的元素的相关联事件。
empty()
无参数。从DOM中清空集合中匹配元素的所有的子节点。
操作CSS
$("p").css("background-color","red");//把所有 p 元素的背景颜色更改为红色
$("p").listClass('类名')//为节点添加类名
常用方法
$(‘选择器’).方法
使用了一个方法之后仍然会返回原节点,所以可以: 节点.方法.方法…
获取位置
- position() - 设置或返回所选元素相对于父级元素的偏移
- offset() - 设置或返回所选元素相对于文档的偏移
- srcollTop() - 滚动的
获取内容
三个简单实用的用于 DOM 操作的 jQuery 方法:
- text() - 设置或返回所选元素的文本内容
- html() - 设置或返回所选元素的内容(包括 HTML 标记)
- val() - 设置或返回表单字段的值
获取属性 - attr()
显示隐藏hide
通过 jQuery,您可以使用 hide() 和 show() 方法来隐藏和显示 HTML 元素:
$(selector).hide(speed,callback);
$(selector).show(speed,callback);
可选的 speed 参数规定隐藏/显示的速度,可以取以下值:“slow”、“fast” 或毫秒。
可选的 callback 参数是隐藏或显示完成后所执行的函数名称。
通过 jQuery,您可以使用 toggle() 方法来切换 hide() 和 show() 方法
jQuery 拥有下面四种 fade 方法:
- fadeIn(speed,callback) 淡入
- fadeOut(speed,callback) 淡出
- fadeToggle(speed,callback) 切换
- fadeTo(speed,opacity,callback) 指定的透明度淡入淡出
动画animate
$(selector).animate({params},speed,callback);
必需的 params 参数定义形成动画的 CSS 属性。
可选的 speed 参数规定效果的时长。它可以取以下值:“slow”、“fast” 或毫秒。
可选的 callback 参数是动画完成后所执行的函数名称。
//把 <div> 元素移动到左边,直到 left 属性等于 250 像素为止
$("button").click(function(){
$("div").animate({left:'250px'});
});
可以用 animate() 方法来操作所有 CSS 属性 !不过,需要记住一件重要的事情:当使用 animate() 时,必须使用 Camel 标记法书写所有的属性名,比如,必须使用 paddingLeft 而不是 padding-left
同时,色彩动画并不包含在核心 jQuery 库中。
也可以定义相对值(该值相对于元素的当前值)。需要在值的前面加上 += 或 -=:
$("button").click(function(){
$("div").animate({
left:'250px',
height:'+=150px',
width:'+=150px'
});
});
滑动slide
jQuery 拥有以下滑动方法:
- slideDown(speed,callback)
- slideUp(speed,callback)
- slideToggle(speed,callback)
面向对象
面向过程:根据事件需求来写代码
面向对象:找到对象,调用功能方法
obj{
属性
方法
}
原型对象(构造函数)
主要方法
- _ _ proto _ _
- prototype
- constructor 属性,找构造函数
- A instanceof B 操作符,判断A是否是B构造出来的
- hasOwnPrototype() 判断一个属性是对象自身私有的还是从原型继承的
构造本身是function函数,首字母大写,有原型prototype属性,箭头函数没有
JavaScript没有类,通过构造函数来模拟类
每一个对象都有一个原型对象,通过 _ _ proto _ _ 方法来访问原型对象,找寻的终点是null,所以null没有原型对象
console.log(Object.__proto__.__proto__.__proto__);//null
它的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(可以理解为父对象)里找,如果父对象也不存在这个属性,则继续往父对象的__proto__属性所指向的那个对象(可以理解为爷爷对象)里找,如果还没找到,则继续往上找…直到原型链顶端null
①**_ _ proto _ _和constructor属性是对象所独有的;② prototype属性是函数所独有的**,因为函数也是一种对象,所以函数也拥有 _ _proto _ _和constructor属性。
let Test = function (name, age) {
this.name = name;
this.age = age;
// return { save: '我是返回的对象' };//显式返回,相当于上面的没用
};
//添加原型方法
Test.prototype.show = function () {
console.log(this);
};
let obj1 = new Test('lxd', 22);
// obj1.show();
console.log(obj1.__proto__);
console.log(Test.prototype);
console.log(obj1.constructor);
原型链
通过_ _proto _ _属性将对象连接起来的这条链路即我们所谓的原型链。
prototype属性的作用就是为函数所实例化的对象们设置公用的属性和方法
若Foo构造函数new出了f1,就有f1. _ _proto _ _ === Foo.prototype,两者指向的同一个东西
let Test = function (name, age) {
this.name = name;
this.age = age;
// return { save: '我是返回的对象' };//显示返回,相当于上面的没用
};
//添加原型方法
Test.prototype.show = function () {
console.log(this);
};
let obj1 = new Test('lxd', 22);
// obj1.show();
console.log(obj1.__proto__);
console.log(Test.prototype);
console.log(obj1.constructor);
constructor属性的含义就是指向该对象的构造函数,所有函数(此时看成对象了)最终的构造函数都指向Function。
封装
//封装(限制访问权限)
console.log('=======');
let stu = {};
Object.defineProperties(stu, {
stuAge: {
get: function () {
return 18;
},
},
stuName: {
get: function () {
return 'laoliang';
},
},
});
console.log(stu.stuName); //laoliang
console.log(stu.stuAge); //18
//单个属性设置存取器
//Object.defineProperty(stu,'属性', { 方法 })
属性特性设置
let obj = {
name: 'xxx',
age: 22,
};
//读取属性特性
let i = Object.getOwnPropertyDescriptor(obj, 'age');
console.log(i);//{ value: 22, writable: true, enumerable: true, configurable: true }
继承
JavaScript是一门单继承语言
方法借用
//方法借用
let arr = [1, 2, 3, 4, 9];
console.log(Math.max.apply(this, arr));
Function.applay(obj,args) 传入的obj将代替原Function的this,args为参数数组
…call(obj.args)中传的参数列表
let One = function(){
this.name = "one";
this.showName = function(){
console.log(this.name);
}
}
let two = {
name : "two"
};
let one = new One();
one.showName.call(two);//two
对象冒充
JS最早的继承方式,无法继承原型上的属性、方法等
//父构造函数
let Person = function(name,age){
this.name = name;
this.age = age;
}
//原型方法,构造函数实例的公用方法都加在原型上
Person.prototype.test = function(){
console.log("this is a test");
}
//子构造函数
let Student = function(name,age,gender,score){
this.temp = Person;//冒充
this.temp(name,age);//传参,传参完成后冒充对象已无用
delete this.temp;//删除冒充对象,避免占用
this.gender = gender;
this.score = score;
}
//实例化
let laoliang = new Student("laoliang",18,"xxx",100);
console.log(laoliang.name);//laoliang
console.log(laoliang.age);//18
console.log(laoliang.gender);//xxx
console.log(laoliang.score);//100
laoliang.test();//报错
原型继承
let Person = function(name,age){
this.name = name;
this.age = age;
}
Person.prototype.test = function(){
console.log("this is a test");
}
let Student = function(name,age,gender,score){
Person.apply(this,[name,age]);//借用方法
this.gender = gender;
this.score = score;
}
Student.prototype = new Person();//将子代的prototype指向改为父构造函数的实例,因此可以使用父代的原型方法
let laoliang = new Student("laoliang",18,"xxx",100);
laoliang.test();//this is a test
ES6继承语法糖
class Person
{//构造方法
constructor(name,age){
this.name = name;
this.age = age;
}
//原型方法
sayName(){
console.log(`my name is ${this.name}`);
}
//静态方法用关键字static
}
//继承
class Student extends Person
{
constructor(name,age,gender,score){
super(name,age);//super代表访问父构造函数
this.gender = gender;
this.score = score;
}
//子代方法
learn(){
console.log("I\'m learning");
}
}
let laoliang = new Student("laoliang",18,"male",100);
laoliang.sayName();//my name is laoliang
laoliang.learn();//I'm learning
克隆
//克隆源
let obj0 = {
name: '外层',
obj1: {
name: '内层',
test: {
name: '引用层',
},
},
};
let arr0 = [0, 1, 2];
let count = 0;
// 深克隆,浅克隆Object.assign()
function clone(obj) {
let new_obj = null;
if (Array.isArray(obj)) {
new_obj = [];
new_obj = obj.map(function (params) {
return params;
});
console.log(new_obj);
//准确的数据类型判别
} else if (Object.prototype.toString.call(obj) === '[object Object]') {
new_obj = {};
for (let item in obj) {
// 递归
new_obj[item] = clone(obj[item]);
}
console.log('复杂数据类型' + new_obj + '-计数器:' + count++);
} else {
new_obj = obj;
console.log('简单数据类型:' + new_obj + '-计数器:' + count++);
}
}
clone(obj0);
函数进阶
立即执行函数IIFE
有些变量使用一次之后就不用了,IFEE形成的函数作用域确保了全局作用域不污染
即使是var声明,也会被函数作用域限制
函数运行过程是先建立,确定arguments参数数组,形参,函数引用,局部变量…
然后在执行阶段才对变量赋值
function test() {
let a = 0;
console.log(foo); //[function foo]
//构建阶段,foo被声明undefined,然后又找到函数变量foo,相当于赋值,然后开始执行
var foo = 'hello'; //变量赋值
function foo(x) {
x = 100;
}
console.log(foo); //输出hello
// foo(a); //此处再想使用foo函数就会报错
}
test();
闭包
形成条件
- 当A函数嵌套了B函数时
- B函数内可以访问A函数内的变量,
- 在外部调用B函数时,可以访问到A函数变量
- 它的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中
- 设置闭包=null可以清除闭包
每次调用闭包都会形成一个新的执行上下文
//闭包
let back, back2;
function food(a) {
let c = 3;
let b = Math.pow(a, 3);
return function () {
console.log('闭包内计算出的值:' + b + '闭包内自增的值:' + c++);
};
}
back = food(3);
back();
back();
//每次调用food函数都会形成一个新的执行上下文,即这里形成了两个闭包
back2 = food(2);
back2();
back2();
使用闭包
//累乘
// 1.不用闭包
function mult () {
let s = 1;
for (let i = 0; i < arguments.length; i++) {
s *= arguments[i]
}
return s;
}
console.log(mult(1, 2, 3, 4));
//2.对计算的结果进行缓存
console.log('缓存:');
let cache = {};
let mult1 = function () {
// let s = Array.from(arguments)对象转数组
let s = Array.prototype.join.call(arguments, ',')//将参数伪数组转化成字符串
cache[s] || (cache[s] = mult(...arguments))//将数组遍历传入函数还可以用apply()
return cache[s]
}
console.log(mult1(1, 2, 3, 4));
//3.使用闭包
let mult2 = (function () {
//缓存
let cache = {};
//功能函数-- 计算
let calc = function () {
let s = 1;
for (let i = 0; i < arguments.length; i++) {
s *= arguments[i];
}
//返回计算结果
return s;
};
// 做闭包
return function () {
let s = Array.prototype.join.call(arguments, ','); //将参数伪数组转化成字符串
// 判定是否需要计算
cache[s] || (cache[s] = calc(...arguments));
return cache[s];
};
})();
console.log(mult2(4, 5));
定义JS模块
function myModule() {
//私有数据
var msg = 'Hello, World';
//操作数据的函数
function doSomething() {
console.log('doSomething() ' + msg.toUpperCase());
}
function doOtherthing() {
console.log('doOtherthing() ' + msg.toLowerCase());
}
//向外暴露对象(给外部使用的方法)
return {
doSomething: doSomething,
doOtherthing: doOtherthing
}
}
//或
(function (window) {
//私有数据
var msg = 'Hello, World';
//操作数据的函数
function doSomething() {
console.log('doSomething() ' + msg.toUpperCase());
}
function doOtherthing() {
console.log('doOtherthing() ' + msg.toLowerCase());
}
//向外暴露对象(给外部使用的方法)
window.myModule = {
doSomething: doSomething,
doOtherthing: doOtherthing
}
})(window);
回调函数
函数作为一个参数传入另一个函数
function test (num, callbake) {
let x = 10;
// 普通参数使用
if (isNaN(num)) {
console.log('参数num需要是一个数字');
}
setTimeout(() => {
x = 100;
// 回调函数使用
callbake(x);//x会作为参数,传入到我们传入的callba内,因此在传入callback的同时,我们可以在callback内使用x的值
}, 2000);
}
递归函数
-
函数体内部调用自己
-
函数体内设置停止调用的条件
//求阶乘
let numCalc = function(i){
if(i == 1)
{
return 1;
}
else{
return i * numCalc(i-1);
}
}
console.log(numCalc(4));//24
防抖
节流
异步编程
JS代码执行是单线程的,运行到异步任务,如setTimeout时,将setTimeout放入异步队列,同时计时器线程开始计时,达到延时后,同步任务执行完,即执行setTimeout。
promise传入一个回调函数,这个回调函数再传入两个回调函数分别作成功和错误的判断
promise有三种状态pending(执行中)、success(成功)、rejected(失败)
执行resolve则pending→success,执行reject则pending→rejected
状态的改变决定了异步操作
Promise
{
//异步任务判断
let err = false;
let pm = new Promise(function (resolve, reject) {
//resolve和reject是两个回调函数
if (!err) {
//传参
resolve('resolve');
} else {
reject('reject');
}
});
//异步任务开始
// 接收resolve参数
pm.then(function (data) {
console.log('成功', data);
//默认返回一个promise对象,所以可以继续写方法,写一个then任务链
});
// 接收reject参数(错误捕获)
pm.catch(function (err) {
console.log('错误', err);
});
}
console.log('=====同步任务执行了======');
Promise.resolve() 不传参直接返回一个状态为resolved的Promise对象,所以如果希望得到一个Promise对象,最直接的方法就是直接调用Promise.resolve方法
//静态方法,resolve,reject,rece,all
Promise.resolve('resolve').then(function (data) {
console.log('成功', data);
//默认返回一个promise对象,可以继续写方法,写一个then任务链
});
//成功 resolve
迭代器
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var f = fruits.entries();
for (x of f) {
console.log(x);
}
生成器
//生成器
function* gen (arg) {
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
//执行获取迭代器对象(将指针置于头部)
let iterator = gen();
console.log(iterator.next().value);
//next方法可以传入实参
console.log(iterator.next('BBB').value);
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
async
async表示该函数要做异步处理。await表示后面的代码是一个异步操作,等待该异步操作完成后再执行后面的动作。如果异步操作有返回的数据,则在左边用一个变量来接收它。
const delay = async () => {
console.log('first');
let data = await new Promise((resolve,reject) => resolve("hello"));
console.log('aa');
console.log(data);
let data2 = await new Promise((resolve) => {setTimeout(()=>{resolve('Yes
')},2000)});
console.log(data2);
return 'World';
}
let result = delay();
console.log(result);
result.then(function(data){
console.log("data:",data);
});
console.log(11);
console.log(22);
// first
// Promise { <pending> }
// 11
// 22
// aa
// hello
// Yes
// data: World
效果∶首先执行async函数,打印出first,然后是暂停里面的代码,返回一个promise,来到外部。在外部执行完所有同步的代码,输出Promise { } ,11和22。接下来回到async函数,输出aa和 hello ,然后等两秒钟后,输出Yes ,最后回到外部,执行then()方法,打印出data: world 。
我们知道, await可以让异步操作变为同步的效果。但是,有的时候为了提高效率,我们需要让多个异步操作同时进行怎么办呢?方法就是执行异步方法时不加await,这样它们就可以同时进行,然后在获取结果时用await
function time(ms){
return new Promise((resolve,reject) => {
setTimeout(()=>{resolve()},ms);
});
}
const delay = async () => {
let t1 = time(2000);
let t2 = time(2000);
await t1;
console.log("t1 finish");
await t2;
console.log("t2 finish");
}
delay();
Node
一种不同于浏览器的JavaScript开发平台
API (应用程序编程接口)是用于构建应用程序软件的一组子程序定义,协议和工具 。
package.json文件
对项目或模块包的描述文件
- version 表明了当前的版本。
- name 设置了应用程序/软件包的名称。 不能含空格,只能包含小写字母、连字符(-)或下划线(_)
- description 是应用程序/软件包的简短描述。
- main 设置了应用程序的入口点。
- private 如果设置为 true,则可以防止应用程序/软件包被意外地发布到 npm。
- scripts 定义了一组可以运行的 node 脚本。
- dependencies 设置了作为依赖安装的 npm 软件包的列表。
- devDependencies 设置了作为开发依赖安装的 npm 软件包的列表。
- engines 设置了此软件包/应用程序在哪个版本的 Node.js 上运行。
- browserslist 用于告知要支持哪些浏览器(及其版本)。
package-look.json文件旨在跟踪被安装的每个软件包的确切版本, 以便产品可以以相同的方式被 100% 复制 (即使软件包的维护者更新了软件包)
从而无需将 node_modules
文件夹(该文件夹通常很大)提交到 Git
只需使用npm install 初始化安装依赖包
即可,初始化安装模块后,可根据package.json
中的scripts
配置,运行命令npm run 指令
npm
node的包管理工具(软件管家),服务器是国外的,国内镜像cnpm,类似的包管理工具还有yarn
-
--save
将模块信息记录 到dependencies
中,记录的都是项目在运行时需要的文件 -
--save-dev
会把信息记录到devDependencies
中 ,意为:仅开发环境所需
cnpm安装
npm install -g cnpm --registry=https://registry.npmmirror.com
express框架
Express是一个基于Node平台的web应用开发框架 , 提供route这个第三方模块定义路由 , 使用原生node.js接受请求参数需要对请求地址进行处理,需要添加事件还需要手动去拼接参数,使用框架去接受请求参数只需要获取请求对象下面的属性就可以了,比如get参数用req.query获取,post请求参数用req.body去获取就可以。
API是一套明确定义的各种软件组件之间的通信方法(接口,协议,工具 )类似银行的柜台工作人员,此处利用express工具来调接口
使用npm全局安装, npm install -g express , 项目依赖包就放在node_modules 目录中
更新软件包 npm update
项目目录结构
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.pug
├── index.pug
└── layout.pug
-
定义路由
app.METHOD(PATH, HANDLER)
- app是 express 的一个实例。
- METHOD是一个HTTP 请求方法,get/post 小写。
- PATH 是服务器上的路径url。
- HANDLER 是路由匹配时执行的函数。
例如在初始化后的routes下的index.js中添加如下路由
router.get('/help', (req, res, next) => { res.send(req.query); }); router.post('/help', (req, res, next) => { console.log(req.body); res.send(req.body); });
然后通过3000端口用get或post方法访问/help就会返回相应信息,另还有.put增加,.delete删除方法等
hello world程序
const express = require('express');//引入模块
const app = express();//调用函数
const port = 3000;//设一个端口号常量
//get 请求'/'端口号时,res.send(响应内容)
app.get('/', (req, res) => {
res.send('Hello World!')
})
//监听端口号port
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
运行该js启动服务,通过3000端口号访问’/'会返回相应信息
生成一个项目
-
创建项目根目录
mikdir myapp
-
在项目根目录中生成package.json文件
npm init -y
-
安装express
npm install express --save
-
通过npx命令 (包含在 Node.js 8.2.0 及更高版本中),快速生成项目
npx express-generator [项目名]
,无此工具则会自动下载,初始化项目依赖后,通过
npm start
命令启动 (相关命令在package.json中的script里)
中间件
-
中间件主要由两部分构成,中间件方法以及请求处理函数
-
中间件方法由Express提供,负责拦截请求,请求处理函数由开发人员提供,负责处理逻辑
-
可以针对同一个请求设置多个中间件,对同一个请求进行多次处理。
-
默认情况下,请求从上到下依次匹配中间件,一旦匹配成功,终止匹配。
-
可以调用next方法将请求的控制权交给下一个中间件,直到遇到结束请求的中间件。
AJAX
原生AJAX
<script>
let xhr = new XMLHttpRequest();
xhr.open('get', 'http://127.0.0.1:3000/ajax');
xhr.send(null);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log('异步请求成功');
console.log(xhr.response);
}
}
};
</script>
fetch API
基础用法
//设置好router接口"/fetch"后
<script>
// let url = 'http://127.0.0.1:3000/fetch?name=lxd&age=22'; //get:地址携带参数
// const promise = fetch(url);
//请求
let url = 'http://127.0.0.1:3000/fetch';
//post:传入参数
const promise = fetch(url, {
method: 'post',
body: '{"name":"lxd","age":18}',//传json串
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }//协议
});
// 请求结果
promise.then(response => {
return response.json() //转换为json
}).then(data => {
console.log(data);
}).catch(err => {
console.log(err);
})
</script>
利用async简化
//设置好"async"路由后
<script>
async function getUsers () {
let url = 'http://localhost:3000/async';
try {
//await 相当 promise里的then异步
let response = await fetch(url);//fetch执行返回一个response对象
return await response.json();//读取响应,转json
} catch (error) {
console.log('Request Failed', error);
}
}
console.log(getUsers());
</script>
Response对象的同步属性
基本属性
- Response.ok 属性返回一个布尔值,表示请求是否成功
- true对应 HTTP 请求的状态码 200 到 299
- false对应其他的状态码
- Response.status 属性返回一个数字
- 表示 HTTP 回应的状态码(例如200,表示成功请求)
[^fetch()发起请求后,只有网络错误,或者无法连接时, fetch()才会报错,其他情况均不会报错,而是认为请求成功。所以可以通过status和ok属性来判别]:
-
Response.statusText 属性返回一个字符串
- 表示 HTTP 回应的状态信息(例如请求成功以后,服务器返回"OK")。
-
Response.url 属性返回请求的 URL
- 如果 URL 存在跳转,该属性返回的是最终 URL。
-
Response.type 属性返回请求的类型。可能的值如下:
- basic:普通请求,即同源请求。
- cors:跨域请求。
- error:网络错误,主要用于 Service Worker。
- opaque:如果fetch()请求的type属性设为no-cors,就会返回这个值,详见请求部分。表示发出的是简单的跨域请求,类似``表单的那种跨域请求。
- opaqueredirect:如果fetch()请求的redirect属性设为manual,就会返回这个值,详见请求部分。
- Response.redirected
-
Response.redirected 属性返回一个布尔值,表示请求是否发生过跳转。
-
response.headers.get()
,用于读取某个标头的值。 如’Content-Type’
读取内容的方法
Response
对象根据服务器返回的不同类型的数据,提供了不同的读取方法。
- response.text():得到文本字符串。
- response.json():得到 JSON 对象。
- response.blob():得到二进制 Blob 对象。
- response.formData():得到 FormData 表单对象。
- response.arrayBuffer():得到二进制 ArrayBuffer 对象。
上面5个读取方法都是异步的,返回的都是 Promise
对象。 必须等到异步操作结束,才能得到服务器返回的完整数据。
Stream 对象只能读取一次,读取完就没了。所以,前面的五个读取方法,只能使用一个
Response
对象提供Response.clone()
方法,创建Response
对象的副本,实现多次读取。
Node.js连接数据库
模块的导入导出
导出
//这是一个模块
// module.exports和exports
var sayHello = function () {
console.log('hello');
};
exports.sayHello = sayHello;
console.log(exports);
console.log(module.exports);
console.log(exports === module.exports);
导入
const mode = require('./export.js');
mode.sayHello();
ES6
导出
//export命令用于规定模块的对外接口;
export function setup() {
console.log('函数导出');
}
export const x = '常量导出';
//不加default 则在接收时需要加个大括号
const obj = {
name: 'xxx',
age: 22,
};
// export default命令,为模块指定默认输出
export default {
obj,
};
导入
<script type="module">
// import { setup, x } from "./export.js";
// import obj from "./export.js";
//合并写
import obj, { setup, x } from "./export.js";
setup();
console.log(x);
console.log(obj);
</script>