ES6
ES6简介
ECMAScript 是浏览器脚本语言的规范,而各种我们熟知的 js 语言,如JavaScript则是规范的具体实现;
JavaScript三大组成部分:
**ECMAScript**:语句语法规范;**BOM**:浏览器对象模型;-
ES6新特性
let 声明变量
1、
var声明的变量往往会越域 ,**let**声明的变量有严格局部作用域
<script>{var a = 1;let b = 2;}console.log(a);console.log(b);</script>
2、
var可以声明多次,**let**只能声明一次
<script>var m=1;var m=3;let n=2;</script>
3、
var会变量提升,let不存在变量提升
<script>console.log("x的值:"+x);//声明前使用var x = 10;console.log("y的值:"+y);//声明前使用let y = 20;</script>
const声明常量(只读变量)
<script>//1.声明之后不允许改变//2.一但声明必须初始化,否则会报错const a=1;</script>
解构表达式
用数组结构赋值(方便)
<script>let arr=[1,2,3];//用数组结构将1,2,3分别赋值给x,y,zlet [x,y,z] = arr;</script>
对象结构
<script>//先声明一个常量const person={name:"张三",age:"19",language:["java","english","chinese"]}//将name,age,language三个属性拿出来const {name,age,language}=person;//将name的属性值赋值到abc中const{name:abc}=person;console.log(name,age,language,abc);</script>
字符串扩展
几个新的 API
<script>//字符串扩展let str = "hello.vue";console.log(str.startsWith("hello"));//判断是否以"hello"开始,返回trueconsole.log(str.endsWith(".vue"));//判断是否以".vueo"结束,返回trueconsole.log(str.includes("e"));//判断是否含"e",返回trueconsole.log(str.includes("hello"));//判断是否含"hello",返回true</script>
字符串模板
模板字符串相当于加强版的字符串,用反引号 `,除了作为普通字符串,还可以用来定义多行字符串,还可以在字符串中加入变量和表达式。
</script> //1、声明多行字符串,以前还需要拼串,现在不需要了 let xml=` <div> <span>hello world<span> </div>`; console.log(xml); //2、字符串插入变量和表达式。变量名写在${}中,${}中也可以写表达式,写方法; let name1 = "张三"; let age1 = 18; let info = `我是${name1},今年${age1+10}了`; console.log(info) </script>函数优化
函数参数默认值
<script> /*以前的做法*/ function add(a, b) { //判断b是否为空,为空就给默认值1 b = b || 1; return a + b; } // 传一个参数 console.log(add(10)); /*现在新特性的做法*/ function add1(a,b=1){ return a+b; } console.log(add1(10)) </script>不定参数
<script> function say(...canshu){ console.log(canshu.length)//输出参数的个数 } say(1);//输出1个 say(1,2,3,4,5,6,7,6)//输出8个 </script>箭头函数
</script> /*箭头函数*/ var print1=obj => console.log(obj); //只有一个参数且方法体只有一行的方法 print1("hello")//调用 var print2=(a,b)=>a+b; //多个参数,只有一行返回值 console.log(print2(1,2)) var print3=(a,b)=>{ c=a+b; return c*c; }//多个参数,方法体不止一行 console.log(print3(1,2)) </script>对象优化
ES6 给Object 拓展了许多新的方法,如:
keys(obj):获取对象的所有key形成的数组values(obj):获取对象的所有value形成的数组entries(obj):获取对象的所有key和value形成的二维数组。格式:[[k1,v1],[k2,v2],...];assign(dest, ...src):将多个src对象的值拷贝到dest中。(第一层为深拷贝,第二层为浅拷贝)<script> /*1、新增的 API*/ const person = { name: "jack", age: 21, language: ['java', 'js', 'css'] } console.log(Object.keys(person));//["name", "age", "language"] console.log(Object.values(person));//["jack", 21, Array(3)] console.log(Object.entries(person));//打印出key,value const target = { a: 1 }; const source1 = { b: 2 }; const source2 = { c: 3 }; //Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。 Object.assign(target, source1, source2); console.log(target)//输出结果为:{a: 1, b: 2, c: 3} /*2、声明对象简写*/ const age = 23 const name = "张三" // 传统 const person1 = { age: age, name: name } console.log(person1) // ES6:属性名和属性值变量名一样,可以省略 const person2 = { age, name } console.log(person2) //{age: 23, name: "张三"} /*3、对象的函数属性简写*/ let person3 = { name: "jack", // 以前: eat: function (food) { console.log(this.name + "在吃" + food); }, // 箭头函数版:这里拿不到this eat2: food => console.log(person3.name + "在吃" + food), // 简写版: eat3(food) { console.log(this.name + "在吃" + food); } } person3.eat("apple");//jack在吃apple person3.eat2("apple");//jack在吃apple person3.eat3("apple");//jack在吃apple </script>对象拓展运算符
拓展运算符
{...}用于取出参数对象所有可遍历属性然后拷贝到当前对象。<script> // 1、拷贝对象(深拷贝) let p1 = { name: "Amy", age: 15 } let someone = { ...p1 }//将p1的属性以及值拷贝到someone中 // 2、合并对象 let myage = { age: 15 } let myname = { name: "Amy" } let p2 = { ...myage, ...myname }//将这两者的属性以及值拷贝到p2中 //如果两个对象的字段名重复,后面对象字段值会覆盖前面对象的字段值 console.log(p2) //{age: 15, name: "Amy"} </script>map和reduce方法map
接收一个函数,将原数组中的所有元素用这个函数处理后放入新数组返回。
<script> let arr = ['1', '20', '-5', '3']; console.log(arr) //数组中的字符都转化为数字,并*2 arr = arr.map(s => parseInt(s)*2); console.log(arr) </script>reduce
语法:
arr.reduce(callback,[initialValue])**reduce**为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用**reduce**的数组。**callback**(执行数组中每个值的函数,包含四个参数)previousValue(上一次调用回调返回的值,或者是提供的初始值(initialValue))currentValue(数组中当前被处理的元素)index(当前元素在数组中的索引)array(调用reduce的数组)
initialValue(作为第一次调用callback的第一个参数。)
<script>
let arr1 = [2, 40, -10, 6];
let result=arr.reduce((a,b) => {
console.log("上一次处理后:"+a)
console.log("当前正在处理:"+b)
return a+b;
},100)
console.log(result);
</script>
Promise
在JavaScript的世界中,所有代码都是单线程执行的。由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现。一旦有一连串的ajax请求a,b,c,d...后面的请求依赖前面的请求结果,就需要层层嵌套。这种缩进和层层嵌套的方式,非常容易造成上下文代码混乱,我们不得不非常小心翼翼处理内层函数与外层函数的数据,一旦内层函数使用了上层函数的变量,这种混乱程度就会加剧……总之,这种层叠上下文的层层嵌套方式,着实增加了神经的紧张程度。
场景
- 查出当前用户信息;
- 按照当前用户的id查出他的课程;
- 按照当前课程id查出分数;
传统嵌套方法(比较乱)
<script> /* 1、查出当前用户信息 2、按照当前用户的id查出他的课程 3、按照当前课程id查出分数 */ //以前的方法 $.ajax({ url:"mock/user.json", success(data){ console.log("查询用户:",data); $.ajax({ url:`mock/user_corse_${data.id}.json`, success(data){ console.log("查询到课程:",data); $.ajax({ url:`mock/corse_score_${data.id}.json`, success(data){ console.log("查询到课程分数:",data); } }); }, }); }, }); </script>使用Promise
<script> //使用promise封装异步操作 //1、先声明一个公用函数 function get(url,data){ return new Promise((ifsuccess,iferror)=>{ $.ajax({ url:url, data:data, success:function(data){ ifsuccess(data)//成功的话 }, error:function(err){ iferror(data)//失败的话 } }); }); } //2、进行操作 get("mock/user.json") .then((data)=>{//动态取值就需要用``号不能用双引号 console.log("查询用户:",data); return get(`mock/user_corse_${data.id}.json`); }).then((data)=>{//then得到上一步成功的数据 console.log("查询到课程:",data); return get(`mock/corse_score_${data.id}.json`); }).then((data)=>{ console.log("查询到课程成绩:",data); }).catch((err)=>{ console.log("出现异常:",err); }); </script>模块化
什么是模块化
模块化就是把代码进行拆分,方便重复利用。类似java中的导包:要使用一个包,必须先 导包。而JS中没有包的概念,换来的是模块。
模块功能主要由两个命令构成:export和import。
export命令用于规定模块的对外接口。-
导出export
const util={ sum(a,b){ return a+b; } } var name="zzk" export {util,name} //还可以简写为: // export const util={ // sum(a,b){ // return a+b; // } // }export不仅可以导出对象,一切JS变量都可以导出。比如:基本类型变量、函数、数组、对象。
导入import
import util from "./hello.js"//“./”一个点“.”代表当前目录 import name from "./hello.js" //也可以直接import {util,name} from "./hello.js" var c=util.sum(1,2) console.log(c) console.log(name)vue
更多信息访问vue官网:vuejs.org
MVVM思想 M:即 Model,模型,包括数据和一些基本操作;
- V:即 View,视图,页面渲染结果;
- VM:即 View-Model,模型与视图间的双向操作(无需开发人员干涉);
在MVVM之前,开发人员从后端获取需要的数据模型,然后要通过DOM操作Model渲染到View中。而后当用户操作视图,我们还需要通过DOM获取View中的数据,然后同步到Model中;
而 MVVM中的VM要做的事情就是把DOM操作完全封装起来,开发人员不用再关心Model和View之间是如何互相影响的:
- 只要我们
Model发生了改变,View上自然就会表现出来。 - 当用户修改了
View,Model中的数据也会跟着改变。
把开发人员从繁琐的DOM操作中解放出来,把关注点放在如何操作Model上。
安装
npm安装:**npm install vue**(安装最新稳定版)之后通过**<script>**标签引入
【注意:npm安装的话你的project名不能和安装的依赖同名】
也可以直接下载然后**<script>**标签下引入;
npm安装:
- 先执行初始化命令
**npm init -y**表示此项目交由npm管理,之后就会生成一个文件package.json, 之后再执行命令
**npm install vue**安装(如果安装特定版本可以直接在**vue**后面加**@版本号**);使用
helloworld程序:
<div id="app"> <h1>{{name}},很帅</h1> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> let vm=new Vue({ el: "#app", data: { name: "张三" } }) </script>双向绑定
效果:我们修改表单项,num会发生变化。我们修改 num,表单项也会发生变化。为了实时观察到这个变化,我们将num输出到页面。
我们不需要关注他们为什么会建立起来关联,以及页面如何变化,我们只需要做好数据和视图的关联即可(MVVM)<div id="app"> <input type="text" v-model="num"> <h1>{{name}},很帅,{{num}}人为他点赞</h1> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> let vm=new Vue({ //属性名和属性值一样的时候可以只写“属性(名|值),” el: "#app", data: { name: "张三", num: 1 } }) </script>
输入框标签里面添加一个属性_v-model_并赋值,在需要输出的地方_{{这个属性值}}_,然后在vue对象的data属性值添加上该值并附上默认值即可;事件处理
在标签中添加一个属性
v-on:xxx="xxx",其中xxx为要对某个属性做的操作,例如还是上面的例子,我添加一个<button_v-on:click_="num++">点赞</button>则每点击一次则vue实例中data属性中的num属性就会+1;
还可以单独写一个方法,点击时调用这个方法来操作数据(把方法都放在vue实例的methods属性里面);<button v-on:click="cancle">取消点赞</button> ... <script> let vm=new Vue({ el: "#app", //与某元素绑定属性 data: { //封装数据 name: "张三", num: 11 }, methods:{ //封装方法 cancle(){ this.num--; } } }) </script>指令
v-text和v-html可以使用
v-text和v-html指令来替代双大括号{{}}说明:
**v-text**:将数据输出到元素内部,如果输出的数据有HTML代码,会作为普通文本输出;**v-html**:将数据输出到元素内部,如果输出的数据有HTML代码,会被渲染;-
v-bind(单向绑定)**v-bind**给html标签的属性进行绑定(即双引号里面的内容)<!-- 给html标签的属性进行绑定 --> <div id="app"> <a v-bind:href="link">go baidu</a> </div> <script src="../node_modules/vue/dist/vue.js"></script> <script> new Vue({ el: "#app", data:{ link: "http://www.baidu.com" }, }); </script>
并且还对属性style和class做了单独的增强:<!-- 给html标签的属性进行绑定 --> <div id="app"> <a v-bind:href="link">go baidu</a><br> <!-- 还对class属性和style属性进行了增强 --> <span v-bind:class="{active:isActive,'text-danger':hasError}" v-bind:style="{color:clo,fontSize:fsize}">测试</span> <!-- 根据isActive的bool值进行判断是否class="active" --> <!--根据hasError的bool值进行判断是否class="'text-danger'" (因为“-”是非法的,所以加个单引号,也可直接驼峰命名textDnger)--> <!-- 下面同理 --> </div> <script src="../node_modules/vue/dist/vue.js"></script> <script> new Vue({ el: "#app", data:{ link: "http://www.baidu.com", isActive:false, hasError:true, clo:'red', fsize: '66px' }, });v-model(双向绑定)<div id="app"> 请选择: <br> <input type="checkbox" v-model="language" value="java"><br> <input type="checkbox" v-model="language" value="phpa"><br> <input type="checkbox" v-model="language" value="golang"><br> 你选择的有: <span v-text="language"></span> </div> <script> let vm=new Vue({ el:"#app", data:{ language:[] //选中的属性值把存在language的数组里面 }, }) </script>
<div id="app"> <h1>你写的是:{{msg}}</h1> <br> <input type="text" v-model:value="msg"> <!--value可省略,即写为v-modele="msg"--> </div> <script> new Vue({ el: '#app', data: { msg:"" } }) </script>v-on基础用法
调用事件,例如调用点击事件:
<div id="app"> <button v-on:click="numAdd">+{{num}}</button><br> <!--也可以简写:@click=xxx--> <span v-text="num"></span> </div> <script> new Vue({ el:"#app", data:{ num: 1 }, methods:{ numAdd(){ this.num+=2 } } }); </script>事件修饰符
事件冒泡问题:子元素的操作连带了父元素;例如:
<div id="try" v-on:click="hello"> 大div <br> <div @click="hello"> 小div </div> </div> <script> new Vue({ el: '#try', methods:{ hello(){ alert("点击了") } }, }); </script>这样的话点击“小div”的话就会
alert("点击了")两次,这就属于时间冒泡事件;
为了解决这个问题,Vue.js 为v-on提供了事件修饰符。修饰符是由点开头的指令后缀来表示的。 .stop:阻止事件冒泡到父元素;.prevent:阻止默认事件发生;.capture:使用事件捕获模式;.self:只有元素自身触发事件才执行。(冒泡或捕获的都不执行).once:只执行一次;
这里就可以用:<div_@click.stop_="hello">
按键修饰符(v-on:keyup或@keyup)
在监听键盘事件时,我们经常需要检查常见的键值。Vue允许为v-on在监听键盘事件时添加按键修饰符;
全部的按键别名:
.enter.tab.delete.esc.space.up.down.left.right
例如:在一个输入框内按”上键”数值增加,按”下键”数值减少,如下:<inputv-model="num1"type="text"v-on:keyup.up="num1++"@keyup.down="num1--">
也可以用设置组合键,例如:<inputv-model="num1"@click.ctrl="num1+=10">
这样ctrl+单击数据就会+10;
v-for
遍历用的;
<div id="app">
<ul>
<li v-for="(user,index) in users":key="user.name">
<!--遍历的时候加上“:key”来区分不同数据,提高vue渲染效率,key值为数据里面的唯一属性-->
<!--第一个参数是值,第二个参数值索引-->
当前索引:{{index}};当前元素值:{{user.name}}--->{{user.age}} <br>
</li>
</ul>
</div>
<script>
new Vue({
el:"#app",
data:{
//定义一个对象数组
users:[
{name:"张三",age:12},
{name:"李宗盛",age:22},
{name:"瘦鸡",age:32},
{name:"事件",age:42},
{name:"微软",age:15},
]
}
});
</script>
v-if和v-show
<h1 v-if="bool">如果bool=true就看到我v-if</h1><br>
<h1 v-show="bool">如果bool=true就看到我v-show</h1><br>
不同的是当bool=false时v-if所在元素是消失,而v-show所在元素是用style="display: none;"修饰:
计算属性和侦听器
<div id="app">
<ul>
<li>西游记;价格:{{xyjPrice}},数量:<input type="number" v-model="xyjNum"></li>
<li>水浒传;价格:{{shzPrice}},数量:<input type="number" v-model="shzNum"></li>
<li>总价:{{totalPrice}}</li>
</ul>
{{msg}}
</div>
<script>
new Vue({
el: '#app',
data:{
xyjPrice: 190.1,
shzPrice: 12.12,
xyjNum: 1,
shzNum: 1,
msg: "",
},
computed:{//声明一个计算属性
totalPrice(){//完成总价的计算
return this.xyjNum*this.xyjPrice+this.shzNum*this.shzPrice
}
},
watch:{//声明一个监听器,监听西游记的数量
xyjNum: function(newVal,oldVal){
//新式语法可以直接写为: xyjNum:(..){..}
if(newVal>3){
this.msg="购买数量过多"
}else{
this.msg=""
}
}
},
});
</script>
过滤器
过滤器不改变真正的data,而只是改变渲染的结果,并返回过滤后的版本。在很多不同的情况下,过滤器都是有用的,比如尽可能保持API响应的干净,并在前端处理数据的格式。
<div id="app">
<ul>
<li v-for="user in userList">
{{user.id}}===>{{user.name}}==>{{user.age}}
==>{{user.age|ageFilter}}==>{{user.age|gFilter}}<br>
<!--用管道符“|”将user.age传入ageFilter方法的参数中-->
</li>
</ul>
</div>
<script>
//声明一个全局过滤器
//(必须声明在局部过滤器之前,否则全局过滤器失效)
Vue.filter("gFilter",function(val){
if(val>=18){
return"成年~~~~~";
}else{
return"未成年~~~~";
}
});
new Vue({
el:"#app",
data:{
userList:[
{id:1,name:"张三",age:13},
{id:2,name:"张静怡",age:23},
{id:3,name:"张诺",age:17},
]
},
filters:{//声明一个局部过滤器
ageFilter(val){
if(val>=18){
return"成年";
}else{
return"未成年";
}
}
},
});
</script>
组件化
在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。 但是如果每个页面都独自开发,这无疑增加了我们开发的成本。
所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。在vue里,所有的vue实例都是组件;
全局组件
<div id="app">
<counter></counter> <!--调用自定义全局组件-->
<!--用组件名声明一个标签名 -->
</div>
<script>
//1、全局声明注册一个组件
Vue.component('counter',{//参数是组件名
template: '<button @click="count++">我被点击了{{count}}次</button>',
data(){
return{count:1}
}
});
new Vue({
el:"#app",
data:{
count: 1,
}
});
</script>
- 组件其实也是一个
**Vue**实例,因此它在定义时也会接收:data、methods、生命周期函数等 - 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有
el属性。 - 但是组件渲染需要
html模板,所以增加了template属性,值就是HTML模板 ; - 全局组件定义完毕,任何
vue实例都可以直接在HTML中通过组件名称来使用组件了 data必须是一个函数,不再是一个对象;
局部组件
一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue的加载而加载。因此,对于一些并不频繁使用的组件,我们会采用局部注册。
<div id="root">
<!--调用自定义局部组件-->
<my-counter></my-counter>
</div>
<script>
//声明一个局部组件
const myCounter={
template: '<button @click="count++">我被点击{{count}}次</button>',
data(){
return{count:1}
}
};
new Vue({
el:"#root",
data:{
count:1
},
//components就是当前vue对象子组件集合。
components:{//在此放入所有自定义局部组件
'my-counter':myCounter
}
});
</script>
组件的**data**属性必须是函数!一个组件的data选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝;
Vue生命周期和钩子函数
生命周期
每个Vue实例在被创建时都要经过一系列的初始化过程 :创建实例,装载模板,渲染模板等等。Vue为生命周期中的每个状态都设置了钩子函数(监听函数)。每当Vue实例处于不同的生命周期时,对应的函数就会被触发调用。
钩子函数使用
beforeCreated:我们在用Vue时都要进行实例化,因此,该函数就是在Vue实例化时调用,也可以将他理解为初始化函数比较方便一点,在Vue1.0时,这个函数的名字就是init。created:在创建实例之后进行调用。beforeMount:页面加载完成,没有渲染。如:此时页面还是{{name}};mounted:我们可以将他理解为原生js中的window.onload=function({.,.});或许大家也在用jquery,所以也可以理解为jquery中的$(document).ready(function(){….}),他的功能就是:在dom文档渲染完毕之后将要执行的函数,该函数在 Vue1.0 版本中名字为compiled。 此时页面中的{{name}}已被渲染成张山;beforeDestroy:该函数将在销毁实例前进行调用。destroyed:改函数将在销毁实例时进行调用。beforeUpdate:组件更新之前。updated:组件更新之后。<div id="root"> <button @click="age++">{{name}}:{{age}}</button> </div> <script> new Vue({ el: '#root', data:{ name:"张山", age:1, }, beforeCreate() { console.log("数据模型加载前"); }, created(){ console.log("数据模型加载完成"); }, beforeMount(){ console.log("页面加载完成,没有渲染"); }, beforeDestroy(){ console.log("实例销毁前"); }, destroyed(){ console.log("实例销毁完成"); }, beforeUpdate(){ console.log("准备修改") } }); </script>使用Vue脚手架进行模块化开发
初始化步骤:
1、全局安装webpack:
npm install webpack -g
2、安装vue脚手架(这里与老师版本一致4.0.3):npm i -g @vue/cli@4.0.3 --force- (
--force表示覆盖以前的vue脚手架版本) - 可用命令
vue-V检查所安装vue脚手架版本或是否安装成功vue脚手架;
- (
3、初始化项目:vue init webpack 项目名(vue脚手架使用webpack模板初始化项目)
4、进入都初始化项目的vue-demo目录里面,执行语句npm run dev项目运行,运行成功浏览器访问http://localhost:8080/,如下:
项目结构


运行流程:
- 进入页面首先加载
index.html和main.js文件。 main.js导入了一些模块【vue、app、router】,并且创建vue实例,关联index.html页面的<div id=”app”>元素。使用了router,导入了App组件。并且使用<App/>标签引用了这个组件;- 第一次默认显示App组件。App组件有个图片和
<router-view>,所以显示了图片。但是由于<router-view>代表路由的视图,默认是访问/#/路径(router路径默认使用HASH模式)。在router中配置的/是显示HelloWorld组件。 - 所以第一次访问,显示图片和
HelloWorld组件。 我们尝试自己写一个组件,并且加入路由。点击跳转。需要使用
<router-link to="/foo">Go to Foo</router-link>标签;手动构建一个单文件组件
// 组件三要素:template,script,style <template> <div> <h1>你好hello{{name}}</h1> </div> </template> <script> export default{ data() { return { name: '张静怡', }; }, } </script> <style> </style>然后在
**router**里面加上这个vue的路由;... import Hello from '@/components/Hello' //引入刚才创建的Hello.vue ... //下面创建这个路由 { path: '/hello', name: "hello", component: Hello, }详情见官网:vueRouter;
Vue整合ElementUI快速开发
elementUI组件库网址:element.eleme.cn
npm安装:
npm i element-ui -S(也可以手动下载下来)- 之后在
main.js里面引入:importElementUIfrom'element-ui';import'element-ui/lib/theme-chalk/index.css';
- 之后让
Vue使用ElementUI:Vue.use(ElementUI) -
axiosaxios是独立于vue的一个项目,基于promise用于浏览器和node.js的http客户端; 在浏览器中可以帮助我们完成
ajax请求的发送;-
nodejsnodejs是**JavaScript**运行环境,类似于java里面的jdk,不需要浏览器通过nodejs直接运行js文件;简介
什么是
Node.js简单的说
Node.js就是运行在服务端的JavaScript。Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。Node.js有什么用 如果你是一个前端程序员,你不懂得像PHP、Python或Ruby等动态编程语言,然后你想创建自己的服务,那么
Node.js是一个非常好的选择。Node.js是运行在服务端的JavaScript,如果你熟悉Javascript,那么你将会很容易的学会Node.js。- 当然,如果你是后端程序员,想部署一些高性能的服务,那么学习
Node.js也是一个非常好的选择。
**cmd**查看**nodejs**版本:**node -v**;
npm
npm简介
什么是npm
npm全称Node Package Manager,是Node.js包管理工具,是全球最大的模块生态系统,里面所有的模块都是开源免费的;也是Node.js的包管理工具,相当于前端的Maven。
npm工具的安装位置
我们通过npm可以很方便地下载**js**库,管理前端工程。Node.js默认安装的npm包和工具的位置:Node.js目录\node_modules
- 在这个目录下你可以看见
npm目录,npm本身就是被npm包管理器管理的一个工具,说明Node.js已经集成了npm工具; **cmd**查看npm版本:npm** -v**;使用
项目初始化
**cmd**在目标文件夹内执行命令**npm init**执行初始化(会让你选择默认js文件name属性,vue版本等信息,也可以直接执行**npm init -y**全部使用默认值);按照提示输入相关信息,如果是用默认值则直接回车即可。
name:项目名称;
version:项目版本号;
description:项目描述;
keywords:{Array}关键词,便于用户搜索到我们的项目;
最后会生成
package.json文件,这个是包的配置文件,相当于maven的pom.xml我们之后也可以根据需要进行修改。
修改npm镜像
- 设置淘宝镜像:
npm config set registry https://registry.npm.taobao.org; - 查看
**npm**配置信息:npm config list; - 测试,比如下载
**jquery**:npm install jquery; - 也可以直接根据配置文件下载:直接根据配置文件下载,直接执行
npm install;
- #使用
**npm install**安装依赖包的最新版, - #模块安装的位置:
**项目目录\node_modules** - #安装会自动在项目目录下添加
**package-lock.json**文件,这个文件帮助锁定安装包的版本 - #同时
**package.json**文件中,依赖包会被添加到**dependencies**节点下,类似**maven**中的**<dependencies>** - #
**npm**管理的项目在备份和传输的时候一般不携带**node_modules**文件夹
**npm install**- #根据
**package.json**中的配置下载依赖,初始化项目
**npm install jquery@指定版本号**- #如果安装时想指定特定的版本
# 局部安装:依赖只在当前项目中能用
- #
**devDependencies**节点:开发时的依赖包,项目打包到生产环境的时候不包含的依赖 - #使用-D参数将依赖添加到
**devDependencies**节点 **npm install --save-dev eslint**#或**npm install -D eslint**
#全局安装
- #Node.js全局安装的npm包和工具的位置:
**用户目录\AppData\Roaming\npm\node_modules** - #一些命令行工具常使用全局安装的方式
**npm install -g webpack**
- #使用
#更新包(更新到最新版本) npm update 包名 #全局更新 npm update -g 包名 #卸载包 npm uninstall 包名 #全局卸载 npm uninstall -g 包名
模块化开发
es5写法
自定义方法
//定义两个自定义方法
const sum=function(a,b){
return parseInt(a)+parseInt(b);
}
const subtract=function(a,b){
return parseInt(a)-parseInt(b);
}
//设置2个方法可以被其他js调用
module.exports={
sum,subtract
}
调用自定义方法
/*调用自定义方法*/
const m=require('./myMethod.js')
console.log(m.sum(1,1));
console.log(m.subtract(1,1));
结果
PS E:\IDEAworks\classroom\moduleDemo\es5> node .\useMyMethod.js 2 0
es6写法
注:**es6不能直接用,需要进行转码,转码过程较为复杂,之后在框架中会直接进行转码,这里不转码**
自定义方法
/*自定义方法:myMethod.js*/
//定义两个可以被其他js调用的自定义方法
//定义方法-1
export function sum(a,b){
return parseInt(a)+parseInt(b);
}
export function subtract(a,b){
return parseInt(a)-parseInt(b);
}
//定义方法-2
export default{
sum(a,b){
return parseInt(a)+parseInt(b);
},
subtract(a,b){
return parseInt(a)-parseInt(b);
}
}
调用自定义方法
/*调用自定义方法:useMyMethod.js*/
//调用方法-1
import {sum,subtract} from "./myMethod1.js"
console.log(sum(1,1));
console.log(subtract(1,1));
//调用方法-2
import * as m from "./myMethod1.js"
console.log(m.sum(1,1));
console.log(m.subtract(1,1));
跨域问题
比如前后端调用,**3**个地方:**访问协议**,**访问ip**,**端口号**有任何一个不一样就会产生跨域问题,不能正常访问,跨域问题本质是浏览器对ajax请求的一种限制;
解决
- 在后端接口
controller添加注解**@CrossOrigin**; - 使用
httpclient; - 通过
gateway网关;
