JavaScript进阶

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();


闭包

形成条件

  1. 当A函数嵌套了B函数时
  2. B函数内可以访问A函数内的变量,
  3. 在外部调用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

  1. 定义路由app.METHOD(PATH, HANDLER)

    1. app是 express 的一个实例。
    2. METHOD是一个HTTP 请求方法,get/post 小写。
    3. PATH 是服务器上的路径url。
    4. 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端口号访问’/'会返回相应信息

生成一个项目
  1. 创建项目根目录 mikdir myapp

  2. 在项目根目录中生成package.json文件 npm init -y

  3. 安装express npm install express --save

  4. 通过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>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值