JS知识点总结(5)+node.js基础知识

102 阅读23分钟

26.DOM

  1. DOM概念 将每一个标签/属性/文本/注释/元素,都看作是一个DOM元素/节点/对象(提供了一些操作元素的属性/方法) ==面试题== HTML/XHTML/DHTML/XML 分别是什么? 1、HTML - 网页 2、XHTML - 更严格的HTML,HTML5->XHTML->HTML4.01 3、DHTML - 动态的网页:D:Dynamic - 其实并不是新技术、新概念,是将现有技术的整合统称,让我们在离线时,网页也具有动态效果 DHTML:html+css+js(dom) 4、XML - 未知的标记语言,一切的标记由自己定义,数据格式

DOM原本是可以操作一切结构化文档的HTML和XML,后来为了方便各类开发者分为了3部分:

  1. 核心DOM:既可以操作HTML又可以操作XML

    • 缺陷:API比较繁琐
  2. HTML DOM:只能操作HTML,API简单

    • 缺陷:比如属性部分,只能访问标准属性,不能访问自定义属性
  3. XML DOM:只能操作XML(XML已经淘汰了,现在最流行的数据格式是JSON) 开发建议:优先使用HTML DOM,HTML DOM实现不了再用核心DOM进行补充

  4. DOM树: 概念:DOM将我们的HTML看做了是一个倒挂的树状结构,但是树根不是html标签,而是document对象 document对象:不需要去创建,由浏览器的js解释器自动创建,一个页面只有一个document 作用:可以通过树根找到页面上的每一个DOM元素/节点/对象,也可以操作它

  5. 每个DOM元素都有三大属性:

    1. elem.nodeType:描述节点的类型
      • document节点:9
      • element节点:1
      • attribute节点:2
      • text节点:3
      • 注:以前用于判断xx是不是一个页面元素(children不会得到文本节点的,但是以前的childNodes会得到文本节点)
    2. attrNode.nodeValue:描述节点的值
      • 注:以前有用:先拿到属性节点,再用此属性去获取属性值
    3. ***elem.nodeName:描述节点的名字(e.target中也会用到)
      • 作用:拿到当前元素的标签名,判断xx是什么标签
      • 注:返回是一个全大写组成的标签名

查找元素

  1. 通过关系查找元素: 前提条件:必须先找到一个元素才可以调用关系网

    • 父元素:elem.parentNode;
    • 子元素:elem.children; (找到的是一个子元素集合)
    • 第一个儿子:elem.firstElementChild;
    • 最后一个儿子:elem.lastElementChild;
    • 前一个兄弟:elem.previousElementSibling;
    • 后一个兄弟:elem.nextElementSibling;
  2. 递归:简单来说就是函数中,又一次调用了函数自己,迟早有一天会停下来

    • 使用场景:遍历DOM树,专门用于【遍历层级不明确】的情况,既可以遍历层级不明确的DOM树,也可以遍历层级不明确的数据!
    • 使用方法:2步 function 函数名(root){ 1、第一层要做什么直接做! 2、判断他有没有下一级,如果有下一级,再次调用此函数,但是传入的实参是他的下一级 } 函数名(实际的根)
    • 算法:深度优先!优先遍历当前系欸但的子节点,子节点遍历完才会跳到兄弟节点
    • 缺点:同时开启大量的函数调用,大量消耗内存,只有一个情况才用:【遍历层级不明确】
    • 递归 vs 循环:
      • 递归
        • 优点:直观、易用
        • 缺点:性能较低,尽量只在层级不明确的时候使用
      • 循环
        • 优点:几乎不占用内存
        • 缺点:使用难度高
  3. TreeWalker(专门用于遍历层级不明确的DOM树的API)

    • 使用方法:2步
      1. 先创建出tw: var tw=document.createTreeWalker(根元素,NodeFilter.SHOW_ALL/SHOW_ELEMENT);
      2. tw对象过后,反复调用nextNode方法找到下一个节点,迟早有一天会等于null,说明没找到,公式: while((node=tw.nextNode())!=null){node要干什么}
    • 缺陷:
      • 自动的跳过根元素,根元素是不会做任何操作的
      • 仅仅只能遍历层级不明确的DOM树,不能遍历层级不明确的数据
  4. API直接找元素:

    • 根据HTML的特点去找元素
      1. 通过ID查找元素
        • 语法:var elem=document.getElementById("id值");
        • 特殊:
          1. 返回值,找到了返回的是一个当前找到的DOM元素;没找到,返回一个null,做了别的操作可能就会报错
          2. 找到了多个相同的id,那么只会返回第一个
          3. 一次只能获取一个元素,也只能操作一个元素
          4. 其实根本不需要使用此方法,直接写ID也可以找到元素
      2. 通过标签名查找元素
        • 语法:var elems=document/已经找到了的父元素.getElementsByTagName("标签名");
        • 特殊:
          1. 返回值:找到了返回的一个是==类数组==DOM集合(很像数组,都能用下标,都能用length,都能遍历),没找到返回一个空集合
          2. JS不能直接操作DOM集合,只能直接操作DOM元素,解决:要么使用下标拿到某一个元素,要么使用遍历拿到每一个元素
          3. 不一定非要从document开始查找,如果document去找,会找到所有的元素,可以换成我们已经找到的某个父元素,就只会找到这个父元素下面的元素了
      3. 通过class名查找元素
        • 语法:var elems=document/已经找到了的父元素.getElementsByClassName("标签名");
      4. 通过Name查找元素
        • 语法:var elems=document/已经找到了的父元素.getElementsByName("标签名");
    • 根据CSS选择器去找元素:
      • 单个元素:
        • 语法:var elem=document.querySelector("任意的css选择器");
        • 强调:万一选择器匹配到多个,只会返回第一个,没找到返回null
      • 多个元素:
        • 语法:var elem=document.querySelectorAll("任意的css选择器");
        • 强调:找到了返回集合,没找到返回空集合

==面试题/笔试题==: getXXX 和 querySelectorAll 有什么区别? 返回结果不同的: 1、getXXX:返回的是要给动态集合HTMLCollection 优点:数据始终和DOM树实时挂钩 缺点:每次DOM树进行修改,都会悄悄的再次查找元素,效率相对较低 2、querySelectorAll:返回的是要给静态集合NodeList 优点:每次不会悄悄重新查找,效率较高,而且还支持使用forEach!

总结:找元素的方式:

  1. 直接查找元素:getXXX 和 querySelectorAll
  2. 通过关系找元素:
  3. 层级不明确的情况才用递归!

操作元素

前提:找到元素才能操作元素: <标签 属性名="属性值" style="样式">内容</标签> 强调:页面上获取/设置到的一切数据都是字符串类型

  1. 元素的内容:
    1. elem.innerHTML:获取/设置开始标签到结束标签之间的内容(支持识别标签,无兼容性问题)
      • 获取:elem.innerHTML;
      • 设置:elem.innerHTML="新内容";
    2. elem.textContent:获取/设置开始标签到结束标签之间的纯文本(不支持识别标签,有兼容性问题)
      • 获取:elem.textContent;
      • 设置:elem.textContent="新文本";
      • 老IE:elem.innerText;(我们第一次见到小三上位)
        • innerText某次浏览器更新后,现在主流浏览器也支持此属性
        • 为什么老IE不将就主流?- 微软的,windows系统的使用的人多 以上两个属性都是为双标签准备的,但是操作不了单标签input的内容
    3. input.value:获取或设置表单控件的值(用于正则验证等场景)
      • 获取:input.value;
      • 设置:input.value="新值";
  2. 元素的属性:
    • 获取属性值
      • 核心DOM:elem.getAttribute("属性名");
      • HTML DOM:elem.属性名;
    • 设置属性值:
      • 核心DOM:elem.setAttribute("属性名","属性值");
      • HTML DOM:elem.属性名="属性值";
    • 删除属性值:
      • 核心DOM:elem.removeAttribute("属性名");
      • HTML DOM:elem.属性名=""
        • 删除不推荐使用HTML DOM,删除不干净属性节点,而有的属性,光有属性名就已经具有功能了
    • 判断有没有属性(没用)
      • 核心DOM:elem.hasAttribute("属性名")
        • 仅仅只能判断有没有这个属性,不能判断出属性值是什么,往往我们自己用获取属性值的操作,获取到了过后再去进行比较运算
      • HTML DOM:elem.属性名!="";
    • 缺陷:
    1. class必须写为className - 2015年过后,ES6诞生过后,class变成了一个关键字
    2. 不能操作自定义属性,只能操作标准属性
  3. 元素的样式
  • 内联样式
    • 优点:
      1. 仅仅当前元素可用,不会牵一发动全身
      2. 优先级最高,一定会覆盖其他的样式
    • 获取:elem.style.css属性名;
    • 设置:elem.style.css属性名="css属性值";
    • 特殊:
      1. css属性名,有横线的地方,去掉横线,变为小驼峰命名法 如:border-radius -> borderRadius
      2. 缺陷:获取时,只能获取内联样式
  • 样式表中的样式
    1. 找到你想要操作的样式表
      • var sheet=document.styleSheets[i];
    2. 获取样式表中所有的样式规则
      • var rules=sheet.cssRules;
    3. 找到自己想要操作的样式规则
      • var rule=rules[i];
    4. 要么获取要么设置
      • console.log(rule.style.css属性名);
      • rule.style.css属性名="css属性值";
  • 一切的获取都是为了判断;一切的设置都是修改或添加
  1. 绑定事件: elem.on事件名=function(){ 操作; } ==this==关键字:目前只能用于事件内: 如果单个元素绑定事件:this->这个元素 如果多个元素绑定事件:this->当前触发事件的元素

总结: 获取 - 往往都是用与判断比较 设置 - 就是添加/修改

创建元素并渲染DOM树

  1. 创建空标签:
    • var 新元素=document.createElement("标签名");
  2. 为此标签设置必要的属性和事件
    • 新元素.属性名="属性值";
    • 新元素.on事件名=function(){操作}
  3. 把新元素上DOM树
    • 父元素.appendChild(elem); - 将elem追加到父元素里当最后一个儿子
    • 父元素.insertBefore(elem,已有子元素) - 将elem追加到父元素里,但是会插入在已有子元素的前面,缺点:会影响到其他元素的下标
    • 父元素.replaceChild(elem,已有子元素) - 将elem追加到父元素里,但是会替换在已有子元素的

删除元素

elem.remove();

HTML DOM常用对象(简化核心DOM)

  1. image对象:仅仅只是简化了创建语句
    • 创建:var img=new Image() === var elem=document.createElement("img");
  2. form对象:简化了查找元素
    • 查找form元素:var form=document.forms[i];
    • 查找form元素中的表单控件:var inp=form.elements[i];
    • 专属事件:form.onsubmit=function(){return false;//阻止提交}//只在表单提交时触发的事件
  3. select对象:
    • 属性:
      • select.options;//得到select下面所有的option,完全等效于xx.children;
      • select.selectedIndex;//得到当前选中项的下标,当时做二级(多级)联动就用到了他
    • 方法:
      • select.add(option);//完全等效于appendChild
      • select.remove(i);//删除下标为i的option
      • 专属事件:select.onchange=function(){//只有选中项发生变化了才会触发}
  4. option对象:仅仅只是简化了创建语句,但是非常牛逼
    • 创建:var opt=new Option("innerHTML","value");
    • 一句话完成四个操作:select.add(new Option("innerHTML","value"))

27.BOM

BOM概念: 提供专门用操作浏览器的一些对象(属性和方法),没有统一标准,存在兼容性问题,使用率相对较低

浏览器弹出框:

  1. 警告框:alert();
  2. 用户输入框:var user=prompt("提示文字","默认值");
  3. 用户确认框:var bool=confirm("提示文字");

定时器:

  • 周期性定时器
    • 开启 timer=setInterval(callback,间隔毫秒数)
    • 停止 clearInterval(timer)
  • 一次性定时器
    • 开启 timer=setTimeout(callback,间隔毫秒数)
    • 停止 clearTimeout(timer)
  • 注意:一次性和周期性定时器底层相同,可以互换 ==面试题== 函数/循环/定时器都能反复执行操作,区别是什么? 时机:
  1. 函数=>用户触发、程序员调用
  2. 循环=>打开页面一瞬间基本就结束了
  3. 定时器=>等待一段时间就做一次

BOM对象:

  1. window对象-扮演两个角色
    1. 代替ES的global,充当全局对象,保存着全局变量和全局函数
    2. 自己也有方法和属性,指代当前窗口本身
      • 属性:
        • 获取浏览器的完整大小:outerWidth/outerHeight
        • 获取浏览器的文档显示区域的大小:innerWidth/inerHeight
        • 获取屏幕的完整大小screen.width/height
      • 方法:
        • 打开窗口:var newW=open('url','自定义的name','width=,height=,lefe=,top=')
          • 注意:
            • 第三个配置参数没有传入时,窗口大小与浏览器相同,并黏在浏览器上
            • 写入第三个实参时,脱离浏览器成为独立的小窗口,可以保存用以绑定事件
            • 宽高有最小限制
        • 关闭窗口:window/newW.close()
        • 修改窗口的大小:newW.resizeTo(宽,高)
        • 修改窗口的位置:newW.moveTo(x,y)

网页打开新链接的方式:4种(目的:提升用户体验感)

  • 替换当前页面,可以后退
  • HTML:<a href='url'>内容</a>
  • JS:open('url','_self')
  • 替换当前页面,禁止后退
  • JS:location.replace('新url')
  • 场景:电商网站用户付款后不允许退回再次付款
  • 原理:
    • history对象:记录着【当前窗口】的历史记录,只有有了历史才能前进后退
    • location对象:记录着【当前窗口】正在打开的url,其replace方法是不会产生任何历史记录的,而url替换后网页必然跳转
  • 新窗口打开,可以打开多个
  • HTML:<a href='url' target='_blank'>内容</a>
  • JS:open('url','__blank');
  • 新窗口打开,只能打开一个
  • HTML:<a href='#' target='自定义name'>内容</a>
  • JS:open('url','自定义name');
  • 场景:电商网站只允许用户打开一个付款页面
  • 原理:每个窗口底层都有一个名字,target属性设置name值,如果name相同新窗口就会替换旧窗口

a标签的作用:

  • 跳转
  • 锚点
  • 下载:<a href='xx.exe/压缩包后缀zip/rar/7z...'>内容</a>
  • 打开:<a href='xx.图片后缀jpg/pgn.../txt'>内容</a>
  • 直接书写JS:<a href='javascript:js代码'>内容</a>
  1. history对象
    • 作用:保存当前窗口的历史记录(打开过的url)
    • 方法:
      • 前进: history.go(1)
      • 后退: history.go(-1)
      • 刷新: history.go(0)
  2. navigator对象
  • 作用:保存了当前浏览器的基本信息,可以使用js来判断我们是什么浏览器以及版本号 - 类似css hack(专门准对老IE解决浏览器兼容问题),但更强大
  • 属性:navigator.userAgent - 值为包含浏览器名和版本号的字符串,想办法格式化后针对不同浏览器写入对应的内容
  1. location对象
    • 作用:保存当前窗口的url,location="新url"即可跳转
    • url网址的组成部分:(5部分)协议名://域名:端口号/路由?请求消息
      • 协议名:http、https、ftp、ws...
      • 域名/主机号:底层都是主机号,域名需要购买
      • 端口号:默认端口号可省略不写,https默认端口为443,http默认端口为80
      • 文件相对路径/路由:决定用户看到哪个网页,可加密隐藏
      • 查询字符串/请求消息:客户端发送到服务器端的内容,服务器端需要接收并判断请求内容,再进行相应
    • 属性:
      • 协议名:location.protocal
      • 域名:location.hostname
      • 端口号:location.port
      • 路由:location.pathname
      • 请求消息:location.search
    • 方法:
      • 跳转后禁止后退:location.replace('新url)
      • 刷新:location.reload()
  2. event对象:事件对象
    • 事件:用户触发或浏览器自动触发的
    • 绑定事件:
      • 在HTML页面绑定事件:
        • <elem on事件名='js语句'>
        • 缺点:
          • 不符合内容/样式/行为分离的原则
          • 无法动态绑定事件,一次只能绑定一个元素
          • 无法同时绑定多个函数对象
      • 在js中使用元素的事件处理函数属性:
        • elem.on事件名=function(){操作}
        • 优点:
          • 符合分离原则
          • 动态绑定事件
          • 无兼容问题
        • 缺点:
          • 无法同时绑定多个函数对象(可以直接将多个功能写一起)
      • 使用专门的事件API绑定事件
        • 主流:elem.addEventListener('事件名',callback)
        • 老IE:elem.attachEvent('on事件名',callback)
        • 兼容:if(elem.addEventListener){ elem.addEventListener('事件名',callback) }else{ elem.attachEvent('on事件名',callback) }
        • 优点:
          • 符合分离原则
          • 动态绑定事件
          • 同时绑定多个对象
        • 缺点:
          • 存在兼容问题
    • 事件周期
      • 主流:3个阶段
        • 捕获阶段,记录着要发生的事件有哪些
        • 目标元素(实际触发事件的元素)优先触发
        • 冒泡触发,向上触发所有记录着的事件
      • 老IE:2个阶段,没有捕获阶段
    • 获取事件对象event
      • 主流:自动作为事件处理函数的第一个形参传入 - elem.on事件名=function(e){e->event}
      • 老IE:event
      • 兼容:var e=event(小三上位)
      • 获取事件对象后可以做的操作
        • 获取鼠标的坐标/位置(3种)
          • e.screenX/Y - 获取鼠标相对于屏幕的位置
          • e.clientX/Y - 获取鼠标相对于客户端/浏览器的位置
          • e.pageX/Y - 获取鼠标相对于页面的位置
          • 应用:鼠标跟随动画,思路:
            1. 鼠标移动事件window/document.onmousemove,添加图片元素,坐标设置为e.pageX/Y
            2. 因为js加载速度快于图片加载速度,在加载事件onload中,添加动画效果
            3. 动画开始时开启定时器删除图片元素
        • 阻止冒泡 =笔试题=开发几乎不用
          • 主流:e.stopPropagation()
          • 老IE:e.cancelBubble=true
          • 兼容:e.cancelBubble=true(小三上位)
        • 事件委托/利用冒泡 =笔试题=开发也用
          • 优化:如果对各子元素定义了相同或相似的事件,最好只给父元素定义一次
          • 原因:每次绑定事件都创建了一个事件对象,创建的事件对象越多,网站性能越差
          • this在事件中仅指向当前元素,在这里需要用到target(目标元素)
          • 主流:e.target
          • 老IE:e.srcElement
          • 兼容:e.srcElement(小三上位)
        • 阻止浏览器的默认行为(如a标签默认跳转页面、右键弹出菜单、F12控制台、F5刷新页面...)
          • 主流:e.preventDefault();
          • 老IE:e.returnValue=false;
          • 兼容:e.returnValue=false;(小三上位)
          • 新事件
            • window.oncontextmenu=()=>{//鼠标右键事件}
            • window.onkeydown=()=>{//键盘事件}
        • 获取键盘的键码
          • e.keyCode 不需要记忆,直接输出查看或搜索,再将其写入对应的条件判断语句

前言

全栈工程师:客户端(PC+移动端+小程序) + 服务器端(Node.js) + 数据库(mongoDB) 全栈晋升路线:全栈 -> 架构师 -> 项目经理 -> 技术总监 可能成为全栈的语言: 1、Java - 不包含移动端开发(能做安卓,不能做IOS) 2、JavaScript语言: 客户端 - 开发根本 服务器端 - Node.js 历史上第一次一门语言可以通吃前后端,前端崛起的原因之一 数据库 - mongoDB 移动端 - 网页、app、小程序 - 跨平台开发,只需要一个前端,学一点点Andriod和IOS的语法,就可以搞定了,前端崛起的原因之一 现在流行混合开发框架:uniapp/h5+plus/jQuery Mobile... 一个前端就可以搞定所有移动端了

sever服务器入门,搭配上ajax,完成最终目标=>全栈开发:登录、注册、后台管理系统

软件架构: C/S - Client客户端/Server服务器端 举例:QQ/大型网络游戏 优点: 运行稳定,用户体验感好,对带宽的要求低 缺点: 占用硬盘空间 更新过于麻烦,服务器端 和 客户端都要更新 B/S - Browser浏览器端/Server服务器端 举例: 网页版QQ、微信/网页游戏 优点: 几乎不占硬盘,不需要安装 更新只需要更新服务器端 缺点: 体验感较差(越来越好)- 云游戏(以后的趋势,不占用硬盘空间也无需相关硬件配置,全部交给云服务器计算),前端崛起的原因之一 现在5G时代的到来,对带宽的要求高

Node.js基础概念

Node.js是基于chrome的v8引擎的JavaScript运行环境 目的:形成了一个前端和数据库沟通交流的桥梁 - 数据交互 官网下载安装后,检验安装:cmd中输入node -v回车 检查版本号 运行方式:

  1. 交互模式 - 临时测试
    • 打开cmd输入node回车 即可输入js代码
    • 退出ctrl+c
  2. 脚本/文件模式 - 正式开发
    • 创建xx.js 书写js代码
    • 打开cmd输入node 文件绝对路径
  3. 编辑器中开发
    • HBuilder 安装nodeeclipse插件
    • VScode 安装Code Runner插件(注意修改配置文件,避免乱码)

js 与 node.js的异同:

  • 相同点:都可以使用ECMAScript的一切语法/API
  • 不同点:
    • JavaScript包括DOM和BOM,用以做特效
    • Node.js不支持DOM和BOM,有自己的模块

Node.js最大的特点:

  • 快 - 以前最快的是php,Node.js的速度是php的14倍,异步能够更大的发挥node.js的特点
  • 为什么快:
    • 因为官方模块提供的东西少,甚至连数据库操作都没有
    • 使用chrome的v8引擎

模块

  • 定义:每一个.js文件都可以称为一个模块.分工合作开发时,将程序按功能分为不同模块再由不同的人完成,最后由主模块进行引入
  • 模块公开/暴露自己的成员:
    • exports.属性名=属性值
    • module.exports={属性名:属性值...}
  • 模块引入其他模块
    • var xxx=require('./文件名')
    • 注意:引入时./不可省略,文件后缀名可省略 ==笔试题==exports和module.exports的区别? 都可以用以公开暴露自己的成员,但exports={...}的写法是错误的,因为在Node.js的底层 exports=module.exports,真正做公开功能的时module.exports,如果使用exports={...}会覆盖module.exports,因此不再具有公开功能
  • 模块的分类
    • 官方模块
    • 第三方模块 - npm下载
    • 自定义模块

官方模块

不需要下载,在你安装node.js环境的时候就已经安好了,但是某的模块需要引入,某的模块不用引入,就需要学习看文档

  1. Globals模块:全局模块 -无需引入,全局可用
    • __dirname:当前文件夹的绝对路径(用以相对路径无法使用的情况)
    • __filename:当前文件的完整绝对路径
    • exports:一个空对象,用以公开/暴露自己的成员
    • require:一个函数,引领其他模块
    • module:指代当前模块本身,包含其他四个变量
    • 定时器
    • 控制台
  2. Querystring模块:查询字符串
    • 需要引入:const qs=require('querystring')
    • 提供解析url查询字符串部分的功能
      • var obj=qs.parse('查询字符串部分'),解析后可直接通过obj.键名获取对应部分
      • 缺陷:只能解析查询字符串部分,无法解析完整url
  3. Url模块:网址
    • 需要引入:const url=require('url)
    • 提供解析完整url的函数
      • var objUrl=url.parse('完整url',true)
      • 此方法能将完整url网址的各个部分全部解析出来,支持传入第二个参数,如果传入的是一个true,自动调用Querystring的parse方法,顺便也解析了查询字符串
      • 获取的重点:
        • 请求消息:objUrl.query.键名 - 拿到前端传入后端的数据
        • 路由:objUrl.pathname - 判断路由,响应不同网页
  4. Buffer模块:缓冲区,将数据转为16进制 - 无需引入,也无需主动使用
    • 可以理解为Buffer是Node.js提供的一种新的数据类型
  5. Fs模块:filesystem 文件系统
    • 需要引入:const fs=require('fs)
    • 提供可以操作文件的API
    • 异步读取文件:
      • fs.readFile('绝对路径|文件路径',(err,buf)=>{需要执行的操作})
      • 注意不可省略形参err只写形参buf
    • 异步写入文件:(将原来的内容替换)
      • fs.writeFile('绝对路径|文件路径','新写入的内容',(err,buf)=>{需要执行的操作})
    • 异步追加文件:(保留原来的内容)
      • fs.append('绝对路径|文件路径','新追加的内容',(err,buf)=>{需要执行的操作})
  6. http模块:使用代码搭建服务器
//引入http、url、fs官方模块
var http=require("http");
var url=require("url");
var fs=require("fs");
//创建服务器
var app=http.createServer();
//为服务器设置监听的端口号
app.listen(80);//http默认端口为80,https默认端口为443
//为服务器绑定请求事件 - 请求?前端发到后端的,
app.on("request",(req,res)=>{
   //req - request:保存请求对象,请求对象,前端->后端,提供了一个属性req.url,解析此属性拿到自己需要的部分(路由|请求消息)
   var objUrl=url.parse(req.url,true);
   //得到前端传来路由部分
   var router=objUrl.pathname;
   //判断前端的路由是什么,给他返回不同的页面
   if(router=="/" || router=="/index.html"){
   	//res - response:保存响应对象,后端->前端,提供了一个方法res.end(你想要响应的东西)
   	fs.readFile("./public/index.html",(err,buf)=>{
   		res.end(buf);
   	})
   }else if(router.match(/html/)!=null){
   	console.log(router);
   	fs.readFile("./public"+router,(err,buf)=>{
   		res.end(buf);
   	})
   }else if(router.match(/css|js|jpg|png|gif|woff/)!=null){
   	fs.readFile("./public"+router,(err,buf)=>{
   		res.end(buf);
   	})
   }
})

强调:

  1. 前端的一切action、href、src,所有引入路径的地方,全都被node.js当作了是一个路由请求,解析请求,读取对应的文件给用户看
  2. 自己想要访问自己,打开浏览器,可以使用127.0.0.1访问自己,访问别人(前提:关闭防火墙),需要别人把自己的ipv4地址给你(打开cmd,输入ipconfig查看ipv4地址)

自定义模块

为什么有的模块要引入时加上./,有的模块又不需要?

  1. 文件模块:创建xx.js去公开需要公开的内容,主模块想要引入必须写为require("./文件名")
  2. 目录模块:3种
    1. 创建名为m1的文件夹,在其中创建index.js的文件,去需要公开的内容,主模块想要引入必须写为require("./文件夹的名字")
    2. 创建名为m2的文件夹,在其中创建xx.js的文件,去需要公开的内容,主模块想要引入必须写为require("./文件夹的名字") 但是需要在m2文件夹中,在创建一个必须package.json的配置文件
    3. 创建一个必须名为node_modules的文件夹,在其中创建名为m3的文件夹,在其中创建index/xx.js的文件,去需要公开的内容,主模块想要引入必须写为require("文件夹的名字")

其实真实开发中,我们程序员用的最多的就是文件模块,目录模块的第三种方式根本就不是人用的,是机器npm的使用的

第三方模块

npm:node package manager:node的模块/包管理器:专门管理第三方模块的,作用:下载安装、删除、更新、维护包的依赖关系... +如何使用第三方模块:

  1. 打开网站:npm官网
  2. 搜索你需要用到的模块,尽量用带有完全符合标志的那个包
  3. 打开cmd:检查一下npm下载工具是否安装成功:npm -v
  4. 下载:npm i 包名
  5. 删除:npm un 包名 - win7系统,删除时只需删除当前包,不会删除依赖关系
  6. 更新:npm up 包名 - 有可能此项目n年后要维护,有可能包就过期了,需要更新

数据库

数据库产品 - 放着很多很多和网站相关的数据

  • 关系型数据库 - 以表格为主
    • Oracle - Oracle(甲骨文) 主要应用于【企业级】开发市场,企业级:大公司、国企、事业单位(银行、警察局),不差钱的公司,安全性很高
    • MySQL - Oracle(甲骨文) 主要应用于【互联网】开发市场,安全性相对较低,但是免费的,中小型公司的首选,但是和Node.js搭配不友好
    • sql server - 微软:大学讲课
  • 非关系型数据库 - 没有固定的格式,是一种运动 - 反关系型数据库
    • 主流产品 - mongoDB,以JSON数据格式为主