position
1.position:relative;相对定位
- 对照自身原来的位置定位,发生定位偏移以后自身原来的位置还在,不脱离文档流。
2.position:absolute;绝对定位
- 不会占据原有的位置,脱离文档流
- 如果外层元素含有(非static 默认定位)定位属性,那么以外层定位元素(0,0)点为参照定位
- 如果外层元素不含定位属性,那么以html(0,0)点为参照定位
3.position:fixed;固定定位
- 不会占据原有的位置,脱离文档流
- 以浏览器(0,0)点为参照定位
字符串的常用方法
1.计算字符串的长度
-
str.length
,会计算空格数。
2.查找字符在字符串中的位置:
-
Str.indexof("要找的字符")
,从前往后找,只找第一个,返回值是索引。没有找到返回值-1,兼容性很好。 -
Str.lastIndexof("要找的字符")
,从后往前找,只找第一个,返回值是索引。没有找到返回值-1,兼容性很好。
3.根据传入索引,查找该元素是什么
-
Str.charAt(index)
4.根据传入索引,查找该元素编码是什么
-
Str.charCodeAt(index)
5.根据字符编码查找该字符
-
String.fromCharCode()
6.字符串截取的方法
-
Str.slice(start,end)
-
作用:对字符串截取,start表示截取的开始元素,end表示截取的截止元素,包前不包后。
-
返回值:截取的字符串
-
console.log(str.slice(0,4));//0是起始索引,4是结束索引,不包含4 console.log(str.slice(4));//表示从4到结束 console.log(str.slice(-3));//表示倒数第三到最后
-
-
Str.substr(start,length)
-
作用:对字符串截取,start表示截取的开始元素,length表示截取的长度
-
返回值:截取的字符串
-
console.log(str.substr(0,2));//从0开始截取2个 console.log(str.substr(2));//从2开始到最后 console.log(str.substr(-3,2))//从倒数第三个,截取2个
-
-
str.substring(start,end)
- 作用:对字符串进行截取
- 参数:start表示截取开始的索引,end表示截取结束的索引,end要大于start,不允许负数
- 返回:从start到end的字符串,不包含end
7.字符串变小写
-
Str.toLowerCase()
8.字符串变大写
-
Str.toUpperCase()
9.去除前后空格
-
str.trim()
数组的常用方法
1.兼容性较好
1.1.增
-
数组.unshift(item)
;
从数组前面增加一个元素
- 作用:从数组前面增加一个元素
- 参数:item要新增的那个元素
- 返回值:数组的长度
- 注意点:直接在原数组操作
-
数组.push(item)
:
从数组后面增加一个元素
- 作用:从数组后面增加一个元素
- 参数:item要新增的那个元素
- 返回值:数组的长度
- 注意点:直接在原数组操作
1.2.删
-
数组.shift()
:
删除数组中的第一个元素
- 作用:删除数组中的第一个元素。
- 返回值:被删除的那个元素。
- 参数:无
- 注意:直接在原数组操作,不会生成新数组。
-
数组.pop()
:
删除数组中的最后一个元素
- 作用:删除数组中的最后一个元素
- 返回值:被删除的那个元素。
- 参数:无
- 注意:直接在原数组操作,不会生成新数组。
-
数组.splice(start,n)
:**
从数组的start位置开始删除n个元素
- 作用:从数组的start位置开始删除n个元素
- 参数:start表示从哪个索引开始删除,n表示要删除几个元素
- 返回值:被删除的元素的集合
- 注意点:直接在原数组操作
数组.splice(start,n,.....)
:
从数组的start位置开始删除n个元素,然后再添加什么元素
- 作用:从数组的start位置开始删除n个元素,新增m个元素
- 参数:start表示从哪个索引开始删除或者增加,n表示要删除几个元素,后面由m个参数,就是要增加要数组中的新元素,从索引是start位置开始增加。
- 返回值:被删除的元素的集合
- 注意点:直接在原数组操作
1.3.截取
-
数组.slice(start,end)
:从数组中截取一部分
- 作用:从数组中截取一部分
- 参数:start表示开始截取的索引,end表示结束截取的索引,包start,不包end,(包前不包后)
- 返回值:返回一个新的数组,包含从 start 到 end (不包括该元素)的 所有元素
- 注意点:返回一个新数组,原数组不变
1.4.
颠倒数组
-
数组.reverse()
:
颠倒数组
- 作用:颠倒数组
- 参数:无
- 返回值:原数组
- 注意点:直接在原数组操作
1.5.
连接数组
-
数组1.concat(数组2,数组3,......)
:
- 作用:用于连接多个数组
- 参数:要被连接的那些数组
- 返回值:连接好的新数组
- 注意点:不在原数组操作,会产生新数组
1.6.数组变字符串
-
数组.join(“分割符”):把数组变成字符串
- 作用:把数组变成字符串
- 参数:默认是逗号,分隔符
- 返回值:生成的那个字符串
- 注意点:不会改变原数组
1.7.查询
-
数组.indexof(ele,start)
-
作用:查找数组中某个元素的索引
-
返回值:如果没找到就返回-1,如果找到了就返回该元素的索引值。
-
参数:第一个参数ele是:要查找的那个元素
第二个参数start:从哪里开始查找,默认从零开始找
-
-
数组.lastIndexof(ele,start)
-
作用:查找数组中某个元素的索引
-
返回值:如果没找到就返回-1,如果找到了就返回该元素的索引值。
-
参数:第一个参数ele是:要查找的那个元素
第二个参数start:从哪里开始查找,默认从零开始找
-
1.8.数组排序
-
数组.sort(fn)
;-
作用:按照指定规则进行排序
-
参数:如果不写参数,默认是按照字符编码的顺序进行排序,如果写参数,参数fn是表示排序 规则的函数
-
返回值:返回值就是拍好序的数组
-
注意点:直接在原数组操作
-
有参数:参数是表示排序规则的函数
-
示例“
arr.sort(function(a,b){ return a-b; })由小到大排序 arr.sort(function(a,b){ return b-a; })由大到小排序
-
typeof 的返回值
- string
- number
- boolean
- undefined
- objcect
- function
数组的遍历
1.for循环
for(var i=0;i<arr.length;i++){
console.log(arr[i])
}
2.for in 循环
for( var index in arr){
//固定写法,arr是要循环的数组,index是循环到的那个元素的索引
console.log("当前循环到的是第"+index+'个元素,元素的值是:'+arr[index])
}
3.forEach()循环
数组.forEach(function(value,index){
要循环执行的函数,数组里面有多少个元素,该函数就执行多少次
console.log("当前循环到的是第"+index+'个元素,元素的值是:'+value)
})
//参数:要循环执行的函数,函数有两个形参,第一个形参实循环到的那个数组元素的值,第二个形参实循环到的那个数组元素的索引
//注意点:不会改变原数组
4.map()循环
数组.map(function(value,index){
要循环执行的函数,数组里面有多少个元素,该函数就执行多少次
return value-1
})
//作用:循环数组
//参数:要循环执行的函数,函数有两个形参,第一个形参实循环到的那个数组元素的值,第二个形参实循环到的那个数组元 素的索引
//返回值:整个map的返回值是每一次循环的函数的返回值的集合
//示例:
var arr = [23,45,43,78,23,12,46,28,97];
console.log(arr)
var newArr = arr.map(function(value,index){
return value-1;
})
console.log(newArr)//newArr = [22,44,42,77,22,11,45,27,96]
5.fliter()循环
数组.fliter(function(value,index){
//要循环执行的函数,数组里面有多少个元素,该函数就执行多少次
//符合条件的返回true
//不符合条件的返回false
if(value>40){
return console.log(true);
}else{
return false;
}
})
//作用:过滤数组中符合条件的元素,返回值是新的数组
6.every()循环
数组.every(function(value,index){
//要循环执行的函数,数组里面有多少个元素,该函数就执行多少次
})
//作用:判断数组中的每一个元素是否都符合条件,符合返回值true,不符合返回值false
//示例:
var arr = [1,15,26,48,45,25,14,44]
var res = arr.every(function(value,index){
return value>30;
})
console.log(res)
7.some()循环
数组.some(function(value,index){
//要循环执行的函数,数组里面有多少个元素,该函数就执行多少次
})
//作用:判断数组中的每一个元素是否有符合条件,符合返回值true,不符合返回值false
//示例:
var arr = [1,15,26,48,45,25,14,44]
var res = arr.every(function(value,index){
return value>30;
})
console.log(res)
遍历对象
1.for in()
- 主要用于遍历对象,可枚举属性,包括自有属性,继承自原型的属性
var obj = {"name":"tom","sex":"male"};
Object.defineProperty(obj, "age", {value:"18", enumerable:false});//增加不可枚举的属性age
Object.prototype.protoPer1 = function(){console.log("name is tom");};//通过原型链增加属性,为一个函数
Object.prototype.protoPer2 = 2;通过原型链增加属性,为一个整型值2
for(var key in obj){
console.log(key)//['name','sex','protoPer1','protoPer1']
}
2.Object.keys()
-
Object.keys主要用于遍历对象自有的可枚举属性,不包括继承自原型的属性和不可枚举的属性。
var obj = {"name":"tom","sex":"male"}; Object.defineProperty(obj, "age", {value:"18", enumerable:false});//增加不可枚举的属性age Object.prototype.protoPer1 = function(){console.log("name is tom");};//通过原型链增加属性,为一个函数 Object.prototype.protoPer2 = 2;通过原型链增加属性,为一个整型值2 console.log("Object.keys:") console.log(Object.keys(obj));//["name",'sex']
3.Object.getOwnPropertyNames()
-
Object.getOwnProperty主要用于返回对象的自有属性,包括可枚举和不可枚举的属性,不包括继承自原型的属性。
var obj = {"name":"tom","sex":"male"}; Object.defineProperty(obj, "age", {value:"18", enumerable:false});//增加不可枚举的属性age Object.prototype.protoPer1 = function(){console.log("name is tom");};//通过原型链增加属性,为一个函数 Object.prototype.protoPer2 = 2;通过原型链增加属性,为一个整型值2 console.log("Object.getOwnPropertyNames: "); console.log(Object.getOwnPropertyNames(obj));//["name","sex","age"]
正则表达式
1.正则表达式:
- 定义字符的规则,也可定义输入字符串的规则。由普通的字符和元字符组成。
-
通过构造函数定义正则表达式:
var reg = new RegExp(/lucy/)
或者
var reg = new RegExp('lucy')
-
通过字面量来定义正则表达式://里面都是字符串
var reg = /lucy/
2.元字符:
- \d 元字符表示0-9
- \D 元字符表示非数字
- \w 元字符表示单词字符:字母数字下划线
- \W 元字符表示非单词字符:
- \s 元字符表示空白字符
- \S 元字符表示非空白字符
- . 元字符表示除\n\r以外的任意字符(元字符用于查找单个字符,除了换行和行结束符)
- \ 表示转义
3.标识符
- g 表示全局去找
- i 表示不区分大小写
4.字符串的方法
-
str.match(reg/字符) 字符串的方法
- 找到一个或者多个字符
- 返回值是找到的字符第一个字符的下标
var str = 'aasjdhhfiiasd46af454as6f4a5s465464f6a5s445454saf64a56s4d'
str.match(/[0-9]+/g)
-
str.search(reg/字符)
- 参数可以是字符串或者正则表达式
- 查找字符串中是否含有指定的字符
- 返回值:如果找到就返回第一个的子串的下标,找不到返回-1
- 只找第一个。g不起作用
5.test(‘要检索的字符串’)方法
- 检索字符串中指定的值,返回值true和false
var reg = /lucy/;
console.log(reg.test("hello lucy"))//true
6.量词
-
指定字符出现的次数
- 指定出现n次,在要出现的字符后面添加{n}
- 指定出现m到n次,在要出现的字符后面添加{m,n}
- 指定出现n次以上,在要出现的字符后面添加{n,}
- 指定出现1次或者1次以上,在要出现的字符后面添加+或者{1,}
- 指定出现0次或者1次,在要出现的字符后面添加?或者{0,1}
- 指定出现0次或者多次,在要出现的字符后面添加*或者{0,}
- 精确匹配n:^n$
- 以n开头:^n
- 以n结尾:n$
7.方括号
- [abc] 表示abc中的任意一个
- [^abc] 表示不包含abc中的任意一个
- [1-9] 表示1-9中的任意一个
面向对象案例
1.选项卡切换
1.1.css样式
<style>
*{
margin: 0;
padding: 0;
}
.box{
width: 400px;
height: 300px;
margin: 200px 0 0 800px;
border: 1px solid #000;
}
.tits{
width: 400px;
height: 40px;
}
.tits li{
width: 98px;
height: 38px;
float: left;
border: 1px solid #000000;
font-size: 20px;
line-height: 38px;
text-align: center;
list-style: none;
}
.content{
width: 400px;
height: 260px;
position: relative;
}
.content li{
width: 400px;
height: 260px;
display: none;
position: absolute;
top: 0;
left: 0;
font-size: 40px;
line-height: 260px;
text-align: center;
list-style: none;
}
.box .tits .titsShow{
background: pink;
}
.box .content .contentShow{
display: block;
}
</style>
1.1.html结构
<div class="box">
<ul class="tits ">
<li class="titsShow">音乐</li>
<li>新闻</li>
<li>娱乐</li>
<li>电影</li>
</ul>
<ul class="content">
<li class="contentShow">音乐</li>
<li>新闻</li>
<li>娱乐</li>
<li>电影</li>
</ul>
</div>
1.3.javaScript代码
//1.面向过程的方法去写
<script>
//获取元素
var tits = document.querySelectorAll('.tits li');
var cons = document.querySelectorAll('.content li');
var prevIndex = 0;
//给元素添加绑定事件
for(var i = 0;i < tits.length;i++){
tits[i].index=i;
tits[i].onclick=function(){
console.log('我被点击了')
//给上一个元素清除leiming
tits[prevIndex].className="";
cons[prevIndex].className="";
//给元素添加类名
tits[this.index].className="titsShow";
cons[this.index].className="contentShow";
//更新全局的prevIndex
prevIndex = this.index;
}
}
</script>
//2.面向对象的方法去写
把变量变成对象的属性,此时tish指向对象,对象上的原型上方法只有对象的实例才能调用,也就是说,原型方法上的this指向调用者。
(function(){
//写一个切换函数
function Tab (tits,cons){
this.tits = tits;
this.cons = cons;
this.prevIndex = 0;
}
//写一个切换类名的函数
Tab.prototype.setClass=function(dom,oClass){
dom.className=oClass;
}
//事件处理机制
Tab.prototype.bindEvent=function(){
var _this=this;
for(var i = 0;i<this.tits.length; i++){
this.tits[i].index=i;
this.tits[i].onclick =function(){
_this.clickHandler(this.index)
}
}
}
//点击事件
Tab.prototype.clickHandler=function(index){
//上次选中的元素的类名清空
this.setClass(this.tits[this.prevIndex],'')
this.setClass(this.cons[this.prevIndex],'')
//给本次选中的元素添加类名
this.setClass(this.tits[index],"titsShow");
this.setClass(this.cons[index],"contentShow");
//更新元素下标
this.prevIndex=index;
}
//创建一个初始话函数,返回示例对象,方便链式调用
Tab.prototype.init=function(){
this.bindEvent()
return this
}
//创建一个工厂函数(创建实例化对象,不需要用户再new了)
function factory (d,c){
return new Tab(d,c).init()
}
window.$=factory;//对外暴露一个接口
})()
var tits = document.querySelectorAll('.tits li');
var cons = document.querySelectorAll('.content li');
$(tits,cons)
三大家族之offset、scroll、client
1.offset家族
- 元素.offsetWidth/Height //元素的宽高:content+padding+margin
- 元素.offsetTop/Left //元素距离最近的有定位的父元素的距离
- 元素.offsetParent //元素的距离最近的有定位的父元素
2.scroll家族
-
元素.scrollWith/Height //如果内容的宽度/高度,就等于内容的宽高
-
元素.scrollTop/Left //页面被卷曲的高度,有兼容问题
解决办法:
元素.scrollTopLeft = document.body.scrollTop/Left ||document.documentElement.scrollTop/Left
3.client家族
-
元素.clientWidth/Height 元素得宽高:content+padding
-
浏览器可视区域宽高:window.innerWidth/Height (有兼容问题)
浏览器可视区域宽高:怪异模式:document.body.clientWidth
标准模式 document.documentElement.clientWidth
4.在JQ中三大家族的使用
$("元素“).offset()
语法:
- 不传递参数的时候就是读取 ,读到的元素相对于页面的位置关系,返回值是一个对象 { left: xxx, top: xxx }
- 传递一个对象就是写入 { left: xxx, top: xxx }
position()
语法:
- 只读的方法,元素相对于定位父级的位置关系,得到的也是一个对象 { left: xxx, top: xxx }
scrollTop()
/
scrollLeft()
语法:
- 不传递参数的时候就是获取卷去的高度/宽度
- 传递一个参数就是设置卷去的高度/宽度
event 对象
-
存在兼容问题:
var event = e ||window.event
-
获取鼠标距离页面可是距离的X,Y
event.clientX
获取鼠标距离页面可视距离左侧的宽度
event.clientY
获取鼠标距离页面可视距离顶部的高度
event.pageX
获取鼠标距离页面左侧的宽度==
event.clientX+window.scrollLeft
(包括页面看的见的和看不见的)
event.pageY
获取鼠标距离页面顶部的高度==
event.clientY+window.scrollTop
(包括页面看的见的和看不见的)
BOM中的五大对象
1.window: 窗口对象 BOM核心
2.history:历史路径
- history.forword() //下一个页面
- history.back() //上一个页面
- history.go(index) //往前挑几个页面
3.loacltion:地址栏对象
- location.href //完整的地址
- location.protocol //协议
- location.port //端口号
- location.hostname //主机名称
- location.pathname //路径名称
- location.search // ?后面的数据部分
4.navigator:导航器对象
- navigator.appName //产品名称
- navigator.appVersion //产品版本号
- navigator.userAgent //用户代理信息
- navigator.platForm //系统平台信息
5.screen:屏幕对象
- screen.width //屏幕的宽度
- screen.height //屏幕的高度
- screen.availWidth //可用屏幕的宽度
- screen.availHeight //可用屏幕的高度
ES6常用API
1.变量定义
1.1.var 声明的变量
- 在代码执行前会进行预解析
- 同一个变量名可以重复定义
- 只有全局作用域和函数作用域,没有块级作用域
- 在函数内,函数的参数优先级高于变量
1.2.let 声明的变量
-
let 没有预解析
-
let 不能重复声明,在函数内部允许声明与形参相同的变量
-
let 有块级作用域
-
let 声明以后后期可以赋值
var liArr = document.body.children[0].chidren; for(let i=0;i<liArr.length;i++){ liArr[i].onclick = function () { alert(i) } }
1.3.const 声明的变量
- const 没有预解析
- const 不能重复声明
- const 有块级作用域
- const 声明的时候要同时赋值,后期不能重复赋值(类似常量)
- 变量名一般全字母大写
2.JSON
2.1.JSON.parse(string)
- 把一个像json的字符串转变成json对象
2.2.JSON.stringify(json对象)
- 把一个json对象转变成json字符串
3.箭头函数
3.1.ES5函数
- 普通函数里的this指向调用者
var fn1 = function(){}//函数表达式
function fn2 (){}//函数声明
box.onclick = function (){}//匿名函数或者 时间处理函数
(function(){})()//自执行函数
1.改变this指向,.bind(this)
box.onclick = function (){
console.log(this)
setTimeout(function(){
console.log(this)
}.bind(this),2000)
}
3.2.ES6语法提供了函数默认值
var sum = function (a=1,a=2){
return a+b;
}
console.log(sum(0,0))
3.3.箭头函数
- 箭头函数不会改变this指向,它内部的this指向上层结构的this,没有arguments参数
- 箭头函数不能用new,作为构造函数来创建实力对象
let test1 = ()=>{}//箭头函数
setTimeout(()={},2000)
box.onclick = ()=>{}
(()=>{})()//自执行函数
//简写:
1.如果函数体上只有一句话,可以省略{}
let fn = ()=>console.log(1);
2.如果函数体上只有一句话,可以省略{},但如果这一句话是return,则return也可省略
let fn1 = ()=>666;
3.如果参数只有一个,且不需要在参数中设置默认值,可以省略()
let fn3 = a=>a;
4.参数打包
4.1.
5.箭头函数里的参数
5.1.
数组去重
1.for循环嵌套,利用splice去重
function newArr(arr){
for(var i=0;i<arr.length;i++){
for(var j=i+1;j<arr.length;j++){
if(arr[i]==arr[j]){
//如果第一个等于第二个,splice方法删除第二个
arr.splice(j,1);
j--;
}
}
}
return arr;
}
let a= m.map((item,index,array)=>{
console.log(array)
})
console.log(a)
2.建新数组,利用indexOf去重
function newArr(array){
//一个新的数组
var arrs = [];
//遍历当前数组
for(var i = 0; i < array.length; i++){
//如果临时数组里没有当前数组的当前值,则把当前值push到新数组里面
if (arrs.indexOf(array[i]) == -1){
arrs.push(array[i])
};
}
return arrs;
}
3.ES6中利用Set,Array.from去重
function newArr(arr){
return Array.from(new Set(arr))
}
4.ES6中利用Set,扩展运算符去重
function newArr(array){
return arr=[new Set(array)]
}
阻止事件传播/阻止浏览器默认行为
1.事件捕获
event.stopPropagation()
2.事件冒泡
event.cancelBubble=false
低版本IE
3.阻止浏览器默认行为:火狐/谷歌
event.preventDefault()
4.阻止浏览器默认行为:低版本IE
event.returnValue=false
服务器+PHP+MYSQL
1.服务器
1.1.前端认知:
-
前端
- 把后端给的数据展示在页面上(列表页面)
- 把前端的数据传递给后端, 让后端存储起来(注册)
-
后端
- 当前端需要数据的时候, 后端从数据库里面拿到数据给前端
- 把前端传递来的数据存储在数据库里面
-
数据库
- 专门让 后端 进行数据的增删改查
-
流程
- 前端 -> 后端 -> 数据库 -> 后端 -> 前端
-
注意:
- 前端是不能操作数据库的
- 前端相对数据库进行任何操作, 都要把信息告诉后端
- 由后端进行数据库操作
- 把操作的信息反馈给前端
1.2.服务器
-
什么是服务器 ?
- 就是一台在网络 “那一头” 的一台电脑,只不过运行了一些特殊的环境,运行了一个特殊的 “软件”。
-
服务器的作用 ?
-
当一台电脑运行了一个服务器环境以后,在这台电脑上, 就会由一个文件夹被对外开放了, 叫做
服务器空间
,只要你在整个服务器空间(文件夹) 里面放上对应的 html 文件,其他的小伙伴就会根据网线找到你这台电脑, 找到对应的文件夹,就可以看到里面的页面了(只读的权限)。 - 运行服务端代码,如果我们写一个后端代码, 那么需要在服务器环境下运行, 因为浏览器不支持后端代码的运行。
-
当一台电脑运行了一个服务器环境以后,在这台电脑上, 就会由一个文件夹被对外开放了, 叫做
-
了解:
- http 传输协议, 浏览器会自动帮你添加 80 端口号
- https 传输协议, 浏览器会自动帮你添加 443 端口号
1.3.集成环境
- WAMP: windows + apache + mysql + php
- MAMP: Mac OS + apache + mysql + php
- LAMP: Linux + apache + mysql + php
2.PHP
2.1.php是 一个后端语言
- 运行需要在 apache 服务器上运行
- 我们要把 php 文件写在 WWW 目录里面
- 在浏览器以 localhost 的形式运行
- .php 代码写在一个 .php 后缀的文件里面
- .html 后缀的文件不认识 php 代码的
- php 文件不允许使用中文命名
2.2.php 里面的三种输出语法
- echo 输出内容;
- print_r(输出内容);
- var_dump(输出内容);
2.3.三种输出语法的详细区别
-
echo
- 只能输出基本数据类型, 复杂数据类型会报错
- 遇到布尔值的时候, true 会输出 1, false 会输出空白内容
-
print_r()
- 可以输出所有数据类型
- 遇到布尔值的时候, true 会输出 1, false 会输出空白内容
-
var_dump()
- 可以输出所有数据类型
- 遇到布尔值会正常输出 true 输出 true, false 输出 false
- 并且会带有数据的类型和数据的信息
2.4.php 里面的字符串
-
在 js 里面 字符串的定义由两种
-
单引号,双引号,
这两个没有任何区别
-
单引号,双引号,
-
在 php 里面 字符串 定义也是两种方式(两种方式是有区别的)
- 单引号: 就是普通字符串
- 双引号: 是一个特殊字符串, 可以在字符串里面直接解析变量,类似jsES6的模板字符串
2.5.php 里面的字符串拼接
-
就是把多个字符串连接在一起
- 我们在 js 里面的时候, 使用 加号(+) 就能进行字符串拼接
- 在 php 里面, 加号(+) 只能进行数学运算, 只有 点(.) 才能进行字符串拼接
2.6.索引型数组
-
语法: $arr = array(数据1, 数据2, 数据3, …)
- 按照索引下标进行排列
- 如果向单独获取数组里面的某一个数据,数组名称[对应的索引]
- 等价于 js 里面的数组
2.7.关联型数组
-
语法: $arr = array(key1 => value1, key2 => value2);
- 获取关联型数组里面某一项的值,数组名称[‘你要获取的属性名’]
- 等价于 js 里面的对象
-
注意:
- 不管是 key 还是 value, 需要用引号包裹, 单引号也行, 双引号也行
- 不可以不包裹, 如果不用引号包裹, 会被当作变量来使用(报错)
- 中间用的是 =>, 不是 : 也不是 =
- 数字和布尔值, 不需要引号包裹, 可以直接使用
2.8.php 转换 json 格式的两个方法
-
把 php 的数据格式转换成 json 的数据格式
-
json_encode()
简记pej - 语法: json_encode(要转换的 php 数据格式)
- 返回值: 转换好的 json 数据格式
-
-
把 json 数据格式转化成 php 的数据格式
-
json_decode()
简记jdp - 语法: json_decode(要转换的 json 格式数据)
- 返回值: 转换好的 php 格式数据
-
2.9.接受前端传过来的数据
-
$_REQUEST()
-
$_GET()
-
$_POST()
2.10.中文解析
-
header('content-type:text/html;charset=utf-8')
3.MYSQL
3.1.SQL语法
-
sql 语句的语法规范(你可以不遵守, 建议你遵守)
- sql 语句里面的关键字大写
- 表名和字段名尽可能使用反引号(键盘 tab 键上面那个按钮 “)包裹
-
sql 语句的语法规则(你必须遵守, 不然报错)
- 当你写一些文本内容的时候, 需要使用 引号 包裹, 表示是一个 字符串
-
数据库增删改查
-
增:INSERT关键字
-
一共两种语法:
-
INSERT INTO
表名
VALUES(数据1, 数据2, 数据3, …);- 按照你数据库里面字段的顺序插入的
- id 我们可以不写, 直接写 null, 会自动增长
-
INSERT INTO
表名
(字段1, 字段2, …) VALUES(数据1, 数据2, …);- 按照你书写的字段添加
- 值添加某些字段的内容, 剩下的稍后完善的时候在做
-
INSERT INTO
-
一共两种语法:
-
删:DELETE关键字
-
DELETE FROM
表名
WHERE 条件- 要从哪一个表删除条件为什么的数据
-
DELETE FROM
-
改:UPDATE关键字
-
UPDATE
表
SET 字段=新值 WHERE 条件 -
UPDATE
表
SET 字段=新值, 字段2=新值 WHERE 条件
-
UPDATE
-
查:SELECT关键字
-
SELECT * FROM
表
- 查询这个表里面的所有数据
-
SELECT * FROM
表
WHERE 条件- 根据我们的条件查询数据库里面的数据
-
SELECT * FROM
表
WHERE 条件1 AND 条件2- 根据两个条件来查询, 两个条件必须都满足
-
SELECT * FROM
表
WHERE 条件1 OR 条件2- 根据两个条件来查询, 两个条件满足一个就可以了
-
SELECT * FROM
表
WHERE 字段 LIKE ‘%关键字%’- 查询数据里面指定字段包含某一个关键字的数据
-
SELECT * FROM
-
3.2.MYSQL数据库的固定操作
-
和数据库进行连接
-
$link = mysqli_connect('IP地址', '数据库用户名', '数据库密码', '仓库名字');
-
-
设置字符编码
-
mysqli_set_charset(utf8");
-
-
执行操作
-
$res=mysqli_query('连接数据库的信息', '你要执行的 sql 语句');
-
-
解析结果
-
$rows=mysqli_fetch_all($res,1)
-
-
断开数据库连接
-
mysqli_close($link)
-
服务器同源策略/解决跨域请求
1.服务器同源策略
- 同源策略,指的是浏览器对不同源的脚本或者文本的访问方式进行的限制。
- 同源指两个页面具有相同的协议,主机(也常说域名),端口,三个要素缺一不可。
- 同源策略就是为了保证网站的数据安全而存在。
2.URL构成:
-
url:
http://image.baidu.com:80/search/detail?ct=503316480&z=undefined#header
- http —- 超文本传输协议
- [image.baidu.com] —- 域名
- 80 —- 端口
- /search/detail —- 资源目录
- ct=503316480&z=undefined —- 发送到服务器的数据
- #header —- 锚点
3.跨域
- 跨域是指在浏览器上进行非同源请求的行为
4.解决跨域问题的办法
1.jsonp方法
-
jsonp跨域就是利用script标签的跨域能力请求资源
-
既然叫jsonp,显然目的还是json,而且是跨域获取
-
利用js创建一个script标签,把json的url赋给script的scr属性,把这个script插入到页面里,让浏览器去跨域获取资源
-
script标签特性:src请求到的数据(字符串),会被当成js执行
-
callback是页面存在的回调方法,参数就是想得到的json
-
回调方法要遵从服务端的约定一般是用 callback 或者 cb
-
注意:jsonp针对get形式的请求
1.1jsonp的封装
//jsonp发送ajax请求 function jsonp(options){ // 把options.success函数声明为全局函数 'mycallback' window[options.callbackName] = options.success; // 判断参数,如果是字符串,直接赋值给data var data = ''; if (typeof options.data === 'string'){ data = options.data; } // 判断参数,如果是对象,把对象格式化成参数序列的字符串再赋值给data if (typeof options.data === 'object' && options.data !== null && options.data.constructor === Object){ // 把{abc:123,ddd:777} 转成 'abc=123&ddd=777' for (var key in options.data){ data += key+'='+options.data[key]+'&'; } // data = 'abc=123&ddd=777&'; data = data.substring(0,data.length-1); } // 创建script标签,并且给src属性赋值(数据地址、参数、参数值) var Script = document.createElement('script'); Script.src = options.url+'?'+ options.cb +'='+options.callbackName+'&'+data; document.body.appendChild(Script); // script标签加载完成时,删除该标签 Script.onload = function (){ document.body.removeChild(Script); } }
1.2.jQuery 发送jsonp请求
$.ajax({ type: "get", //jsonp只能发送get请求 async: false,//不异步 url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998", dataType: "jsonp",//这里吧标注jsonp,jQ就判断发送jsonp请求 jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名 (一般默认为:callback) jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动 生成的随机函数名,也可以写"?",jQuery会自动为你处理数据 success: function(json){ alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。'); }, error: function(){ alert('fail'); } });
2.CORS 跨域资源共享(xhr2)
-
CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)
-
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
-
整个CORS通信过程,都是浏览器自动完成,不需要用户参与
-
对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样
-
实现CORS通信的关键是服务端,只要服务端实现了CORS接口,就可以跨源通信
-
示例:
实现CORS并不难,只需服务端做一些设置即可:如 <?php header("Access-Control-Allow-Origin:*"); // 允许任何来源 注意:IE10以下不支持CORS
3.代理跨域
-
在服务器上配置代理,然后请求代理标识符D:\phpstudy_pro\Extensions\Nginx1.15.11\conf\vhosts\localhost_80.conf
# 配置代理 # https://www.duitang.com/napi/vienna/feed/list/by_common/?start=0&limit=18 # 当我们请求 http://localhost/dt 时,Nginx转发到 https://www.duitang.com/napi/vienna/feed/list/by_common/ location = /dt { proxy_pass https://www.duitang.com/napi/vienna/feed/list/by_common/; }
ajax
1.什么是ajax?
- AJAX是再一种无需重新加载整个页面的情况下,也能够更新网页部分的技术(局部刷新)
- AJAX是一个异步的代码,再程序中同步异步的区别就是,同步代码按照顺序执行,异步代码不按照顺序执行。
2.ajax的优点?
- 页面无刷新更新数据:ajax最大的优点就是能够在不刷新网页的情况下与服务器通信维护数据;
- 异步与服务器通信:ajax使用异步方式与服务器通信 ,不需要打断用户的操作,具有更加迅速的响应能力;
- 前端和后端负载平衡:ajax可以把以前一些服务端负担的工作转嫁到客户端,减轻服务器和带宽的负担,节约空间和宽带租用成本;
- 基于标准被广泛支持:ajax基本标准化的并被广泛支持的技术,不需要下载浏览器插件;
- 界面与应用分离:ajax使WEB中的数据与呈现分离,有利于分工合作,提高效率。
3.ajax的缺点
- ajax干掉了Back和History功能:即对浏览器机制的破坏,在动态页面的情况下,用户无法回到前面一个页面状态;
- ajax有安全问题:ajax技术给用户带来了很好的用户体验的同时也带来了新的安全威胁,ajax技术就如同对企业数据建立了一个直接的通道;
- 对搜索引擎支持较弱:对搜索引擎优化不太好;
- 破坏程序的异常处理机制:像Ajax。dll,Ajaxpro.dll这些Ajax框架是会破坏程序的异常机制;
- AJAX不能很好支持移动端设备;
4.如何使用ajax
-
主流W3C标准浏览器都支持XMLHttpRequest对象
-
低版本IE浏览器使用的是 ActiveXObject
4.1.创建ajax对象
var xhr = new XMLHttpRequest();//主流W3C标准浏览器 //考虑兼容 if(window.XMLHttpRequest){ // 非IE5 IE6 var xhr=new XMLHttpRequest(); }else{ // IE5 IE6 var xhr=new ActiveXObject("Microsoft.XMLHTTP"); };
4.2.初始化ajax请求
xhr.open(method,url,async); //参数说明: method:请求数据类型 get/post url:文件在服务器上的位置 async: 可选,默认ture(异步),false(同步)
4.3发送请求
xhr.send(param); //参数说明: param:对于get请求,参数为null param:对于post请求,参数为发送到服务器的数据 //为post请求时,需要在send()之前设置http请求头:作用模拟表单post来传递参数 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded") //get/post区别 1.语义化不一样 GET倾向于从服务器获取数据 post倾向于从服务器提交数据 2.传递参数的方式 GET请求直接在地址栏后边拼接 post请求在请求体里面传递 3.参数大小限制 GET请求一般理论上不大于2KB post请求理论上没有上线 4.缓存能力 GET会被浏览器主动缓存 POST不会被浏览器主动缓存 5.安全性能 GET请求相对安全性较低 POST请求相对安全性较高 get/post本质上都是tcp连接
4.4请求-响应状态
//readystate 属性存有XMLHttpRequest对象的状态,会从0-4发生变化; 0:请求未初始化 1:服务器连接已经建立 2:请求已经接收 3:请求处理中 4:请求已经完成 //当readystate改变时就会触发onreadystatechange事件 //status:http请求状态码 //下面是常见的Http请求状态码: 200:请求成功 301:网页被重定向到其他的url 304:文件未被修改,使用缓存资源 404:找不到此网页(指定的资源) 500:服务器内部错误 //当readyState为 4 且 status为 200 时,表示请求已完成,成功得到响应结果 xhr.onreadystatechange=function (){ if (xhr.readyState==4) { // 请求完成 if (xhr.status==200) { //ok 成功 alert( xhr.responseText ); // 得到响应结果 } else{ alert( xhr.status ); // 弹出失败的状态码 }; }; } //xhr.responseText 获得文本形式的响应数据 //xhr.responseXML 获得 XML 形式的响应数据
5.封装ajax
5.1封装ajax
//封装ajax请求
function ajax(options){
1.创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
//判断传入的参数类型,处理一下data,变成字符串数据
//如果data为对象
var data = "";
if(typeof options.data === "string"){
data = options.data;
}
if(typeof options.data === "object" && options.data!==null && options.data.constructor === Object){
//{abc:123, ddd:777}转变成'abc=123&ddd=777'
for(var key in options.data){
data += key+"="+options.data[key]+"&";
}
//data='abc=123&ddd=777&'
data = data.substring(0,data.length-1)
//data='abc=123&ddd=777'
}
//判断请求类型
if(options.type.toLowerCase()==='get'){
2.初始化一个请求
xhr.open(options.type,options.url+"?"+data+"&_="+Date.now())
3.发送一个请求
xhr.send()
}else if (options.type.toLowerCase()==='post'){
2.初始化一个请求
xhr.open(options.type,options.url)
//设置请求头
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
3.发送一个请求
xhr.send(data)
}els{
alert('目前只支持 get和post 请求!')
}
4.请求-响应状态
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300) {
options.success(xhr.responseText)
} else {
options.error(xhr.status)
}
}
}
}
//参数说明:
options:是一个参数对象
options ={
type:"GET/POST", //请求的类型
url: , //请求的地址
data:{
//请求携带的参数,支持字符串类型,对象类型
},
success:function(){
//请求成功的回调,要执行的内容
}
error:function(){
//请求失败的回调,要执行的内容
}
}
5.2.使用Promise封装ajax
function promiseAjax(options){
return new Promise(function(resolve,reject){
// 1.创建XMLHttpRequest对象(数据交互对象)
var xhr = new XMLHttpRequest();//w3c标准
// var xhr = new ActiveXObject('Microsoft.XMLHTTP');//IE 5 6
var data = '';
if (typeof options.data === 'string'){
data = options.data;
}
if (typeof options.data === 'object' && options.data !== null && options.data.constructor === Object){
// 把{abc:123,ddd:777} 转成 'abc=123&ddd=777'
for (var key in options.data){
data += key+'='+options.data[key]+'&';
}
// data = 'abc=123&ddd=777&';
data = data.substring(0,data.length-1);
// console.log(data);
}
// return;
// 判断请求方式
if (options.method.toLowerCase() === 'get'){
xhr.open(options.method,options.url+'?'+data+'&_='+Date.now(),true);
xhr.send(null);// get请求
} else if (options.method.toLowerCase() === 'post'){
xhr.open(options.method,options.url,true);
// 作用是模拟表单post来传递参数
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send(data);// post请求发送数据
} else {
alert('目前只支持 get和post 请求!')
}
// 4.请求-响应 状态
xhr.onreadystatechange = function (){
// console.log(xhr.readyState);
if (xhr.readyState == 4){//请求完成 (请求状态)
if(xhr.status >= 200 && xhr.status < 300){// 得到响应数据 (响应状态)
resolve(xhr.responseText);
} else{
reject(xhr.status);
}
}
}
});
}
Promise
1.简述
1.1概述
- Promise是异步编程的一种解决方案,从语法上讲,Promise是一个对象,可以获取异步操作的消息
1.2.目的
- 避免回调地狱的问题
- Promise对象提供了简洁的API,使得控制异步操作更加容易
1.3.Promise的三种状态:
- pendding //正在请求
- rejected //失败
- resolved //成功
1.4.基础用法:
new Promise(function(resolve,reject){
})
1.5.resolved,rejected函数:
- 在异步事件状态pendding->resolved回调成功时,通过调用resolved函数返回结果;当异步操作失败时,回调用rejected函数显示错误信息。
1.6.then的用法
-
then中传了两个参数,第一个对应resolve的回调,第二个对应reject的回调
p.then((data) => { console.log('resolved',data); },(err) => { console.log('rejected',err); } );
1.7.catch方法
-
捕捉promise错误函数,和then函数参数中rejected作用一样,处理错误,由于Promise抛出错误具有冒泡性质,能够不断传递,会传到catch中,所以一般来说所有错误处理放在catch中,then中只处理成功的,同时catch还会捕捉resolved中抛出的异常
p.then((data) => { console.log('resolved',data); }) .catch((err) => { console.log('rejected',err); });
1.8.all方法/race方法
-
Promise.all([promise1,promise2])——参数是对象数组。以慢为准,等数组中所有的promise对象状态为resolved时,该对象就为resolved;只要数组中有任意一个promise对象状态为rejected,该对象就为rejected
-
race方法:Promise.race([promise1,promise2])——参数是对象数组。以快为准,数组中所有的promise对象,有一个先执行了何种状态,该对象就为何种状态,并执行相应函数
let p = Promise.all([Promise1, Promise2]) p.then((data) => { //都成功才表示成功 }) .catch((err) => { //有一个失败,则都失败 });
async await
Localstorage
1.设置Localstorage的键值:
Localstorage.setItem('key''val');
2.获取Localstorage的值:
Localstorage.setItem('key');
3.获取key:
Localstorage.key(索引);
4.清除Localstorage:
localStorage.clear();
5.删除某一条Localstorage:
localStorage.removeItem('key');
6.json对象转json字符串:
JSON.stringify()
7.json字符串转成json对象:
JSON.parse()
闭包、原型/原型链、继承
1.闭包
1.1.官方解释
- 一个拥有许多变量和绑定了这些变量的环境表达式(通常是一个函数),因而这些变量也是该表达式的一部分
-
当一个函数能够记住并访问到其所在的词法作用域及作用域链,特别强调是在其定义的作用域外进行的访问,此时该函数和其上层执行上下文共同构成闭包。
- 闭包就是指有权访问另一个函数作用域中的变量参数的函数。
- 闭包就是能够读取其他函数内部变量(参数)的函数
- 闭包可以理解成定义在一个函数内部的函数
1.2.特别需要明确几点
- 闭包一定是函数对象
- 闭包和词法作用域、作用域链、垃圾回收机制等息息相关
- 函数内保持对上层作用域的引用
- 当函数在其定义的作用域外进行访问时,才产生闭包
- 闭包是由该函数和其上层执行上下文共同构成
1.3.闭包的应用
-
在函数外读取函数内部的变量;
-
让局部变量的值能够被保存下来;
-
将模块的公有属性和方法暴露出来。
-
function fn1(){ var n = 5; return function fn2() { n++; return n; } } var fn = fn1(); console.log( fn() ); console.log( fn() ); console.log( fn() );
1.4.变量
- 变量无非就是全局变量和局部变量
- Javascript语言中,函数内部可以直接读取全局变量,在函数外部无法直接读取函数内的局部变量。
1.5.作用域的概念:
- 通常来说,一段程序代码中所用到的名字并不总是有效可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
-
词法作用域:
- 词法作用域,也叫静态作用域,它的作用域是指在词法分析阶段就确定了,不会改变。
- 动态作用域,是在运行时根据程序的流程信息来动态确定的,而不是在写代码时进行静态确定的。
- 主要区别:词法作用域是在写代码或者定义时确定的,而动态作用域是在运行时确定的。
- 词法作用域关注函数在何处声明,而动态作用域关注函数从何处调用。
- javascript 使用的是词法作用域
2.原型原型链
- JavaScript是一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言。
-
我们把JS中的对象分为
普通对象
和
函数对象
2.1.prototype(原型)
-
每一个函数对象(Function.prototype除外)都有一个prototype属性(这个属性指向一个对象即原型)
-
prototype原型是函数的一个默认属性,在函数的创建过程中由JS编译器自动添加
-
内置构造函数String、Number他们的原型指向一个普通对象,(Number{}和String{}),而Function的原型则指向函数对象function(){[native code]},这是原生代码。而这个函数对象(Function.prototype)是没有原型,即没有原型属性,所以他的prototype返回undefined。
-
var fn1 = function (){ }; var fn2 = new Function(); function fn3(){ }; console.log(fn1.prototype);//{constructor:ƒ __proto__:Object} console.log(fn2.prototype);//{constructor:ƒ anonymous() __proto__:Object} console.log(fn3.prototype); // {constructor:ƒ fn3() __proto__:Object} //Object{} 这就是我们所说的原型,它是一个对象也叫原型对象 // 为什么说 Function.prototype 除外呢?看代码: console.log(Number.prototype);//Number{constructor:ƒ Number() __proto__:Object} console.log(String.prototype);//String{constructor:ƒ String() __proto__:Object} console.log(Function.prototype);//ƒ () { [native code] } console.log(Function.prototype.prototype);// 结果看下图undefined
-
可以看到内置构造函数Number、String等,它们的原型指向一个普通对象(Number{}和String{})
-
Function的原型则指向函数对象 function () { [native code] },这是原生代码!这个函数对象(Function.prototype)是没有原型属性的,所以它的prototype返回 undefined。
-
function Cat(){}; Cat.prototype.name = '小白'; // 给原型对象添加属性 Cat.prototype.color = 'black'; // 给原型对象添加属性 Cat.prototype.sayHello = function (){ // 给原型对象添加方法 console.log('大家好,我的名字叫'+this.name); } var cat1 = new Cat(); // 实例对象 var obj = Cat.prototype;// 原型对象 console.log(obj);//{name: "小白", color: "black", sayHello: ƒ, constructor: ƒ} console.log(cat1.constructor);//ƒ Cat(){} console.log(obj.constructor);//ƒ Cat(){} console.log(Cat.prototype === cat1.constructor.prototype);
-
可以看到Cat这个构造函数,它的原型指向一个对象,即原型对象({name: “小白”, color: “black”, sayHello: ƒ, constructor: ƒ})
-
这个原型对象的constructor(构造器)指向Cat构造函数
-
cat1实例对象的constructor(构造器)也指向Cat构造函数
-
2.2.constructor(构造器)
-
每个对象都有一个隐藏属性constructor,该属性指向对象的构造函数(“类”)
-
通过上面的代码我们可以看到,实例对象 cat1 和原型对象 obj 它们的构造器相同,都指向 Cat!我们换一种写法:
-
function Cat(){} Cat.prototype = {// 原型对象 name: '小白', color: 'black', sayHello: function (){ console.log('大家好,我的名字叫'+this.name); } } var cat1 = new Cat(); console.log(Cat.prototype === cat1.constructor.prototype); //false console.log(Cat.prototype.constructor === Object); //true console.log(cat1.constructor === Object); //true
-
此时 Cat.prototype 指向一个对象字面量方式定义的对象{},其构造器(constructor)指向的自然是根构造器 Object,所以 cat1 的构造器也指向根构造器 Object。
-
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
-
2.3.
_ _ proto _ _
(原型)
-
每个对象都有一个隐藏属性
_ _proto_ _
即原型对象,用于指向创建他的构造函数的原型即原型对象 。 -
也就是说: 实例.
_ _proto_ _
===构造函数.prototype -
对象 通过_ _ proto _ _指向原型对象,函数对象 通过prototype指向原型对象
-
Object.prototype.jdk = 'abc123'; Object.prototype.sayHi = function (){ console.log('嗨~大家好'); } var str = 'yoyo'; str.sayHi(); // 嗨~大家好 console.log(str.jdk); // 'abc123'
-
str 是怎么访问到 sayHi 方法和 jdk 属性的呢?
- hasOwnProperty() 方法 ,用于判断某个属性是否为该对象自身的成员
-
看看大致的访问过程:
-
console.log(str.hasOwnProperty('sayHi'))
;//false str自身没有sayHi方法
console.log(str.__proto__.hasOwnProperty('sayHi'));
//false 原型对象也没有sayHi方法
console.log(str.__proto__.__proto__.hasOwnProperty('sayHi'))
;//true 原型的原型有sayHi方法str -> str._ _ proto _ _ -> str._ _ proto _ _ . _ _ proto _ _ 感觉到什么吗?
-
-
我们来描述一下执行过程:
-
str.sayHi() --> 自身查找 --> 没有sayHi方法 -->
-
查找上层原型
str._ _ proto _ _ --> 指向 String.prototype对象 --> 没有sayHi方法 -->
-
查找上层原型
String.prototype._ _ proto _ _ --> 指向Object.prototype对象 --> 找到sayHi方法 --> 执行sayHi方法
-
-
var Person =function(name){ this.name=name; }; Person.prototype.getName = function(){ console.log(this.name) }; var p1 =new Person('jack'); console.log(p1.__proto__===Person.prototype);//true console.log(p1.__proto__.__proto__===Object.prototype);//true console.log(p1.__proto__.__proto__.__proto__);null
-
p1
—-
__proto__
—-
Person.prototype
—-
__proto__
—-
Object.prototype
—-
__proto__
—–null - 由上可知:原型链,就是在当前对象中如果自身没有该属性,则向上一层原型对象中寻找,一直到最外层(null)
-
每个继承父函数的子函数的对象都包含一个内部属性
_ _ proto _ _
,该属性包含一个指针,指向父函数的prototype,若父函数的原型对象的
_ _ proto _ _
属性为再上一层函数的原型,在此过程中就形成了原型链。
-
3.继承
3.1.构造函数继承
-
原理:调用父类构造函数,并改变其中的this (bind、call、apply)
unction Cat(n,c){ // 猫 类 this.name = n; this.color = c; this.trait = function (){ console.log('卖萌~'); } } Cat.prototype.skill = function (){ // 原型上的属性方法 console.log('抓老鼠'); } // 需求:狗要卖萌,狗要多管闲事-抓老鼠 function Dog(n,c,f){ // 狗 类 this.food = f; Cat.call(this,n,c); // 狗冒充猫,访问猫的属性方法 } var dog1 = new Dog('二哈','yellow','shi');// 实例对象 console.log(dog1.name); // 二哈 dog1.trait(); // 卖萌 dog1.skill(); // 报错 dog1.skill is not a function
我们看到这种继承方式有局限性,“父类”原型上的属性方法无法继承,所以二哈没有抓老鼠的技能
3.2.原型链继承
-
原理:将原型对象链接到另一个对象实现继承(改变原型的指向)
function Cat(n,c){ // 猫 类 this.name = n; this.color = c; this.trait = function (){ console.log('卖萌~'); } } Cat.prototype.skill = function (){// 原型上的属性方法 console.log('抓老鼠'); } function Dog(n,c,f){ // 狗 类 this.food = f; } Dog.prototype = new Cat(); // 把狗的原型指向猫的实例对象 var dog1 = new Dog('二哈','yellow','shi'); console.log(dog1.name); // undefined console.log(dog1.food); // shi dog1.trait(); // 卖萌~ dog1.skill(); // 抓老鼠 console.log(dog1.constructor); // Cat
- 实例化对象的时候不能给“父类”传参,导致访问dog1.name没有值
- 有句台词:‘人是人妈生的,妖是妖妈生的 ’ 现在 dog1.constructor 指向 Cat,意味着 二哈 是猫妈生的!很显然这不符合伦理,也不环保…
3.3.混合继承(组合继承)
function Cat(n,c){
this.name = n;
this.color = c;
this.trait = function (){
console.log('卖萌~');
}
}
Cat.prototype.skill = function (){
console.log('抓老鼠');
}
function Dog(n,c,f){
this.food = f;
Cat.call(this,n,c);// 对象冒充继承
}
Dog.prototype = Object.create(Cat.prototype);// 寄生继承
Dog.prototype.constructor=Dog;// 指正构造器
var dog1=new Dog('二哈','yellow','shi');
console.log(dog1.name);// 二哈
console.log(dog1.food);// shi
dog1.trait();// 卖萌~
dog1.skill();// 抓老鼠
console.log(dog1.constructor);// Dog
- 两种方式结合可以实现相对比较完美的“继承”别忘了指正构造器(类型),不能认贼作父!
函数的this指向
1.this的指向
-
this指向函数的调用对象
-
this指事件的调用对象
-
在构造函数中this指向示例对象
-
再prototype原型的方法中,this指向示例对象、
-
找不到函数的调用的this指向window
-
箭头函数没有自己的this,它的this指向上下文中的this(即所处环境的this)
function fn(x, y) { console.log('coming',this); console.log(x + y); } let obj={ name:'nick', hobby:'basketball' } // 调用函数,改变函数中的this fn.call(obj,5,7) //第一个参数改变了this的指向,其他参数对应函数里的参数,立即执行=>call fn.apply(obj,[5,7]) //第一个参数改变了this的指向,第二个参数是个数组,立即执行=>apply let emit = fn.bind(obj,5,7) //第一个参数改变了this的指向,其他参数对应函数里的参数, //但需调用再执行=>bind emit()
call、apply、bind
- call、apply、bind都是Function.prototype的方法,所以每个函数都有call、apply、bind属性。
- call、apply、bind的作用都可改变函数内部的this指向
1.call
-
call()的作用
- 改变了原来函数的this指向
- 绑定函数内部的this指向,this指向obj
- 没有返回值,会执行当前函数。
-
传参方式:call()里的第一个参数一个对象,后边参数是用逗号隔开的列表。
-
fn.call(obj,2,3,4,5)
-
2.apply
-
apply()的作用
- 改变了原来函数的this指向
- 绑定函数内部的this指向,this指向obj
- 没有返回值,会执行当前函数。
-
传参方式:apply()里只有两个参数,第一个参数是一个对象,第二个参数是一个数组
-
fn.apply(obj,[2,3,4,5])
-
3.bind
-
bind(obj)的作用
-
改变了原来函数的this指向
-
绑定函数内部的this指向,this指向obj
-
返回值是调用bind方法的函数体本身,不会执行当前函数,要调用一下f()。
-
var obj={ a:1, b:2 } function fn(){ console.log(this) } var f = fn.bind(obj) f()//{a:1,b:2}
-
-
总结
-
call、apply和bind都可以改变函数的this指向
-
call、apply和bind第一个参数的是this要指向的对象
-
call、apply和bind都可以后续为函数传参,apply是将参数并成一个数组,call和bind是将参数依次列出。
-
call、apply都是直接调用,bind生成的this指向改变函数需要手动调用。
-
JQurey
1.
jQure
y的选择器
jQure
-
$(".box")
通过类名 -
$("div")
通过标签名 -
$("#box")
通过id -
特殊选择器
-
$("li:first")
获取li中的第一个 -
$("li:last")
获取li中的最后一个 -
$("li:eq(3))
获取li中索引是3的那一个 -
$("li:odd")
获取li中索引是奇数的li -
$("li:even")
获取li中索引是偶数的li
-
-
转换:
-
var box = document.querySelector('#box')
; // js对象 -
var $box = $('#box');
// jq对象 -
JQ获取DOM对象,转domj元素,操作样式
-
$box[0].style.color = 'blue'
; // 转成 js 对象 -
$box.get(0).style.color = 'blue'
;// 转成 js 对象
-
-
JS获取的DOM对象,转JQ对象
-
$(box).css('color','red');
// 转成 jq 对象
-
-
2.
jQurey
筛选器
jQurey
-
first()
-
用法:
$(".box").first()
- 含义:.box类名集合下的第一个
-
用法:
-
last()
-
用法:
$(".box").last()
- 含义:.box类名集合下的最后一个
-
用法:
-
eq()
-
用法:
$(".box").eq(3)
- 含义:.box类名集合下的索引值为3的那一个
-
用法:
-
next()
-
用法:
$('span').next()
- 含义:.拿到span标签的下一个兄弟元素
-
用法:
-
nextAll()
-
用法:
$('span').nextAll()
- 含义:.拿到span标签后边的所有元素
-
用法:
-
nextUntil()
-
用法:
$('span').nextUntil(.box)
- 含义:.拿到span标签后边到.box元素的所有元素,不包含.box
-
用法:
-
prev()
-
用法:
$('span').prev()
- 含义:.拿到span标签的上一个兄弟元素
-
用法:
-
prevAll()
-
用法:
$('span').preAll()
- 含义:.拿到span标签前边的所有元素
-
用法:
-
prevUntil()
-
用法:
$('span').prevUntil(.box)
- 含义:.拿到span标签后边到.box元素的所有元素,不包含.box
-
用法:
-
parent()
-
用法:
$('span').parent()
- 含义:.找出span标签的父元素
-
用法:
-
parents()
-
用法:
$('span').parents()
- 含义:.找出span标签的所有父元素,直到html元素为止
-
用法:
-
parentsUntil()
-
用法:
$('span').parentsUntil(选择器)
-
含义:.找出span标签的所有父元素,直到
选择器
元素为止
-
用法:
-
children()
-
用法:
$('span').children()
- 含义:.筛选出元素所有的子级元素
-
用法:
$('span').children(选择器)
-
含义:.筛选出span元素中所有的符合
选择器
de 子级元素
-
用法:
-
sibilings()
-
用法:
$('span').sibilings()
- 含义:.筛选出span标签的所有的兄弟级元素
-
用法:
-
find()
-
用法:
$('span').find(.box)
-
含义:.筛选出span标签中所有子代元素里类名为
.box
的元素- 在一个元素的后代元素中查找对应选择器的元素
- 在一个元素集合的每一个元素中, 查找后代元素
-
用法:
-
index()
-
用法:
$('span').index()
- 含义:.拿到span在其父元素的索引值
-
用法:
3.
jQurey
操作文本内容
jQurey
-
html()
-
语法:
$("div").html()
- 不传参数的时候,就是获取元素内部的超文本内容
- 传递参数的时候,就是设置元素的超文本内容
-
语法:
-
text()
-
语法:
$("div").text()
- 不传参数的时候,就是获取元素内部的文本内容
- 传递参数的时候,就是设置元素的文本内容
-
语法:
-
val()
-
语法:
$("div").val()
-
不传参数的时候,就是获取
input
标签的
value
值 -
传递参数的时候,就是设置就
input
标签的
value
值
-
语法:
-
总结:
-
获
-
html()
:只能获取第一个元素的超文本内容 -
text()
:能获取元素集合内所有元素的文本内容合 -
val()
:只能获取第一个元素的 value 值
-
-
设置:
-
html()
:给元素集合内所有的元素设置超文本内容 -
text()
:给元素集合内所有的元素设置文本内容 -
val()
:给元素集合内所有的元素设置
value
值
-
-
获
4.
jQurey
操作元素类名
jQurey
-
addClass()
添加类名-
语法:
$("span").addclass("box")
- 注释:执行这个方法会给元素集合里面所有的元素添加上固定的类名,如果有就不添加了,没有才会添加
-
语法:
-
removeClass()
移除类名-
语法:
$('div').removeClass('box')
- 注释:移除div集合中含有类名.box的div的雷鸣
-
语法:
-
toggleClass()
切换类名-
语法:
$('div').toggleClass('container')
- 注释:执行这个方法会给所有元素加上这个类名,有的删除,没得加上
-
语法:
-
hasClass()
判断有没有这个类名-
语法:
$('div').hasClass('box')
- 注释:会返回一个布尔值
-
语法:
5.
jQurey
操作元素的样式
jQurey
-
css("样式名称")
- 获取元素集合的第一个元素的样式值,不管是行内样式还是非行内样式都能获取
-
css("样式名称",'样式的值')
- 设置元素的样式值, 元素集合能获取多少个元素就设置多少个元素
- 设置的时候, 所有的单位都可以不写, 默认添加 px 为单位
-
css(对象)
-
css({
width:100,
height:100,
})
-
批量设置 css 样式
-
给元素集合里面的所有元素, 批量设置样式
-
6.
jQurey
操作元素的属性
jQurey
-
attr()
attribute
- attr(要读取的属性名),传递一个参数的时候是读取
- attr(属性名, 属性值): 传递两个参数的时候是设置
removeAttr()
- 专门用来移除属性的
attr 这套方法的注意:
- 所有的属性都会显示在标签上(原生属性和自定义属性)
- 不管你设置的是什么数据类型, 都会给你变成字符串
- removeAttr 删除 attr 设置的属性, 有多少删除多少(针对自定义属性)
-
prop()
property
- prop(要读取的属性名): 传递一个参数的时候是读取
- prop(属性名, 属性值): 传递两个参数的时候是设置
removeProp()
- 专门用来移除属性的
prop 这套方法的注意:
- 非原生属性, 不会显示在标签上, 但是你可以获取使用
- 你存储的是什么数据类型, 获取的时候就是什么数据类型
- removeProp 删除 prop 设置的属性, 有多少删除多少(针对自定义属性)
- removeProp() 不能删除原生属性 id class style 这样的
-
data()
- data(要读取的属性名): 传递一个参数的时候是读取
- data(属性名, 属性值): 传递两个参数的时候是设置
removeData()
- 专门用来删除数据的
data 这套方法的注意:
- 和元素的原生属性没有关系, 可以设置 id, 但是和元素的 id 没关系
- 就是在元素身上给你开辟一个地方, 存储一些数据
- 你设置的是什么数据类型, 拿到的就是什么数据类型
- removeData 删除 data 设置的属性
- data() 方法也能读取写在标签上的 H5 标准自定义属性
-
三个方法存储内容
- attr 设置的自定义属性存储在标签身上
- prop 设置的自定义属性存储在元素对象里面
- data 设置的自定义属性存储在元素对象里面单独开辟的一个对象
7.
jQurey
绑定事件
jQurey
-
on()
-
on('事件类型', 事件处理函数)
-
给元素集合内所有的元素绑定一个事件
-
$('ul').on('click', function handlerA() { console.log('我是事件处理函数 ') })
-
-
on('事件类型', '事件委托', 事件处理函数)
-
把 事件委托 位置的元素的事件 委托给了前面的元素集合
-
$('ul').on('click', 'li', function () { console.log('我被点击了, 事件委托') })
-
-
on('事件类型', 复杂数据类型, 事件处理函数)
-
给每一个元素绑定一个事件, 复杂数据类型是触发事件的时候传递的参数
-
$('li').on('click', { name: 'Jack', age: 18 }, function (e) { console.log('我被点击了, li') console.log(e) })
-
-
on('事件类型', '事件委托', 任意数据类型, 事件处理函数)
-
做一个事件委托的形式, 第三个参数位置的数据
-
是触发事件的时候, 可以传递进去的数据
-
给 li 做一个事件委托, 委托给了 ul 每一个 li 点击的时候都能得到一个传递进去的数据叫做 hello world $('ul').on('click', 'li', 'hello world', function (e) { console.log('我又被点击了') console.log(e) console.log(this) // 就是你点击的那一个 li })
-
-
on(对象)
-
给一个元素绑定多个事件的方式
-
给 ul 同时绑定三个事件 这个时候就不能传递参数了 这个时候就不要贪图事件委托了 $('ul').on({ click: function () { console.log('点击事件') }, mouseover: function () { console.log('移入事件') }, mouseout: function () { console.log('移出事件') } })
-
-
off( event , selector , fnName )
on()的反向操作,移除用on()绑定的事件
-
-
事件绑定及移除
-
bind( )
为每个匹配的元素绑定一个或多个事件处理函数语法:bind( event , fn ) //不能给未来元素添加事件-
$("p").bind("click", function(){ alert( $(this).text() ); }); $('h2').bind({ mouseover: function (){ alert('移上'); }, mouseout: function (){ alert('移出'); } })
-
-
unbind( )
与
bind( )
反向的操作,删除元素的一个或多个事件语法:
unbind(event , fnName )
-
8.事件对象
- 阻止冒泡/传播:e.stopPropagation() return false;
- 阻止默认行为:e.preventDefault(); return false;
-
事件类型:
- e.type触发事件的元素:
- e.target ( 原生DOM节点 )
- 指示按了哪个键或按钮:e.which 1 2 3
- 鼠标的相对坐标:e.clientX/Y e.pageX/Y
- 事件发生时的时间戳:e.timeStamp(毫秒数)
9.
jQurey
的节点操作
jQurey
-
创建节点
-
$()
或者
jQuery()
- () 里面传递一个 html 格式文本的时候就是创建节点
- () 里面传递一个选择器的时候, 就是获取页面中的 DOM 元素
- () 里面传递一个选择器的时候, 就是获取页面中的 DOM 元素
- () 里面传递一个 html 格式文本的时候, 就是创建一个 DOM 元素
-
例子:
$('<div>我是一个创建出来的节点</div>')
-
-
插入节点
-
在页面元素内部插入
-
语法:在后面插入
-
页面元素.append(要插入的元素)
-
要插入的元素.appendTo(页面元素)
-
-
语法:在前面插入
-
页面元素.prepend(要插入的元素)
-
要插入的元素.prependTo(页面元素)
-
-
语法:在后面插入
-
-
删除节点
-
语法:
-
页面元素.empty()
-> 把自己变成空标签 -
页面元素.remove()
-> 把自己移除
-
-
语法:
-
替换节点
-
语法:
-
页面元素.replaceWith(替换元素)
-
替换元素.replaceAll(页面元素)
-
-
语法:
-
克隆节点
-
语法:
元素.clone()
- 第一个参数: 自己的事件是否克隆
- 第二个参数: 子节点的事件是否克隆(当第一个参数为 false 的时候, 第二个参数没有意义)
注意:不管你是否传递参数, 都会把所有后代元素都克隆下来
-
语法:
10.
jQurey
获取元素的尺寸
jQurey
-
三套方法, 四种使用方式:
-
width()
和
height()
- 注释:获取元素的内容区域的尺寸(content)
-
innerWidth()
和
innerHeight()
- 注释:获取的元素的内容区域+padding区域的尺寸
-
outerWidth()
和
outerHeight()
- 注释:获取的元素的内容区域+padding区域+border的尺寸
-
outerWidth(true)
和
outerHeight(true)
- 注释:获取的元素的内容区域+padding区域+border+margin的尺寸
-
11.
jQurey
获取元素的位置
jQurey
-
offset()
-
语法:
- 不传递参数就是读取,读到的元素相对于页面的位置关系,返回值是一个对象 { left: xxx, top: xxx }
- 传递一个对象就是写入 { left: xxx, top: xxx }
-
语法:
-
position()
-
语法:
- 只读的方法,元素相对于定位父级的位置关系,得到的也是一个对象 { left: xxx, top: xxx }
-
语法:
12.
jQurey
获取页面卷去的尺寸
jQurey
-
scrollTop()
/
scrollLeft()
-
语法:
- 不传递参数的时候就是获取卷去的高度/宽度
- 传递一个参数就是设置卷去的高度/宽度
-
语法:
13.
jQurey
的函数
jQurey
-
ready()
事件- 类似于 window.onload 事件
- window.onload -> 会在页面所有资源加载完毕执行
- ready() -> 会在页面 html 结构加载完毕后执行
- 也叫做 jQuery 的入口函数
-
有一个简写的形式
$(function () {})
-
each()
方法-
类似于
forEach()
, 遍历数组的 -
jQuery 的元素集合, 是一个 jQuery 数组, 不是一个数组, 不能使用 forEach()
-
$('div').each(function (index, item) { // index -> 就是索引 // item -> 就是每一项 console.log(index, item) })
-
14.
jQurey
的动画
jQurey
-
标准动画
-
show()
显示-
语法:show(时间, 运动曲线, 运动结束的函数)
-
$('div').show(2000, 'linear', function () { console.log('显示结束') })
-
-
hide()
隐藏-
语法:hide(时间, 运动曲线, 运动结束的函数)
-
$('div').hide(2000, 'linear', function () { console.log('隐藏结束') })
-
-
toggle()
切换(如果是隐藏就显示, 如果是显示就隐藏)-
语法:toggle(时间, 运动曲线, 运动结束的函数)
-
$('div').toggle(2000, 'linear', function () { console.log('切换结束') })
-
-
-
折叠动画
-
slideDown()
-> 下滑显示-
语法: slideDown(时间, 运动曲线, 运动结束的函数)
-
$('div').slideDown(2000, 'linear', function () { console.log('下滑结束') })
-
-
slideUp()
-> 上滑隐藏-
语法: slideUp(时间, 运动曲线, 运动结束的函数)
-
$('div').slideUp(2000, 'linear', () => console.log('上滑结束'))
-
-
slideToggle()
-> 切换滑动显示和隐藏-
语法: slideToggle(时间, 运动曲线, 运动结束的函数)
-
$('div').slideToggle(2000, 'linear', function () { console.log('切换结束') })
-
-
-
渐隐渐显动画
-
fadeIn()
-> 渐渐的显示(贱贱的显示)- 语法: fadeIn(时间, 运动曲线, 运动结束的函数)
-
fadeOut()
-> 渐渐的消失- 语法: fadeOut(时间, 运动曲线, 运动结束的函数)
-
fadeToggle()
-> 渐渐的切换显示和消失’- 语法: fadeToggle(时间, 运动曲线, 运动结束的函数)
-
fadeTo()
-> 去到一个你指定的透明度- 语法: fadeTo(时间, 你指定的透明度, 运动曲线, 运动结束的函数)
-
-
综合动画
-
animate()
-
基本上大部分的 css 样式都可以动画
-
transform 不行, 颜色不行
-
语法: animate({}, 时间, 运动曲线, 运动结束的函数)
-
$('button').click(() => { $('div').animate({ width: 300, height: 300, left: 30, top: 50, borderRadius: '50%', opacity: 0.5 }, 2000, 'linear', () => console.log('运动结束')) })
-
-
-
停止动画
-
stop()
- 当这个函数触发的时候, 就会让运动立刻停下来
- 你运动到哪一个位置了就停止在哪一个位置
-
finish()
- 当这个函数触发的时候, 就会让运动立刻停下来
- 不管你运动到了哪一个位置, 瞬间到达运动完成位置
-
15.$符冲突问题
-
noConflict()方法
-
jQuery
中的
noConflict( )
方法的作用就是让
jQuery
放弃对
符的
所
有
权
当
代
码
中
调
用
该
方
法
后
,
不
可
以
使
用
符的所有权当代码中调用该方法后,不可以使用
符
的
所
有
权
当
代
码
中
调
用
该
方
法
后
,
不
可
以
使
用
来调用
jQuery
方法-
$.noConflict( );
- “$(‘#div’).click(…)`; //无效
-
jQuery(‘#div’).click(....)
; //有效
-
-
jQuery
中允许我们自定义
jQuery
的别名-
var jq=$.noConflict();
-
jq(‘#div’).click(....);
//有效 -
jQuery(‘#div’).click(....);
//有效 -
$(‘#div’).click(....);
//无效 报错
-
-
-
如何继续使用$符
-
$.noConflict( );
-
jQuery(function ($){ $(‘h1’).click( function (){ alert($(this).html( ) );});
-
-
16.
jQuery
扩展 ( 插件开发接口 )
jQuery
-
$.extend()方法
-
jQuery.extend([boolean],target [,object1] [,objectN])
-
[boolean] 表示是否深拷贝,默认false 浅拷贝当提供两个或多个对象参数时,其他对象的属性将合并到目标对象。
-
var obj1 = {a: 1, b: 2, c: {d: 4, e: 5}}; var obj2 = {c: {g: 7}, d: 8}; $.extend(obj1,obj2); //浅拷贝 $.extend(true,obj1,obj2); //深拷贝 for (var key in obj2){ //浅拷贝 obj1[key] = obj2[key]; } var obj3 = JSON.stringify(obj2); //深拷贝 Object.assign(obj1,obj2); //浅拷贝 console.log( obj1.c === obj2.c );
-
17.
jQuery ajax
jQuery ajax
-
$.ajax( options )
通过 HTTP 请求加载远程数据-
url:请求的url地址
type:请求类型(get/post…)
cache:是否读取缓存,默认true
data:要发送给服务器的数据,示例:”name=jack&age=19″string或Object{name:“jack”,age:“19”}
async:默认true,为异步请求
dataType:服务器返回的数据类型特殊的格式JQ会进行预解析和兼容性修复。可选择的值:“xml” , “html” , “script” , “json” , “text”,”jsonp”等
timeout:设置超时(毫秒)
success:请求成功的回调函数
error:请求失败的回调函数
complete:请求完成后的回调函数,无论成功与失败
beforeSend:发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义 HTTP头。在beforeSend中如果返回false可以取消本次ajax请求。XMLHttpRequest对象是惟一的参数。 -
$('#login').click(function (){ $.ajax({ type:'get', url:'test.php', dataType:'json', cache:false, //不使用缓存 success:function (json){ $('h1').html(json.name+json.sex+json.age); }, error:function (){ alert('请求失败'); } }); })
-
-
serialize( )
-
将一个form表单内的所有数据转换为可以发送给服务器的字符串示例
-
$("form").serialize() "name=小明&age=19&msg=abc"
-
-
-
$.get( url [, data] [, callback] [, dataType]);
-
url : 请求的URL
data : 可选,发送至服务器的数据
callback : 可选,请求完成时的回调函数
dataType : 可选,参照$.ajax参数中的dataType
-
$.get(“act.php”,{user:“cainiao”,pass:“123”},function (data){ alert(data.msg); },“json”);
-
-
$.post()
-
$.post 与 $.get 语法相同,唯一的不同就是请求是以post方式进行。
-
$.post(“act.php”,{user:“cainiao”,pass:“123”},function (data){ alert(data.msg); }, ”json”);
-
18.
jsonp:
跨域请求
jsonp:
-
ipt.onkeyup=function (){ $.ajax({ type:'get', url:'http://suggestion.baidu.com/su?wd='+$('#ipt').val(), dataType:'jsonp', jsonp:'cb', // jsonpCallback:'mycallback', success:function (json){ // $('#list').empty(); $('#list').html(''); for (var i = 0; i < json.s.length; i++) { $('#list').append('<li>'+json.s[i]+'</li>'); } } }); }
swiper
1.引入
- 引入css样式
<link rel="stylesheet" href="dist/css/swiper.min.css">
- 引入script代码
<script src="dist/js/swiper.min.js"></script>
2.HTML结构
//如果同一个页面要用几个轮播图,那么可以给.swiper-container这个div加上id选择器来区分
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>
<!-- 如果需要导航按钮 -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- 如果需要滚动条 -->
<div class="swiper-scrollbar"></div>
</div>
//导航等组件可以放在container之外
3.script代码
<script>
var mySwiper = new Swiper ('.swiper-container', {
direction: 'vertical', // 垂直切换选项
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
// 如果需要滚动条
scrollbar: {
el: '.swiper-scrollbar',
},
})
</script>
github
1.github的操作
-
git bash here
邮件要操作的文件夹
-
git config --list
查看配置清单
-
git config --global user.name "你的用git户名"
给git配置用户名
-
git config --global user.email "你的用git邮箱"
给git配置用邮箱
2.github命令
-
cd
进入文件夹
-
cd..
返回上一层目录
-
mkdir
创建项目
-
pwd
显示当前工作目录的全路径
-
touch xx
新建xx文件
-
rm
删除文件
-
ls
查看当前目录所有文件
-
clear
清屏
3.创建本地仓库
-
git init
-
创建本地仓库,会生成.git文件夹
。
-
-
git add .
-
将本地仓库的数据传输到暂存区
-
git status
查询工作区和暂存区数据工作状态
-
On branch master nothing to commit, working tree clean 在你的工作master分支上,工作区和暂存区文件一样 红色提示是工作区有更改,未提交到暂存区 绿色提示是暂存区有更改
-
-
-
git commit -m '提交注释'
-
将暂缓区的内容提交到本地仓库
-
-
git diff ‘工作区的文件名’
-
查看工作区修改的文件的内容
-
-
git log
/
git reflog
-
查看工作日志
-
-
git reset --hard HEAD^
-
回复到上一个版本号
-
-
git reset --hard HEAD^^
-
回复到倒数第二个版本号
-
-
git reset --hard "版本号"
-
回复到指定的版本号
-
4.关联本地仓库和远程仓库
-
git remote add origin '地址'
-
git remote -v
查看是否连接成功
-
git remote rm origin
删除关联的地址
-
git push -u origin master
第一次推送本地仓库到******github
-
git push
以后推送本地仓库到******github
5.创建切换合并删除分支
-
git branch '分支名(不用加双引号)'
创建分支
git branch day1 -
git checkout '分支名'
切换分支
-
git checkout -b '分支名
’
创建切换分支
-
git push origin '分支名'
推送到哪个分支上
-
git merge '分支名'
合并某分支到当前分支
-
git branch -d '分支名'
删除某分支
-
git branch –list 查看自己创建的分支
分支的合并
1.创建分支 git branch day1
2.在当前的分支中修改内容后,
在git add .
git commit -m “first”
git push origin day1 (创建好分支)
切换到主分支(master)
git checkout master
在master进行分支的合并
git merge day1
然后在
6.更新/拉去
- git fetch 更新远程代码到本地,不会自动merge
- git pull 更新远程代码到本地,会自动合并merge
- git pull origin 分支名 更新远程分支代码到本地
7.克隆项目
-
git clone '地址'
克隆别人的项目到自己的电脑上
8.配置SSH
-
cd ~/.ssh
检查是否电脑又ssh -
ssh-keygen -t rsa -C 'github邮箱地址'
- 三次回车
- Enter file in which to save the key (/c/Users/lsh/.ssh/id_rsa) 去找id_rsa的文件
- 根据提示到C盘找(id_rsa.pub)pub后缀文件中的所有内容,去vscode复制内容
- 打开github 点击头像找setting (找到ssh and GPG keys)
- 找ssh ,复制进去。
9.设置git忽略文件
- 在工作区创建文件:.gitignore
- 在vscode打开,设置忽略文件列表 node_modules
nodeJs
1.node操作
-
win+r+cmd
打开命令行终端
-
node -v
或者
node --version
检查版本号
-
node '文件名'
文件名不要写成
node.js
-
cd..
返回上级目录
-
dir
查看目录
**** -
tree
查看偶有文件夹和子文件夹里的内容
-
cd 文件夹名称
进入那个文件夹
-
盘符:
切换盘符
-
创建文件夹
-
mkdir 你要创建的文件夹名称
-
md 你要创建的文件夹名称
-
-
删除文件夹
-
rd 你要删除的文件夹的名称
(
只能删除空文件夹
) -
rd /s /q 你要删除的文件夹名称
(
强制删除文件夹
)
-
-
xcopy 你要复制的文件夹名 复制以后的文件夹名
复制文件夹
-
echo 你要写入的内容>你指定的文件
向文件里写入一些内容,完全覆盖式的写入
-
echo 你要写入的内容>>你指定的文件
向文件里写入一些内容,追加
-
type 你要查看的文件名
查看文本里的内容化
-
ren 你要修改的文件 你要改成什么名字
给文本重命名
-
del 你要删除的文件名
删除文件
-
copy 你要复制的文件名 复制以后的文件名
复制文件
-
remove 你要移动的文件名 你要移动到哪一个目录
移动文件名
-
cls
清屏
-
ipconfig
查看电脑ip
-
ping www.baidu.com -t
测试网速
-
systeminfo
查看电脑信息
-
nodejs 的特点
- 是一个基于V8引擎的JavaScript运行环境
- 单线程
- 非阻塞I/O 也就是异步,通过回调函数,
- 事件驱动
2.node模块化
2.1.内置模块
-
(核心模块包括 os(操作系统)、fs(文件系统)、http(网络系统)),安装node这个环境的时候就自带有的模块(js文件),不需要下载,导入进来使用就好。
-
fs(文件系统)
-
专门来读取写入文件内容的
* 导入模块用`require()`方法 1. 导入fs模块 `const fs = require('fs')` * fs 模块的几个方法 1. `fs.readFile()` 专门用来异步读取文件的方式 语法:`fs.readFile('你要读取的文件路径',读取文件格式(选填),读取文件成功的回调函数)` `fs.readFile('./test.txt','utf-8',function(err,data){ //函数是读取文件完成后执行的回调函数 //接受两个形参 err=>读取失败的时候的失败信息 data=>读取成功的时候的读取的内容 ->读取的内容默认是buffer格式的字符串,我们看不懂,计算机看的懂 ->如果想读取一个我们看的懂得文件,那么要在第二个参数设置'utf-8' if(err){ return console.log(err) } console.log(data) })` 2.`fs.readFileSync()` 专门用来同步读取文件的方式 语法:`fs.readFile('你要读取的文件路径',读取文件格式(选填))` `let data = fs.readFile('你要读取的文件路径','utf-8')` 1. `fs.writeFile()` 专门用来异步写入文件的方式,覆盖式的写入 语法:`fs.writeFile('你要写入的文件路径',你要写入的内容,读取文件成功的回调函数)` `fs.writeFile('./test.txt',你要写入的内容,function(){ console.log('写入成功了') })` 2. `fs.writeFileSync()` 专门用来同步步写入文件的方式 语法:`fs.writeFile('你要写入的文件路径',你要写入的内容)` `fs.writeFileSync('./test.txt',你要写入的内容 `console.log('写入成功了') 1. `fs.appendFile()` 专门用来异步写入文件的方式,追加式的写入 语法:`fs.appendFile('你要写入的文件路径',你要写入的内容,读取文件成功的回调函数)` `fs.appendFile('./test.txt',你要写入的内容,function(){ console.log('写入成功了') })`
-
2.2.http内置模块
-
这个模块是专门用来创建http服务的,只能支持http协议
-
就是可以把电脑上的命令行窗口当成一个服务器来使用
* 导入http模块 const http = require('http') 导入fs模块 const fs = require('fs') * 创建http服务 const server = http.createServer(function(req,res){ +这个函数是前端的每一个请求都会执行这个函数 +只有我在监听这个端口号有请求过来的时候,就会执行 +这个参数接收两个形参 -req 表示每次请求的信息 req.url 表示本次请求的地址 -res 表示每次请求的响应 res.end() 表示本次给回的响应 +通过不同的url做不同的事情 if(req.url==='./index.html'){ fs.readFile('./index.html','utf-8',function(err,data){ if(err) return console.log(err) //响应之前设置响应头 res.setHeader('Content-Type','text/html;charset=utf-8') res.end(data) }) } console.log('我执行了,表示有请求进来了') }) * 监听一个端口号(端口号是0-65535,0-1023不推荐使用) server.listen(8080,function(){ console.log('监听8080端口成功') }) * 代码写完以后,当你在终端运行这个文件的时候 +你的那个终端就是一个服务器了 +你就可以打开浏览器去访问localhost:8080
2.3.自定义模块
- 自定义模块就是在一个js文件里写入一些方法,然后要把js文件里的方法导出,外部才能接收。
- 每个js文件里自带 module对象,每个module对象里自带exports对象,module.exports就是这个文件向外导出的内容,我们向外暴露该对象内容就可以了
funtion fn1(){
console.log('我是a模块里的fn1方法')
}
function fn2(){
console.log('我是a模块里的fn2方法')
}
module.exports.fn1 =fn1;
module.exports.fn2 =fn2;
-
模块导入的方法
-
·导入模块用
require()
方法 - 在b文件里导入我们自定义的模块 文件名
-
·导入模块用
-
为什么浏览器里面不需要导出直接导入就行
- 之所以你浏览器不用导出,是我因为我们的浏览器里有一个顶级对象window
- 你写在全局的变量都是挂在window上的
- 在一个html文件里,多个js文件公用一个window对象
-
在node环境下
-
我们没有真正意义上的全局对象
-
所以我们需要在一个文件导入,一个文件导出的时候才能使用
-
我们每个js都是独立模块,都会独立模块作用限制着
-
在你写a.js文件里的内容,再写b.js文件里是使用不了的
-
第三方模块
3.npm
3.1.什么是npm
- 是node的生态系统的一部分
- 包管理器:专门管理js相关的所有插件/类库/框架
-
检查版本号
npm --version
或者
node -v
3.2.npm的使用
-
npm install 包名
(简写:
npm i 包名
)- 下载js相关的所有插件/类库/框架
- 需要在哪个文件夹里使用,就在哪个文件夹下开启下载命令
- 执行完毕后,就会自动下载,并且在当前文件夹下会生成node_modules的文件夹
- 这个文件夹里就是你下载的第三方包
- 下载下来的内容一般去node_modules文件夹里的dist文件夹里找
-
npm install 包名@指定版本号
(简写
npm i 包名@指定版本号
)- 下载指定版本的包,npm默认下载最新的
- 同名的包在 node_modules里面只能保留一个版本
-
npm init
(j简写
npm init -y
,所有项会走默认值,前提文件夹必须是英文名字)- 初始化项目
- 就是给你生成一个package.json 文件,用来描述你当前的项目
- 并且用dependencies记录下你使用npm下载了那些依赖
-
npm uninstall 包名
(简写:
npm unl 包名
)-
删除包
- 直接手动删除,不会修改package.json文件
- 使用指令删除,会修改package.json文件
-
删除包
-
npm install
(
npm i
)- 会把当前文件夹下的package.json里的第三方插件都下载下来
- 我们在传输项目的时候,不需要传递node_modules这个文件夹
-
只需要把package.json保留,到别人电脑上执行
npm install
-
npm update
- 更新全部依赖包
-
版本号小知识
- x.y.z
- x:当你做了不兼容的 API 修改。为 0 时一般表示处于开发阶段。
- y:当你做了向下兼容的功能性新增。
- z:当你做了向下兼容的问题修正。
-
package.json中^和~有啥区别?
- ^ 锁定主版本,更新到最新的次版本+修订版
- ~锁定主版本和次版本,更新到修订版
-
npm update 包名
- 更新指定依赖包
-
npm config set registry http://registry.npm.taobao.org/
- 不通过下载nrm,手动修改npm的下载地址
4.nrm
4.1.什么是nrm
- nrm是国内的服务器,是国外npm的镜像源地址管理工具
-
npm install --global nrm
(简写:
npm i -g nrm
)- 使用npm下载一个全局的第三方依赖nrm
- 安装完毕以后,在电脑上的任何一个地方就可以使用了
-
检测nrm版本号
nrm --version
(简写
nrm -v
)
4.2.nrm使用
-
nrm test
- 检测所有可用的镜像源地址的网络延迟
- 需要比较长的时间,因为要检测每一个镜像源地址
- 需要等到最慢的哪个网络延迟测试出来以后才一起返回
-
镜像源地址名称 —- 延迟
- npm —- 3706ms 原始npm地址
- yarn —- 710ms facebook家的地址
- cnpm —- 220ms 自己国家的镜像地址
- taobao —- 445ms taobao家的镜像地址
- *代表你当前正在使用的
-
nrm use 镜像源地址名称
- 切换你想要的镜像源地址 找延迟小一点的
5.gulp
5.1.什么是gulp
-
前端自动化打包工具
-
运行需要依赖node环境
- 自动化打包,不需要手动做事,但是需要你手动编辑好一个步骤
- 打包:就是把零散的东西给你结合在一起,对代码进行压缩/混淆/合并
- 工具:就是帮我们完成这个事情的东西
-
5.2.安装gulp
-
npm install --global gulp
(简写:
npm i -g gulp
)- 安装gulp指令
-
npm uninstall --global gulp
(简写:
npm un -g gulp
)- 卸载gulp指令
-
npm cache clear -f
- 清除缓存
-
-
gulp配置打包
-
需要手动写一个配置文件,告诉gulp按照我们的这个配置文件来打包
-
每一个项目一个配置文件,每个项目打包的时候使用的都是当前的项目文件
-
gulp使用之前
-
-
先准备一个项目文件夹——————–我的整个项目文件夹
-src/ ————————-我的所有原始代码
+pages/ ———————-放我所有的html文件
+css/ ———————–放我所有的css文件
+js/ ———————–放我所有的js文件
+images/ ———————–放我所有的图片
+lib/ ————————-放我所有的第三方 文件 (比如jquery swiper)
-package.json ————————-用来记录我项目信息的描述的文件
-
使用
npm init
初始化一下项目 +因为我们的项目一定会用到很多第三方工具
+我就用npm下载第三方工具
+最好就是使用
npm init
给我生成一个package.json文件来记录一下我用了哪些包 +顺便也记录一下自己的项目
3.自己手在项目的根目录创建一个叫
gulpfile.js
的文件 +名字必须是
gulpfile.js
+这个文件里就用来书写我们项目的打包规则(也就是这个项目打包的配置文件 )
+使用gulp的时候会默认读取
gulpfile.js
的打包配置文件 -
-
-
gulpfile.js
的打包配置文件规则
- 借助一些gulp的API方法来帮助我们打包,所以先在项目文件夹里安装一个gulp,作为开发依赖
-
项目里安装的gulp和node 全局安装的gulp区别
-
项目里面安装的gulp(
npm install gulp
简写
npm i gulp
)- 一个第三方依赖包
- 也是一个node的第三方模块
- 也是也别人写好的一堆方法,放在了里面
- 用来给我提供一些API使用的
-
全局安装的gulp(
npm install --golbal gulp
简写
npm i -g gulp
)- 是为我们的电脑增加一个可以使用gulp的能力
-
也就是可以再命令行
gulp xx
的指令,一台电脑安装一次,可以以后一直使用
-
项目里面安装的gulp(
-
gulpfile.js
文件
//1.导入gulp这个第三方模块的时候,会优先去内置模块寻找,如果内置模块里没有,那么就会自动去node-modules的文件里面查找,导入这个gulp以后,就可以使用gulp.xxx()的各种方法了 const gulp =require('gulp') //2.导入gulp-cssmin这个第三方模块 const cssmin = require('gulp-cssmin') //3.先写一个打包css的方法 const cssHandler=()=>{ //找到src目录下对的css目录下的所有后缀为.css的文件 return gulp.src('./src/css/*.css') //压缩css代码 .pipe(cssmin()) //压缩完毕的css代码放在dist文件夹里 .pipe(gulp.dest('./dist/css')) } //4.最后导出我准备好的这个方法 module.exports.css=cssHandler
-
gulp里面的一些方法
-
src()
- 用来找到你要打包的文件的
- src(‘你要打包的文件的地址’)
- 返回值是一个二进制流,就可以继续去调用别的方法
-
pipe()
- 用来帮你做事情的
- pipe(‘你要做的事情’)
- 返回值:又是一个二进制流,又可以接着调用别的方法
-
dest()
- 用来写入文件的
- dest(‘你要放的文件夹’)
- 你要把你已经压缩好的代码放在哪一个文件夹里
- 如果没有指定文件夹,会自动创建一个文件夹 放进去
-
src()
-
parallel()
- 用来并行多个任务的
- gulp.parallel(你定义的任务1,你定义的任务2,…)
- 他会把几个任务都给你执行了
- 只要这个返回值一执行,就能把你准备好的几个任务同时开始执行
-
series()
- 用来逐个执行多个任务的
- gulp.series(你定义的任务1,你定义的任务2,…)
- 只要这个返回值一执行,就能把你准备好的几个任务逐个开始执行
- watch()
- 监控src文件夹下的文件,只要已修改就执行对应的任务
- gulp.watchr(你要监控的文件目录,你要执行的任务)
-
执行各种压缩代码的方法,都是第三方依赖包
-
一个小问题
- 当我在项目文件夹里安装gulp以后,package.json文件就会记录我下载了gulp包
- 当我在项目文件夹里安装jQuery以后,也会在package.json文件记录我下载了jQuery包
- 但是我下载gulp仅仅是为了打包项目使用,打包完成后就不用了了;jQuery是我在项目里一直使用的第三方,
- 既然有区别,那就记录的时候分开记录,现在都是记录在dependencies里面
- 我们安装一些上线不需要的包的时候,就使用另外一套指令
-
npm install --save-dev 包名
的指令(简写:
npm i -D 包名
)-
和
npm install 包名
的下载没有任何区别
-
和
- 唯一的区别就是在package.json里面的记录位置不一样了,现在记录在devdependencies里面
-
-
gulp-cssmin
专门用来压缩css文件的,你需要下载导入-
下载指令
npm install --save-dev gulp-cssmin
(简写:
npm i -D gulp-cssmin
) -
导入第三方模块:
const cssmin = require('gulp-cssmin')
-
导出这个方法:
module.exports.css=cssHandler
- cmd命令行 执行 gulp css,就会执行压缩
-
gulp-autoprefixer
第三方模块是专门用来加前缀,解决浏览器兼容问题-
下载指令
npm install --save-dev gulp-autoprefixer
(简写:
npm i -D gulp-autoprefixer
) -
导入第三方模块:
const autoprefixer = require('gulp-autoprefixer')
-
//1.导入gulp这个第三方模块的时候,会优先去内置模块寻找,如果内置模块里没有,那么就会自动去node-modules的文件里面查找,导入这个gulp以后,就可以使用gulp.xxx()的各种方法了 const gulp =require('gulp') //2.导入gulp-cssmin这个第三方模块 const cssmin = require('gulp-cssmin') //3.导入gulp-autoprefixer`这个第三方模块 const autoprefixer = require('gulp-autoprefixer') //4.先写一个打包css的方法 const cssHandler=()=>{ //找到src目录下对的css目录下的所有后缀为.css的文件 return gulp.src('./src/css/*.css') //给css代码加前缀 .pipe(autoprefixer({ browsers:['last 2 versions'] })) //压缩css代码 .pipe(cssmin()) //压缩完毕的css代码放在dist文件夹里 .pipe(gulp.dest('./dist/css')) } //5.最后导出我准备好的这个方法 module.exports.css=cssHandler
-
-
gulp-uglify
第三方模块是专门用来压缩js的-
下载指令
npm install --save-dev gulp-uglify
(简写:
npm i -D gulp-uglify
) -
导入第三方模块:
const uglify = require('gulp-uglify')
-
导出这个方法:
module.exports.js=jsHandler
-
这个安装包不认识es6的语法,所以要用
gulp-bable
先把es6语法转换成es5语法
-
下载指令
-
gulp-bable
这个第三方模块是专门用来把es6语法转换成es5的语法-
这个第三方包还依赖了另外两个第三方包
@babel/core
和@
babel/preset-env
-
下载的时候需要下载三个包,导入的时候只要导入一个gulp-babel就可以了
-
下载指令
npm install --save-dev gulp-bable @babel/core babel/preset-env
-
导入第三方模块:
const bable = require('gulp-bable')
-
//1.导入gulp这个第三方模块的时候,会优先去内置模块寻找,如果内置模块里没有,那么就会自动去node-modules的文件里面查找,导入这个gulp以后,就可以使用gulp.xxx()的各种方法了 const gulp =require('gulp') //3.导入gulp-uglify这个第三方模块 const uglify = require('gulp-uglify') //4.先写一个打包js的方法 const jsHandler=()=>{ //找到src目录下对的js目录下的所有后缀为.js的文件 return gulp.src('./src/js/*.js') //es6转es5 .pipe(babel({ prests:['@bable/env'] })) .pipe(uglify()) //压缩完毕的js代码放在dist文件夹里 .pipe(gulp.dest('./dist/js')) } //5.最后导出我准备好的这个方法 module.exports.js=jsHandler
-
cmd命令行 执行 gulp js,就会执行压缩
-
-
gulp-htmlmin
专门用来压缩html文件的,你需要下载导入-
下载指令
npm install --save-dev gulp-htmlmin
(简写:
npm i -D gulp-htmlmin
) -
导入第三方模块:
const htmlmin = require('gulp-htmlmin')
-
导出这个方法:
module.exports.html=htmlHandler
-
cmd命令行 执行 gulp html,就会执行压缩
-
//1.导入gulp这个第三方模块的时候,会优先去内置模块寻找,如果内置模块里没有,那么就会自动去node-modules的文件里面查找,导入这个gulp以后,就可以使用gulp.xxx()的各种方法了 const gulp =require('gulp') //3.导入gulp-uglify这个第三方模块 const htmlmin = require('gulp-htmlmin') //4.先写一个打包js的方法 const htmlHandler=()=>{ //找到src目录下对的pages目录下的所有后缀为.html的文件 return gulp.src('./src/html/*.html') .pipe(htmlmin({ removeAttributeQuotes:ture,//移除属性上的双引号 removeComments:ture,//移除注释 collapseBooleanAttributes:ture,//把值为布尔的属性简写 collapseWhitespace:ture,//移除所有空格 minifyCSS:true,//style里的css样式给去空格 minifyJS:true,//script里的JS样式给去空格 })) //压缩完毕的js代码放在dist文件夹里 .pipe(gulp.dest('./dist/js')) } //5.最后导出我准备好的这个方法 module.exports.html=htmlHandler
-
-
书写一个移动img文件的方法
-
图片我们尽量不压缩,设计师给图片的时候是已经压缩好的
-
我们再压缩的话,图片就会在失帧的基础上压缩
-
const imgHandler=()=>{ //找到src目录下对的images目录下的所有后缀为**的文件 return gulp.src('./src/images/**') .pipe(gulp.dest('./dist/images')) } //5.最后导出我准备好的这个方法 module.exports.img=imgHandler
-
-
书写一个移动lib文件夹的方法
-
第三方插件/框架放在lib文件夹下,不需要压缩 只需要移动就好了
-
const libHandler=()=>{ //找到src目录下对的lib目录下的所有后缀为**的文件 return gulp.src('./src/lib/**') .pipe(gulp.dest('./dist/lib')) } //5.最后导出我准备好的这个方法 module.exports.lib=libHandler
-
-
导出一个默认任务
- 当你在执行gulp default的时候,可以不写default
- 你在执行gulp这个指令,就是在执行default
//第一种:导出默认任务,这个parallel是同时执行 module.exports.default = gulp.parallel(cssHandler,jsHandler,htmlHandler,imgHandler,libHandler ) //第二种:导出默认任务,这个series是逐个执行,在这里是先执行删除delHandler,再同时执行parallel() module.exports.default = gulp.series( delHandler, gulp.parallel(cssHandler,jsHandler,htmlHandler,imgHandler,libHandler ), serverHandler, watchHandler )
-
再书写一个任务自动删除dist文件夹里的东西
-
下载指令
npm install --save-dev del
(简写:
npm i -D del
) -
const delHandler=()=>{ //这个函数的目的是为了删除dist目录里的东西 return del(['./dist']) } //5.最后导出我准备好的这个方法 module.exports.del=delHandler
-
-
在书写一个配置服务器的任务
-
下载指令
npm install --save-dev gulp-webserver
(简写:
npm i -D gulp-webserver
) -
这个是专门用来配置node服务器的
-
导入第三方模块:
const webserver = require('gulp-webserver')
-
配置代理—webserver可以配置代理
- 直接在webserver的时候 添加一个配置项
-
const webserver = require('gulp-webserver') const serverHandler=()=>{ //要把页面在服务器上打开 //打开的是dist目录里面我已经压缩好的页面 //找到我要打开的页面的文件夹,把这个文件夹当做网站根目录 return gulp.src('./dist') .pipe(webserver({ //需要一些配置项 host:'localhost',//域名 port:8080,//端口号 open:'./pages/index.html',//默认打开的页面 livereload:true,//-热重启-当dist里面的东西改变就自动刷新浏览器 //所有的代理配置都是在proxies里面 proxies:[ { source:'/gx'//源 代理标识符 target:'http//127.0.0.1/test.php'//目标地址 } ] })) } //5.最后导出我准备好的这个方法 module.exports.server=serveHandler
-
自定义域名
- 如果你想要自定义域名,前提:建议别使用已经存在的域名
-
修改一下你电脑里的hosts文件
- window-我的电脑–C–windows –system32–drivers –etc–hosts
- 在最后添加 127.0.0.1 你自己定义的域名
-
-
书写一个自动监控文件的任务
const watchHandler=()=>{ //这个函数的目的是为了监控src里的东西 gulp.watch('./src/css/*.css',cssHandler) gulp.watch('./src/js/*.js',jsHandler) gulp.watch('./src/pages/*.html',htmlsHandler) gulp.watch('./src/images/**',imgHandler) gulp.watch('./src/lib/**',libHandler) } //5.最后导出我准备好的这个方法 module.exports.watch=watchHandler
-
下载指令
-
-
nodejs端口被占用的原因及处理问题
-
首先打开cmd命令窗口,输入
netstat -ano|findstr 8080
-
此时可以获取8080端口对应的tcp信息,如下,TCP号是15528
-
在cmd 输入 taskkill /f /t /im 15528 号,来关掉被占用的端口;此时可正常使用访问 8080 端口
taskkill /f /t /im 15528
-
6.再次学习node js
6.1.实时监听node环境下http服务的工具
下载指令 : $ npm install nodemon -g(简写 npm i nodemon -g)
- nodemon 只在运行服务的代码时去使用。
6.2.http模块处理请求
- 获取get请求的参数
- get请求的参数是在地址栏上
const http = require("http")
const server = http.creatServer((req,res)=>{
let str = req.url.substring(2,req.url.length)
let arr = str.split("&")
let query = {}
arr.forEach(item=>{
let tmp = item.split("=")
query[tmp[0]]=tmp[1]
})
console.log(query)
res.setHeader('Content-type':'text/html';'charset=utf-8')
res.write(`hello,${query.name}你好,你的年龄是${query.age}`)
res.end()
})
2.获取post的参数
-
post请求的参数是不在地址栏上,不能用req.url来获得
//监听req的data事件(请求传输事件) -data这个事件的回调函数是当请求发送时候触发,并且可能会触发多次,原因是当请求体很大的时候 -chuank 是每次触发这个事情时传递的一部分请求内容 -如何才能把完整的请求体内容全部的到? 拼接chunk let raw ="" req.on('data',(chunk)=>{ raw+=chunk res.write('hello') res.end() }) req.on('end'()=>{ console.log(raw) let arr = raw.split("&") let result = {} arr.forEach(item=>{ let tmp = item.split("=") result[tmp[0]]=tmp[1] }) console.log(result) res.write(`hello,${query.name}你好,你的年龄是${query.age}`) res.end() }) //监听req的end事件() -这个end事件时当整个请求体传输完成时候触发的
6.3.模块化
-
不使用模块化的坏处
- 变量污染
- 代码复用性不高
- 代码可维护性不高
- 以来关系管理不方便
-
什么是模块化?
- 一个模块就是一个实现特定功能的文件,有了模块我们就可以更方便的使用别人的代码,要用什么功能就加载什么模块。
-
模块化带来的好处
- 避免变量污染
- 提供代码的复用率
- 提高代码的可维护性
- 依赖关系清晰
-
规范与实现
- NodeJs – CommonJs规范
- RequireJS – AMD规范
- SeaJS – CMD规范
-
CommonJs规范
-
每个文件就一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其它文件不可见。
-
CommonJS规范规定,每个模块内部,
module
变量代表当前模块。这个变量是一个对象,它的
exports
属性(即
module.exports
)是对外的接口。加载某个模块,其实就是加载该模块的
module.exports
属性。 -
require
方法用于加载模块。- CommonJS模块的特点如下:所有代码都运行在模块作用域,不会污染全局作用域。
- 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
- 模块加载的顺序,按照其在代码中出现的顺序。
-
-
module对象
每个模块内部,都有一个
module
对象,代表当前模块。它有以下属性:- module.id 模块的识别符,通常是带有绝对路径的模块文件名。
- module.filename 模块的文件名,带有绝对路径。
- module.loaded 返回一个布尔值,表示模块是否已经完成加载。
- module.parent 返回一个对象,表示调用该模块的模块。
- module.children 返回一个数组,表示该模块要用到的其他模块。
- module.exports 表示模块对外输出的值。
-
module.exports
-
module.exports
属性表示当前模块对外输出的接口,其他文件加载该模块,实际上就是读取
module.exports
-
-
exports
-
每个模块还提供有一个
exports
变量,指向
module.exports
。这等于在每个模块头部,有一行隐藏的如下代码:var exports = module.exports;
-
造成的结果是,在对外暴露模块接口时,可以直接向
exports
添加属性和方法。var name = '张三'; exports.name = name; exports.sayHi = () => { console.log(`Hello, My Name is ${name}`); }
-
注意,不能直接将exports变量指向一个值,因为这样等于切断了
exports
与
module.exports
的联系。// a.js 切断了与module.exports的联系 exports = function(x) {console.log(x)}; // b.js hello方法没有被暴露,因为module.exports重新赋值了 exports.hello = function() { return 'hello'; }; module.exports = 'Hello world';
-
如果你觉得,
exports
与
module.exports
之间的区别很难分清,一个简单的处理方法,就是放弃使用
exports
,只使用
module.exports
。
-
6.4require 命令
- 如果指定的模块文件没有发现,Node会尝试为文件名添加**.js、.json、.node**后,再去搜索。.js件会以文本格式的JavaScript脚本文件解析,.json文件会以JSON格式的文本文件解析,.node文件会以编译后的二进制文件解析。
-
require
发现参数字符串指向一个目录以后,会自动查看该目录的
package.json
文件,然后加载
main
字段指定的入口文件。如果
package.json
文件没有
main
字段,或者根本就没有
package.json
文件,则会加载
该目录下的index.js 文件 或者 index.json 文件 或者 index.node 文件
。
6.5一些内置模块
-
url模块(快过时了)
-
url.parse(urlString,[,parseQueryString])
- 主要是对url地址做解析
- 参数 加ture 的时候可以的到参数的对象
-
url.format()
- 把解析后的url对象解析成url字符串
-
-
new URL
- 实例化一个URL对象,返回的是一个新标准的url对象
-
new URL(url)
- 主要是对url地址做解析
-
new URL(url).searchParams.get('age'))
- 获取url的参数的age的值
-
new URL(url).toString())
- 把解析后的url对象解析成url字符串
-
querystring 查询字符串模块
-
对于一个查询字符串,解析成查询对象
-
querystring.parse(str,[,sep[,eq]])
- sep规定了键值对之间的分隔符是什么默认是&
- eq规定了键值之间的分隔符是什么,默认是=
const querystring = require('querystring') const str = 'key1=value1&key2=value2' querystring.parse(str)
-
querystring.stringify(str,[,sep[,eq]])
- sep规定了键值对之间的分隔符是什么默认是&
- eq规定了键值之间的分隔符是什么,默认是=
const querystring = require('querystring') const obj = {key1:'value1',key2:'value2'} const str = querystring.stringify(obj,"@","-") console.log(str)
-
-
path模块
-
专门用来处理路径有关的方法,
-
path.resolve('./day01-homework','./utils/index.js')
- 结合成一个绝对路径返回
const path = require('path') const filePath=path.resolve('./day01-homework','./utils/index.js') console.log(filePath)
-
path.join('./day01-homework','./utils/index.js')
-
仅仅是把路径拼接起来
const path = require('path') const filePath=path.join('./day01-homework','./utils/index.js') console.log(filePath)
-
-
path.join()
与
path.resolve()
有什么区别?-
返回值不同,
path.resolve
总是返回一个绝对路径,而
path.join
只是简单的将路径拼接。 -
对于以
/
开始的路径片段,
path.join
只是简单的将该路径片段进行拼接,而
path.resolve
将以
/
开始的路径片段作为根目录,在此之前的路径将会被丢弃
-
返回值不同,
-
-
__dirname
和
__filename
-
__dirname:
当前模块的目录名的绝对路径 -
__filename:
当前模块的文件名
-
7.node–小爬虫
-
网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
-
基于 https 模块实现爬取拉勾网职位分类信息
-
cheerio
第三方模块-
安装模块,简单理解为是使用在服务器端的 jquery。保留了 jquery 选择器的相关功能,去掉了 DOM 操作功能。
$ npm install cheerio
-
引入
const cheerio = require('cheerio')
-
装载
const $ = cheerio.load('<h2 class="title">Hello world</h2>')
-
使用相应的API
console.log($("h2")) $("h2.")addClass("hello") console.log($.html)
-
-
小爬虫代码
var https = require('https');
var cheerio = require('cheerio');
var url = 'https://www.lagou.com/';
https.get(url, function(res) {
var html = '';
res.on('data', function(chunk) {
html += chunk;
});
res.on('end', function() {
findMenu(html);
})
})
function findMenu(htmlStr) {
var $ = cheerio.load(htmlStr);
var $menuMain = $('.menu_main');
var result = [];
$menuMain.each(function(i, item) {
var obj = {};
var h2Text = $(item).find('h2').text();
h2Text = h2Text.trim();
obj.name = h2Text;
obj.subName = [];
var $as = $(item).find('a');
$as.each(function(i, item) {
var aText = $(item).text().trim();
obj.subName.push(aText);
})
result.push(obj);
})
console.log(result);
}
8.express框架
-
前言
- 基于 Node.js 平台,快速、开放、极简的 Web 开发框架 。
-
框架的作用
- 框架可以帮助省略掉一些基本的相同底层代码的反复书写,只需调用框架的方法就可以实现你想要的功能。
-
node 相关框架
- express
- koa
- egg
- thinkjs
- adonisjs
- nestjs
- …
-
安装指令,express是在项目文件夹下安装
$ npm install express
-
路由
-
路由
是指确定应用程序如何响应客户端(浏览器)对特定端点的请求,该特定端点是URL(或路径)和特定的HTTP请求方式(GET、POST等)。 - 每个路由可以具有一个或多个处理程序函数,这些函数在路由匹配时执行。
-
sass
1.世界上最成熟、最稳定、最强大的专业级CSS扩展语言!
-
sass
是一个
css
的预编译工具 -
也就是能够
更优雅
的书写
css
- 可以定义变量
- 可以定义函数
- 可以有if语句,可以有for循环语句
-
sass
写出来的东西
浏览器不认识
,cass可以写 css代码。 -
依旧是要转换成
css
在浏览器中运行 - 这个时候就需要一个工具来帮我们做
2.和css区别
- css文件后缀是.css
- sass文件后缀是.sass或者.scss
3.sass和scss文件区别
-
在.scss文件里面和写css语法基本一致
-
h1 { width: 100px; height: 200px; }
-
在.sass文件里面没有大括号和分号,全部依靠缩进
-
h1 width: 100px height: 200px
-
这两个文件被编译成css文件是一样的
4.
sass
安装卸载
sass
-
# 安装全局 sass 环境 $ npm i -g sass #卸载 $ npm un -g sass
5.sass 编译
-
sass单文件编译
- 你先写好.scss或者.sass后缀的文件
-
输入指令
sass 要编译的文件名 编译后的文件名
- 每次需要改sass都要重新编译一下
-
sass单文件实时编译
- 你先写好.scss或者.sass后缀的文件
-
输入指令
sass --watch 要编译的文件:编译后的文件名
- 如果sass有修改,sass实时编译
6.sass常用语法
6.1.sass变量
$width = 400px;
$height = 200px;
h1{
width:$width;
height:$height
background-color:#ccc;
}
6.2.sass注释
- /* */sass和css都认识的注释
- // 只有sass认识的注释,不会被编译到css文件中。
6.3.嵌套语法
- 在Sass中,你可以像俄罗斯套娃那样在规则块中嵌套规则块。Sass允许将一套 CSS 样式嵌套进另一套样式中,内层的样式将它外层的选择器作为父选择器。
#box{
width:100px;
height:100px;
h1{
text-align:center;
}
span{
font-size:16px;
a{
color:blue
}
}
}
//编译后
#box {
width: 100px;
height: 100px;
}
#box h1 {
text-align: center;
}
#box span {
font-size: 16px;
}
#box span a {
color: blue;
}
6.4.父选择器标识符&
- 指向父选择器,
6.5.@import
-
在css里
- 在CSS里面 link是页面结构和样式同时加载,@import会等页面结构加载完成后,再加载css样式。
-
在sass里
- sass的@import规则在生成css文件时就把相关文件导入进来。@import “sidebar”;这条命令将把sidebar.scss文件中所有样式添加到当前样式表中。
6.6.混合器(宏)@mixin
-
可以通过混合器让大段样式重用,@include 引入使用
@mixin no-bullets { width:200px; height:200px; border:1px solid #ccc } #box1 { @include no-bullets; background-color:#fff; } #box2 { @include no-bullets; background-color:#000; } #box3 { @include no-bullets; background-color:#bbb; }
-
可以传参的混合器 @mixin name (){}
@mixin no-bullets ($width,$height) { width:$width; height:$height; border:1px solid #ccc } #box1 { @include no-bullets(200,400); } #box2 { @include no-bullets(300,600); } #box3 { @include no-bullets(300,800); }
6.7.继承 @extend+选择器
#box{
width:100px;
height:100px;
h1{
text-align:center;
}
span{
font-size:16px;
a{
color:blue
}
}
}
#box2{
@extend #box;
}
6.8.颜色函数
-
co
l
o
r
要
改
变
的
颜
色
,
color要改变的颜色,
c
o
l
o
r
要
改
变
的
颜
色
,
amount取值范围是0~100%lighten($color, $amount) //颜色变浅函数; darken($color, $amount) //颜色变深函数;
6.9. sass逻辑结构
-
@if
当 @if 的表达式返回值不是 false 或者 null 时,条件成立,输出 {} 内的代码:p { @if 1 + 1 == 2 { border: 1px solid; } @if 5 < 3 { border: 2px dotted; } @if null { border: 3px double; } } // 编译为 p { border: 1px solid; }
-
@for
@for 指令可以在限制的范围内重复输出格式,每次按要求(变量的值)对输出结果做出变动。//第一种写法 @for $i from 1 through 3 {//循环三次 .item-#{$i} { width: 2em * $i; } } //相当于 .item-1{width:2em} .item-2{width:4em} .item-3{width:6em} //第二种写法 @for $i from 1 to 3 {//循环三次 .item-#{$i} { width: 2em * $i; } } //相当于 .item-1{width:2em} .item-2{width:4em} .item-3{width:6em}
-
function
Sass支持自定义函数,并能在任何属性值或Sass script中使用$grid-width: 40px; $gutter-width: 10px; @function grid-width($n) { @return $n * $grid-width + ($n - 1) * $gutter-width; } #sidebar1 { width: grid-width(5); } #sidebar2 { width: grid-width(4); } // 编译为 #sidebar { width: 240px; }
7.gulp-sass安装失败解决办法
1.安装gulp-sass需要依赖,node-sass
指令 : npm install node-sass
2.node-sass 安装完成后,gulp-sass 的依赖问题也就解决了,然后跳出去 node_modules 目录继续安装 gulp
指令 : npm install gulp-sass --save-dev