一、概述
不是JS,但是语法和JavaScript非常相似,他的竞争对手:Java、C++、C#、Python...,后端语言
做的功能绝对不是特效!做的是和服务器端其他语言是一致的(和数据库进行交互,成为了一个前端到数据库的中间桥梁)
目的:
1、使用代码搭建一个服务器&文件系统(服务器文件可以放在任何位置,但是不在自己的电脑里,你可以根据网址来访问到我的东西)
2、Node.js如何沟通前端和数据库
3、全栈:图书管理系统(HTML+CSS+JS+Node+Mongo)
二、安装
4、Node.js安装:官方网站:nodejs.org/en, 下载LTS版本,常用稳定版;然后安装,一路往下点,不用取消任何勾选。
版本:
16年初(0.12) 16年中(4.xx) 16年末(6.xx) - 更新速度快
检查安装是否成功:
打开cmd输入:node -v - 查看版本号,如果有版本号代表你已经安装成功!
其实你安装的这个node.js就是一个运行环境而已!我们书写“js”不再需要浏览器了,因为根本写的就是不是js,而是node.js,只不过语法和js非常相似
Node.js如何运行(3种):
1、交互模式 - 临时测试
打开cmd输入:node回车,就可以开始敲"js"代码
2、脚本/文件模式 - 正式开发中
- 先创建xx.js,里面书写自己的代码
- 打开cmd输入:node文件的绝对路径
3、编辑器 - vscode安装Code Runner插件。
前提:前两个方式都能成功
安装Code Runner插件后,打开编辑器设置,输入execute,勾选下面的Code-runner:File Directory As Cwd(不勾选,可能是用不了绝对路径)
运行时,对着nodejs文件点击右键,选择第一个Run Code,或者右上角的一个播放按钮,就可以执行nodejs代码了
三、Node.js知识
1、js和node的区别
相同点
都可以使用一切的ECMAAscipt的东西包括一切的API都可以使用,在服务器端不存在任何浏览器,所以不必担心兼容问题
不同点
1、JavaScript: DOM+BOM - 做特效
2、Node.js:虽然没有DOM+BOM,但是他却有10万+的模块
模块(modual)
每一个xx.js文件,都可以称之为是一个模块
1、模块化开发
如果以一个网站来说,我们可以按功能分为很多模块:商家模块、商品模块、促销模块、用户模块、产品模块......
分工合作:将每个模块交给对应的人,完成,最后再由【主模块】进行引入
(1)每一个模块都有一个操作,可以用于公开/暴露自己的成员
exports:Node.js自带的一个预定义变量,可以直接使用,是一个对象,放在此对象里面的东西,就是允许公开的东西
语法:
a、exports.属性名=属性值;
b、
module.exports={
属性名:属性值,
...
}
错误导出语法:
exports={
name:"袍哥",
age:18,
hobby:"学习"
}
(2)每一个模块(主模块)都有一个操作,可以用于导入/引入其他模块
require:Node.js自带的一个预定义变量,可以直接使用,是一个函数,函数中需要书写出引入模块的路径
语法:var x=require("./文件名")
笔试题:exports 和 module.exports有什么区别?
1、语法、写法、用法不同
2、都是用于公开暴露自己的成员的
但是exports={},写法是错误的
其实Node.js底层有一句话:exports=module.exports
其实真正做公开功能的是module.exports
如果使用了exports={};//这是创建了一个新的空对象,把module.exports,所以不再具有公开的功能
2、模块的分类
(1)官方模块
大概有二十几个,但重要的只有几个
不需要下载,在安装node.js环境的时候就已经带上了,但是某些模块可能需要引入,某些模块可能不需要引入
A、Global模块
不需要引入的,可以直接使用
提供了:
A、五个预定义变量,可以直接使用
a、_filename - 获取当前文件完整的绝对路径
b、* _dirname - 获取当前文件绝对路径,不包含文件的名字。
何时使用:当vscode不能识别绝对路径时,只能写绝对路径(vscode不能使用绝对路径,是安装插件后,没有设置的问题,上面有解决办法)
c、* exports - 空对象,可以用于公开暴露自己的成员
d、* require - 函数,可以用于导入其他模块
e、*** module - 指代当前模块本身,甚至包含着以上4个操作
B、定时器(周期性、一次性、瞬间定时器)
定时器不是当初的js,只不过用法和当初一模一样
C、console
也不是当初的console,只不过用法和当初一模一样
B、querystring模块
解析查询字符串,使其变成一个对象,可以获取到前端传到后端的消息
需要引入:var qs=require("querystring");
作用:解析url查询字符串部分的功能
语法:var obj=qs.parse("查询字符串");
想要获得前端传来的每一个部分:obj.键名;
这是一个垃圾:如果前端传来的是一个完整的url网址,它就解析不了了!
C、***url模块
需要引入:var url=require("url");
作用:提供了解析url各个部分的功能
var objU=url.parse("网址",true);//支持第二参数,是一个布尔值,默认为false,一旦设置为true,自动使用querystring模块的parse方法去解析查询字符串部分
真正的重点:
A、查询字符串:objUrl.query.键名; - 前端form表单提交传到后端的东西
B、路由(文件相对路径或请求地址):objUrl.pathname - 判断路由的不同,去读取不同的HTML发送给我们的用户看
D、Buffer模块
缓冲区,可以将数据变成一个16进制的数字,你可以理解为是Node.js中的一种新的数据类型,但是我们绝对不会手动使用,因为我们一眼看不懂,但是后面的一些API可能会导致我们被动使用到Buffer,Node.js中大部分的API都支持Buffer。可以是.toString()方法将buffer转换成文字
E、*****fs模块
需要引入:let fs=require("fs");
*异步读取文件:
fs.readFile("文件路径",(err,buf)=>{
buf->读取到的内容
})
异步写入文件
fs.writeFile("文件路径","新内容"/buf,()=>{
console.log("写入完毕后,要做什么,必须放在这里面");
})//会替换掉原来的东西
异步追加文件
fs.appendFile("文件路径","新内容"/buf,()=>{
console.log("写入完毕后,要做什么,必须放在这里面");
})//会替换掉原来的东西
强调:只有异步才能更完美的发挥Node.js的特点(快)
F、http模块
超级重点:搭建服务器
//引入了http(搭建服务器)、url(区分开路由和请求消息)、fs(读取文件响应给用户看)
var http=require("http");
var url=require("url");
var fs=require("fs");
//创建服务器应用
var app=http.createServer();
//为其绑定监听端口
app.listen(80);
//为其绑定请求事件:http:请求 - 响应模式,必须要有一个请求,才有一个响应
app.on("request",(res,res)=>{
//req:request(请求)对象,他有一个属性叫做req.url,获取到前端传到后端的路由和请求消息,但是路由和请求消息是融为一体的,不方便我们获取某个部分,所以我们引入了url,进行解析,分开两部分
var objUrl=url.parse(req.url,true);
//保存路由
var router=objUrl.pathname;
if(router=="/" || router=="/index.html"){//判断路由的不同,读取不同的页面给用户看
//res:response(响应)对象,他有一个方法:res.end(响应的内容) - 可以响应给前端想要的东西
fs.readFile("./public/html/index.html",(err,buf)=>{
res.end(buf);//res.end只能用一次
})
}
})
扩展:字符串有一个API:math
var rs=str.match(reg);和indexOf几乎一致,但是支持正则,我们不关心为多少,只关心为不为null
强调:一切的src和href都是一个请求都是一个路由,这个请求就需要后端来解析,根据不同的请求响应不同的内容
(2)第三方模块
多到数不清,提供了很多官方模块没有的东西,有一个npm的官网:www.npmjs.com/ 可以去下载
(3)自定义模块
自己书写的xxx.js:require("./模块名");
为什么有的模块引入要./有的又不用加./
自定义模块:分为2大类
(1)文件模块:创建xx.js去公开需要公开的内容,主模块要引入,必须写为require("./模块名");
(2)目录模块:3种用法
A、比如创建m1的文件夹,在其中创建index.js的文件,去公开需要公开的内容,主模块要引入,必须写为require("./m2");
B、比如创建m1的文件夹,在其中创建xx.js的文件,去公开需要公开的内容,主模块要引入,必须写为require("./m2");
必须再创建一个package.json的配置文件,写入:{"main":"xx.js"}
C、创建一个文件夹必须名为:node_modules,再在其中创建出m3文件夹,在其中创建index.js的文件,去公开需要公开的内容,主模块要引入,必须写为require("m3");
在真实开发中,程序员用的最多的是文件模块,目录模块的第三种方式,其实根本不是给人用的(第三方模块下载后会自动创建此文件夹)
Node.js最大的特点
(1)快、非常快 - 以前最快的是php,js的速度是php的十六倍
(2)为什么快
a、因为官方提供的东西少,甚至连数据库的操作API都没有提供
b、使用了chrome浏览器的v8引擎
3、如何下载第三方模块
npm工具:Node Package Manager:Node.js的模块/包管理器,专门用于管理第三方模块的,作用:下载、更新、删除、维护包之间的依赖关系
打开网址:npm官网 :www.npmjs.com/
搜索需要用到的模块:尽量使用带有完全符合(exact match)标签的那个包,或者是第一个包
(1)打开cms:检查npm是否安装成功:npm -v
(2)在你的项目之中,再打开cmd
(3)下载:npm i 包名
(4)更新:npm up 包名
(5)删除:npm un 包名
四、mongoDB
mongo就是基于json的数据库,json就是JavaScript Object Notation
1、安装&启动
(1)解压ngodb-win32-x86_64-2008plus-ssl-3.6.11.zip文件
(2)打开bin文件夹,里面有:mongo.exe(客户端) 和 mongod.exe(服务器端)
(3)如何启动
在bin文件夹中打开cmd:输入:.\mongod.exe --dbpath=你想要保存的绝对文件夹路径; - 服务器开启成功,而且那个文件夹就保存着你以后要存储的所有的数据
不要关闭mongo服务器的cmd
再打开一个cmd:输入:.\mongo.exe - 在上一个命令行可以查看我们是否链接成功 - 客户端开启成功
2、mongo的语法
都是在客户端cmd输入
(1)数据库的操作
A、查询所有数据库:show dbs
B、创建/切换数据库:没有就创建,有了就切换:use 数据库名称
C、查看当前选中的数据库:db
D、创建数据表:db.createCollection("表名") - 无限,一定要先创建数据表后,我们才能查看到自己创建的数据库
E、删除数据库:db.dropDatabase(); - 一旦删除不能恢复,不推荐,因为要坐牢
(2)数据表的操作
A、创建数据表:db.createCollection("表名",{size:5242880,capped:true,max:5000}) - 最大存储空间为5mb,最多存储500个,意味着这个数据表做了限制,不推荐
B、查看目前所有的数据表:db.getCollectionNames();
C、删除数据表:db.表名.drop();
(3)*****数据的操作
A、增:db.表名.save({键值对,...}) - 一次只能插入一条数据
db.表名.save([{},{},{},....]) - 一次插入多条数据
db.user.save([{name:"funan",age:"19,pwd:"111111",email:"fn@qq.com",vip:"0"},{name:"袍哥",age:"20,pwd:"222222",email:"pg@qq.com",vip:"1"}])
B、删:db.表名.remove({}) - 不推荐,删除数据库中所有的数据
db.表名.remove({name:"任小波"}) - 会删除数据库中name:"任小波"的所有数据
C、改:db.表名.update({条件},{$set:{新内容}});
eg:db.表名.update({name:"任小波"},{$set:{pwd:"123123"}});
D、* 查:db.表名.find(); - 找所有
db.表名.find({pwd:"666666"}); - 找到所有的密码为666666的数据
db.表名.find({},{name:1,pwd:1}) - 找到所有的数据,但是只返回name和pwd
db.表名.find().sort({age:1}) - 按照age升序排列,-1为降序排列
db.表名.find({age:{$gte:18}}) - 拿到所有age大于等于18的数据
db.表名.find({name:/正则/}) - 甚至可以用正则(模糊查询)
db.表名.find().skip(5).limit(5) - 跳过前5条,再拿5条,理解为5-10条数据(第几个分页条显示第几条数据-第几条数据)
db.表名.find().count() - 获取到此表有多少条数据(做出分页条)
3、安装mongoDBCompass软件
形化界面,直观、好看、方便 - 仅仅只用于给我们方便查看
4、Node.js操作mongoDB
(1)安装第三方模块:mongoose
(2)使用步骤
A、引入:const mongoose = require('mongoose');
B、连接数据库:mongoose.connect("mongodb://127.0.0.1/数据库名称");
C、创建出一个新的数据表的同时,设置数据类型的控制,防止用户乱输
const UserSchema=mongoose.Schema({
age:Number,
pwd:String,
email:String,
vip:String,
name:String
})
var User=mongoose.model("User",UserSchema,"数据表名");
D、增
var x=new User({//仅仅只是创建出了一个x对象,并没有放入到数据库之中
age:"20",
pwd:"123123",
email:"dy@qq.com",
vip:"0",
name:"dy",
})
x.save((err)=>{
console.log("新增成功后要干什么");
})
E、删
User.remove/deleteOne/deleteMany({条件},(err)=>{//作者不推荐update在mongoose之中使用
console.log("删除成功后要干什么");
})
F、查
User.find({条件},(err,result)=>{
result 就是你查找到的结果
})
目前:前端能传到后端的技术,只有一个:form表单,action属性可以随便自定义一个路由名称,后端解析此路由就可以通过objUrl.query.键名得到想要的部分
五、Ajax
1、概念
同步交互:用户向服务器端发起请求,直到服务器端进行响应的全过程,用户是不可以做其他事情的
典型:表单提交、网址请求 - 都属于同步交互
异步交互:用户向服务器端发起请求,知道服务器端进行响应的全过程,用户是可以做其他事情的
典型:ajax请求
2、*****Ajax
Asynchronous JavaScript And XML - 直译:异步的JavaScript和XML - 前端技术
不严格定义:页面不完全刷新,只会导致页面局部发生改变的技术
异步技术:
- 定时器 - 做特效
- mongoose操作数据库的增删改查 - 操作数据库
- ajax - 目的:在不刷新页面的情况下和服务器端进行交互 - 可以将服务器端的数据放到前端(比较验证、数据渲染)
3、如何使用
固定4步:
A、创建ajax核心对象
var xhr=new XMLHttpRequest();
B、建立和服务器端的连接
xhr.open("GET/POST","路由");
C、向服务器端发送请求消息
xhr.send();//此方法很特殊
- 如果是GET请求,send方法会失效,但是还不能省略,必须写为:
xhr.open("GET","路由?key=value&key=value&...");
xhr.send(null);
- 如果你是POST请求,send方法可用,必须写为: - 暂时不能用
xhr.open("POST","路由");
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send("key=value&key=value&...");
get:获取 - ajax一般都是使用get,去找服务器端拿东西 - 举例:跟安全性不挂钩的,搜索框
post:发送 - 举例:跟安全性挂钩,登录、注册
D、绑定状态监听事件
xhr.onreadystatechange=()=>{
if(xhr.readyState==4&&xhr.status==200){
xhr.responseText - 服务器端响应的文本,ajax就难在拿到数据后要做什么操作
}
}
六、数据格式
(一)、XML
1、面试题:HTML、XHTML、DHTML、XML分别是什么?
HTML - 网页:预定义了很多标签,可以使用这些标签写出网页
XHTML - 更严格的网页:HTML5->XHTML->HTML4.01,比如:<input />,<input disabled="disabled">
DHTML - 动态效果网页:在离线端,我们的网页也具有动态的特效:其实不是新技术也不是新概念,而是现有技术的一个整合统称:HTML+CSS+JS(dom)
XML - 配置文件|数据格式:没有提供过任何预定义标签!全靠自定义
1、如何使用XML,其实就是一个后缀.xml的文件
(1)创建xx.xml文件
(2)必须写上声明标签:<?xml version="1.0" encoding="utf-8"?> - 必须放在第一行第一列
version - 版本号:目前有的版本只有1.0和1.1,但是1.1升级并不理想,没有人使用,所以1.0可以说是唯一版本,已经被淘汰了
encoding - 编码格式
(3)必须写上一个跟标签,而且只能写一个根标签,而且必须是双标签
(4)里面随意,放什么都可以
开发中,正常来说后端会想办法将数据库的数据整理为一个xml格式的文件
前端:依然使用ajax去获取xml
A、路由 写为 "xx.xml"
B、xhr.responseText换成xhr.responseXML - 可以使用【核心DOM】去操作需要的东西 - 淘汰的原因,现在来获取数据都要使用核心DOM,太麻烦了
(二)JSON
JavaScript Object Notation:JS对象表示法,本身就是JS的一部分
作用:数据格式类似于XML
好处:比XML更简洁、更快、更容易解析 - 一个优秀的数据格式可以极大的提升我们程序员的开发效率
1、JSON字符串的格式有:
(1)'[1,2,3,4,5]';
(2)'{"key":value,...}';
(3)[{},{},{},{}];
(4){"names":[1,2,3,4],"age":[1,2,3,4]};
2、后端把数据库的数据取出来整理为一个JSON字符串:var jsonTxt=JSON.stringify(jsonObj);
3、前端依然使用ajax去获取响应数据,真正重要的:xhr.reponseText;
将JSON字符串解析为一个JSON对象:那么两种方法 - 脱衣服
(1)eval("("+xhr.reponseText+")");
(2)* JSON.parse(xhr.reponseText);
七、JQuery
1、JQueryUI
基于JQuery(基于JavaScript的一个框架,是三大框架出现之前,最火的一个,但是现在已经被淘汰了)的开源网页用户界面代码库 - 提供了HTML、CSS、JS的一个插件库
三大框架:Vue(中国人的框架)、React、Angular(在国内几乎没有市场)
组件库:组件,组成网站一部分的部分,代码宠用,一般不具备JS功能:比如导航条、图文显示...
插件库:跟组件差不多,只不过带有JS功能 - 选项卡、轮播...
如何使用插件库
(1)下载JQueryUI
(2)必须在页面上进行引入: - 顺序不能错,一定要先引入jquery.js再引入jquery-ui.js
<link rel="stylesheet" type="text/css" href="jquery-ui-1.13.2.custom/jquery-ui.css"/>
<script src="jquery-ui-1.13.2.custom/external/jquery/jquery.js" type="text/javascript" charset="utf-8"></script>
<script src="jquery-ui-1.13.2.custom/jquery-ui.js" type="text/javascript" charset="utf-8"></script>
(3)挑选出你需要的/喜欢的插件,直接复制到项目中
(4)根据设计图,来修改样式 - 修改不成功,只有一个可能:权重不够
(5)使用ajax去获取数据库中的数据,来进行页面渲染
(6)千万别忘了调用JQuery提供的xx方法来实现功能
推荐的JQUI的插件:
- a、选项卡/标签页
- b、菜单
- c、手风琴/折叠面板
- d、模糊查询/自动完成
- e、JQ动画/特效
- f、交互部分自己试试
2、简化了核心DOM
使用JQuery,必须先引入:<script src="jquery-ui-1.13.2.custom/external/jquery/jquery.js" type="text/javascript" charset="utf-8"></script>
JQuery中最有魅力的一个方法叫做$:
作用:
(1)查找元素:$("JQ选择器"); - 包含一切css选择器的,不需要记忆:推荐网址:www.w3school.com.cn/jquery/jque… - 底层就是document.querySelectorAll
(2)创建元素:$("<标签></标签>"); - document.createElement
(3)可以将DOM转为JQ:${DOM对象};
(4)代替了window.onload - ${callback};面试题:两者的区别?
A、window.onload - 等待所有资源(html、css、其他js、图片、视频、视频...)加载完毕才会执行,效率降到了最低,而且一个页面只能写一次
B、${callback}; - 只是等待DOM加载完毕就会执行,性能比window.onload要高,而且一个页面能写多次
底层用到了一个人:重载;arguments - 可以通过判断用户传入的实参的不同执行不同的操作
(1)查找元素
(A)除了直接查找:${"JQ选择器"};
(B)通过关系查找:至少要先找到一个人可以使用关系
a、父:parent();
b、子:children();
c、前一个兄弟:prev();
d、后一个兄弟:next();
e、其他兄弟:siblings();
JQ自带隐式迭代,不需要遍历,可以对集合直接做操作
(2)操作元素
A、内容
获取:$("xx").html/text/val();
获取:$("xx").html/text/val("新内容");
B、属性
获取:$("xx").attr("属性名");
设置:$("xx").attr("属性名","属性值");
C、样式
(A)可以操作class
(a)、添加class:$("xx").addClass("新class") - JS 中没有此操作,只能替换
(b)、删除class:$("xx").removeClass()
如果不传参,删除所有的class名
如果传入,删除对应的class名
(B)直接操作css
获取:$("xx").css("css属性名");
设置:$("xx").css("css属性名","css属性值");
一句话设置多个样式:
$("xx").css({
css 属性名:"css 属性值",
})
(3)JQ的遍历
$("一堆人").each((i,val)=>{
})
(4)JQ上树&删除
上树:父亲.append(儿子)
删除:$("xx").remove();
(5)JQ动画
(A)显示 - $("xx").show();
(B)隐藏 - $("xx").hide();
(C)切换 - $("xx").toggle();
- 如果不传参数,是瞬间显示,瞬间隐藏
- 可以传入实参:
$("xx").api("动画名称",时长);
JQ不可以用以前DOM的语法,DOM不可以用JQ的语法,但是两者其实可以互换
JQ->DOM:$("xx")[下标];
DOM->JQ:$(DOM)
JQuery有的人爱称呼是一个类库(小),有的人爱称呼是一个框架(大)
因为大部分人只知道JQuery有一个.js文件(类库)jquery.js
但是Jquery可以称呼是一个框架,因为它由4部分组成:
- jquery.js
- jqueryUI.js
- jquery-Mobile.js - 但是现在又uniapp
- QUnit - 测试用来测试JavaScript代码的一个工具
工具:
- 百度搜索:jquery插件库网站,一个账号一天只能白嫖两次
- 百度搜索:jquery之家,免费的,但是没有jquery插件库那么好看
八、Express
Node.js的第三方框架:express,需要使用npm去下载,express中有两个核心概念
1、使用步骤
(1)下载:在你的项目路径下打开cmd:npm i express
(2)引入后发现express是一个函数,创建服务器应用,还要设置监听端口
var express=require("express");
var app=express();
app.listen(端口号);
2、两个核心概念
(1)路由
客户端发来的请求中的一部分,也称呼叫做相对路径,通过判断路由的不同响应不同的内容
(A)
app.get("路由",(req,res)=>{//req和res不是以前的req和res,用法会与原生Node有所不同
req->依然是请求对象,保存着前端传来的请求消息:req.query.键名;
res->依然是响应对象,可以为前端发数据,也可以为前端发页面
a、发数据:res.send("想要发的东西");
b、发文件:res.sendFile("文件的路径");
})
(B)特殊:post请求要稍微麻烦一点点,尤其在于获取前端传到后端的请求消息,因为post是隐式提交,所以需要某些东西才能看得见他
app.post("路由",(req,res)=>{//req和res不是以前的req和res,用法会与原生Node有所不同
req->依然是请求对象,保存着前端传来的请求消息:3步
a、需要引入一个第三方模块(中间件的语法):var bp=require("body-parser");
b、使用中间件的语法:app.use(bp.urlencoded({extended:false}))
c、req.body键名;
res->依然是响应对象,可以为前端发数据,也可以为前端发页面:
a、发数据:res.send("想要发的东西");
b、发文件:res.sendFile("文件的路径");
})
不管是form表单还是ajax,都可以自行选择使用get还是post
前后端分离,需要沟通,路由,请求方式...
(2)中间件
express本身就是一个功能极简的框架,完全由路由和中间件两部分构成
中间件其实就是一个函数,但是它也可以访问req和res两个对象,处于路由之前 - 可以理解为是现实生活中的一个保安、保镖、秘书
中间件的功能包括:
- 可以执行任何代码
- 可以修改请求和响应对象
- 可以终止请求
- 可以放行你到下一个中间件/路由 - 中间件可以写多个
语法:
app.use((req,res,resolve)=>{
//一切想要执行的代码,中间件代码
resolve();//放行的函数
})
固定套路:
- 1、*获取post的请求消息,见上面 -
app.use(bp.urlencoded({extended:false})); - 2、*内置中间件加载一切静态资源:
app.use(express.static("静态资源的文件夹名"));
3、如何简化ajax
(1)jQuery提供了一个新的ajax
$.ajax({
url:"路由", - 必写
data:"请求消息", - 可选
dataType:"HTML/XML/JSON", - 可选,默认值为HTML,如果你写了JSON,则可以省略JSON.parse方法
type:"GET/POST", - 可选,默认值为GET
success:(data)=>{ - 必写
data->后端响应的内容,你不需要再写xhr.responseText
}
})
(2)jQuery是如何实现的,我们自己也封装一个