赞
踩
vuepc适配
post: 提交数据的方法
get: 获取数据的办法
md转换成index.html
i5ting_toc -f 代码格式化规范.md
// js更改 root 里的变量
document.documentElement.style.setProperty(`root变量`, 更改的值)
document.documentElement.style.setProperty
date = new Date(date)
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds()
click | 单击鼠标左键时发生,如果右键也按下则不会发生。当用户的焦点在按钮上并按了 Enter 键时,同样会触发这个事件 |
---|---|
dblclick | 双击鼠标左键时发生,如果右键也按下则不会发生 |
mousedown | 鼠标按下时触发 |
mouseup | 鼠标弹起时,松开任意一个鼠标按钮时发生 |
mousemove | 鼠标移动时,鼠标在某个元素上时持续发生 |
mouseout | 鼠标离开 时 |
focus | 获取焦点时 |
blur | 失去焦点时 |
mouseleave | 离开时,触发(子盒子不会触发) |
mouseenter | 经过盒子,触发(不会触发子盒子) |
transitionend | 过渡事件完成 |
Object.prototype.toString.call(变量)
typeOf // typeOf []
instanceof // [] instanceof Array
Array.isArray([])
constructor // {}.constoructor
typeof | instanceof | |
---|---|---|
作用 | 监测数据类型 | 检测对象之间的关联性 |
返回 | 小写字母字符串 | 布尔值 |
操作数 | 简单数据类型、 函数或者对象 | 左边必须是引用类型右边必须是函数 |
操作数量 | 一个 | 2个 |
事例 | typeof a | a instanceod Object |
// 简单的, 三个变量互调
// 数组, 将俩个数存入数组中然后, a=数组[0], b=数组[1]
// 对象法, 跟数组类似
// 数组运算法
let a = 3 , b = 5
a = [b, b = a][0]
// 解构赋值法
let a = 3, b = 5
[a, b] = [b, a]
var str = 'hello'
var pattern = /x/
const regxp = new RegExp(input, 'gi') // 全局匹配,并大小写
var result = pattern.exec(str)
console.log(result)
String的扩展
includes(str)
判断字符串中是否包含5
startsWith(str)
判断字符串是否以str开头
endsWith(str)
判断字符串是否以str结尾
repeat(count)
重复字符串
字符串.match(正则) // 一个在字符串中执行查找匹配的 String 方法,它返回一个数组,在未匹配到时会返回 null。
替换正则表达式
字符串.replace(‘12’, ‘#’) // 12换成#
匹配正则
var str = 'hello'
var pattern = /x/
var result = pattern.exec(str)
var result = 字符串.match(正则) // 一个在字符串中执行查找匹配的 String 方法,它返回一个数组,在未匹配到时会返回 null。
var result = 正则.test(字符串) // 判断是否在字符串中, 返回 true 或者 false
字符串.replace(/ok/g, '**')// 讲text 中的 ok 替换成 **
console.log(result)
let text = 'ssss'
let a = /^a/ // 以a开头的字符串
let a = /a$/ // 以a 结尾的字符串
text.replace(/ok/g, '**') // 讲text 中的 ok 替换成 **
text.replace(/ok/g, '**').replace(/jsg/g, 'jpg') // 讲text 中的 ok 替换成 ** 在吧 png 换成 jpg
输入框替换
const regxp = new RegExp(input)
if (this.souAll.username !== 'id') {
item[this.souAll.username] = item[this.souAll.username].replace(regxp, `<mark slot="one">${input}</mark>`)
}
浅拷贝只复制指向某个对象的指针, 而不是复制对象本身, 新旧对象还共享同一块内存
深拷贝复制出来了一个一模一样的对象, 修改新对象不会更改原有的对象
// 利用JSON.parse(JOSN.stringify(对象)),来进行深拷贝
let shen = { o: '你好' }
// let shen2 = Object.create(shen)
let shen2 = JSON.parse(JSON.stringify(shen))
// shen2.o = 'heoo'
console.log(shen)
console.log('-----');
console.log(shen2.o);
// object.assign倒是完美一些,即使function还有set什么的都可以拿到,但是对于引用的,如果拷贝的对象里面有一个属性值是另一个对象,那么这一个
Object.assgin({}, author) //author 是个对象
// 拷贝之后, 深拷贝用的Object.create 深拷贝的对象要用__proto__进行获取
Object.create() 方法
let shen = { o: '你好' }
let shen2 = Object.create(shen)
console.log(shen)
console.log('-----');
console.log(shen2.__proto__);
防抖: 如果事件被频繁的触发, 防抖能保证只有最后一次才能触发生效! 前面的 N 多次都会被忽略
节流: 如果事件被频繁的触发, 节流能够减少事件触发的频率, 因此, 节流是有选择性的执行一部分事件!
watch: {
input: {
immediate: true, deep: true,
handler(newVal) {
if (this.time) {
clearTimeout(this.time) // 清除定时器
}
this.time = setTimeout(() => {
this.changeBlian(newVal)
}, 1000)
}
}
},
/** 输入框发生变化 */
changeBlian(e) {
console.log(e)
},
// 防抖
var timer = null // 防抖动的 timer
function debounceSeaarch(keywords){ // 定义防抖的函数
timer = setTimeout(() =>{
getSuggestList(keywords)
}, 500)
}
$('#ipt').on('keyup', function(){ // 在触发 keyup 实践时, 立即清空 timer
clearTimeout(timer)
debounceSeaarch(keywords)
})
// 使用节流优化鼠标跟随效果
$(function () {
var angel = $('#angel')
var timer = null // 预定义一个 timer 节流阀
$(documone).on('mousemove', function(e){
if(timer) {return} // 判断节流阀是否为空, 如果不为空, 则证明距离上次执行事件不够, 把他清除掉
timer = setTimeout(function () {
$(angel).css('left', e.pageX + 'px').css('top', e.pageY + 'px')
timer = null // 设置了鼠标跟随效果后, 清空timer 节流阀, 方便下次继续开启
}, 16)
})
})
//js是个单线程语言, 他会先执行全局作用域之后,在执行各个局部作用域的代码片段。一个作用域引用另一个作用域中的变量, 我用到的,闭包的语法主要是,()()
每一个函数类型的数据,都有一个叫做prototype的属性,这个属性指向的是一个对象,就是所谓的原型对象
而原型对象有个 prototype.constructor 属性来指向构造函数
每一个实例对象又有一个 proto 属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有__proto__属性,这样一层一层往上找就形成了原型链。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9CC9VziR-1666187859832)(img/image-20220924223024625.png)]
// 箭头函数他是匿名的,用完就废弃了。所以他不需要构造函数的原型了,箭头函数的 this 指向为父级作用域的this ,因为没有自己的this,所以没法通过bind、call、apply来改变this指向
// 普通函数的 this 指向 是谁调用函数,就指向谁。如果没调用,就默认指向window。在vue中可能指向 vue 的实例。
[js数组截取方式splice()和slice()方法](https://blog.csdn.net/curryFMVP/article/details/113627742?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-113627742-blog-95458169.pc_relevant_sortByAnswer&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-113627742-blog-95458169.pc_relevant_sortByAnswer&utm_relevant_index=1)
使用slice()函数 // 删除字符串, 不改变原数组
slice(start, end) 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
使用 start(包含) 和 end(不包含) 参数来指定字符串提取的部分。
start 参数字符串中第一个字符位置为 0, 第二个字符位置为 1, 以此类推,如果是负数表示从尾部截取多少个字符串,slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。
end 参数如果为负数,-1 指字符串的最后一个字符的位置,-2 指倒数第二个字符,以此类推。
var str="ab12345"; // 改变原数组
str.slice()// 复制一个数组
str.slice(1,2) // 截取数组
str.slice(-1, '数组的长度') // 截取最后几个内容
console.log(str.slice(2)) // => 12345
字符串.split(',') // 将字符串转换成数组
Math.sign(x),负数返回-1,正数返回1
1. string.search() // 返回当前下标
{
let searchVal = 'yyds'
let searchResult = searchVal.search('y')
console.log(searchResult) // 0
}
string.includes() // 返回一个布尔值
{
let searchVal = 'yyds'
let searchResult = searchVal.includes('y', 1)
console.log(searchResult) // true
}
字符串.replace('a', 'b') // 第一个值的原字符,第二个为a换成b 。 字符串
字符串.padStart(2,0) // 前面补
字符串.padEnd(2,0) // 后面补
字符串.toUpperlase() // 字符串全部大写
字符串.toLowerlase() // 字符串全部小写
字符串.substring(0, 3) // 获取前三位的值
'x'.repeat(3) // 将x这个字符串重复三次
'sss'.startsWith('s') // 以 s 开头
'sss'.endsWith('s') // 以 s 开头
const res = Date.parse(new Date()) + '' // 将日期转换成时间戳
new Date().getTime()
console.log(res);
let ress = res.substring(0, res.length - 3); // 获取后三位之前的内容
console.log(ress);
const shijian = new Date().toLocaleDateString() + " "+ new Date().toLocaleTimeString('chinese', { hour12: false }) // 获取时间
console.log(shijian); // '2022/9/25 16:37:38'
Number(new Date()) // 将日期转换成毫秒数
arr.push() // 添加数组,也可返回数组的长度
arr.unshift() // 在数组第一个值前添加
arr.pop() // 删除数组最后一个值
arr.shift() // 删除数组第一个值
arr.reverse() // 翻转数组
arr.indexOf('') // 括号中的值为数组的值,可以得到索引,返回第一个符合条件的值
// arr.indexOf('查找的值')
arr.slice()// 复制一个数组,, 不改变原数组
arr.slice(1,2) // 截取数组
arr.slice(-1, '数组的长度') // 截取最后几个内容
arr.concat() // 合并多个数组, 不改变原数组
arr.join('') // 将数组转换成字符串, 括号里的为用什么隔开
[a,d,v].findIndex((value) => value > 9) // 找到第一个符合条件的, 返回下标,返回一个新的值,从0开始查找
arr.findIndex(实参 =>表达式) 这个是遍历数组中的对象,可以把数组里的每一个元素遍历
* indexOf :查找值作为第一个参数,采用 === 比较,更多的是用于查找基本类型,如果是对象类型,则是判断是否是同一个对象的引用
* findIndex :比较函数作为第一个参数,多用于非基本类型(例如对象)的数组索引查找,或查找条件很复杂,遍历数组中的每个元素
arr.concat(a) // 将a和arr进行相连接
arr.splice(2,1) // 将数组索引从第二个删,删除一个(索引删除数组的值)
arr.forEach(function(value, index, array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的数组
})
//相当于数组遍历的 for循环 没有返回值
arr.includes()
[1,2].includes(2) // 数组包不包含2
判断数组是否包含某个值,返回 true / false
参数1,必须,表示查找的内容
参数2,可选,表示开始查找的位置,0表示开头的位置
let a = arr.reduce( (sum, value) => {
return sum += value
}, 0) // 累积数组的和, 返回一个数字
let a = arr.every(value =>{
return 判断条件
}) // 找到数组中不符合条件的返回 false, 返回一个布尔值
arr.sort(function (a, b) { // 冒泡排序
return a-b // 降序
b - a // 升序
})
const bands = ['The Plot in You', 'The Devil Wears Prada', 'Pierce the Veil', 'Norma Jean', 'The Bled', 'Say Anything', 'The Midway State', 'We Came as Romans', 'Counterparts', 'Oh, Sleeper', 'A Skylit Drive', 'Anywhere But Here', 'An Old Dog'];
const sortedBands = bands.sort((a, b) => {
if (b > a) { // 字符z-a 排序
return 1
} else { // 字符 a - b 排序
return -1
}
});
console.log(sortedBands);
// some 查找数组中是否有满足条件的元素
var arr = [10, 30, 4];
var flag = arr.some(function(value,index,array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的数组
return value < 3;
});
console.log(flag);//false返回值是布尔值,只要查找到满足条件的一个元素就立马终止循环
数组方法 find 过滤数组
var newArr = arr.find(function(value, index,array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的数组
return value >= 20;
});
console.log(newArr);//[66] //找到第一个符合条件的,就返回改判断条件
数组方法filter过滤数组
var newArr = arr.filter(function(value, index,array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的数组
return value >= 20;
});
console.log(newArr);//[66,88] //返回值是一个新数组
数组查重
var ter = ["科幻", "娱乐", "奇闻"]
var xin = []
for (var i = 0; i < 500; i++) {
if (xin.indexOf(ter[i]) === -1) {
xin.push(ter[i]);
}
}
...new Set()
const res = this.array
const aaaa = res.unshift(11112)
const p = [...new Set(res)]
this.array = p
代码
// findIndex 比 indexof 高级, 可以自己去比较过程
// 语法:
// 数组对象.findIndex( (值变量名) => { return 判断条件 })
// 返回值: 找到符合条件,当前值对应索引返回在原地
// 执行过程(很多数组高级方法都是如此) : 对每个遍历的值, 传入函数体执行
let result = list.findIndex( (obj) =>{ // 返回第一个找到的下标
return obj.id === 101
})
log(result)
0.Array.isArray() 用于确定传递的值是否是一个 Array。
1.Array.of() 返回一个由参数组成的数组
2.Array.from() 将数组对象转换为数组 不改变原对象 返回新数组
8.splice() 添加/删除/替换 当前数组改变
11.fill()数组的填充、 数组的替换 [改变原数组、ES6] //
arr.fill(100, 2) // 讲数组的第二个元素到最后一个换成100
new Arr(5) // 创建数组长度为5
new Arr(5).fill(100) // 创建数组长度为5,且元素都是100
16.indexOf() 查找数组中某元素的第一个索引值。[不改变原数组] 如果没有就返回-1
17.lastIndexOf() 逆向查找指定元素在数组中的第一个位置。[不改变原数组]
18.includes() 查找数组是否包含某个元素。[不改变原数组,]
数组遍历方法
5.map() 对数组中的每一个元素都进行处理,返回新的数组
6.keys() 遍历键名 / values() 遍历键值/ entries() 遍历键值对
8.find() / findIndex() 根据条件找到数组成员 [ES6]
找到数组中第一个满足条件的成员并返回该成员,如果找不到返回undefined
findIndex( (值变量名) => {return 判断条件} )
执行过程(很多数组高级方法都是如此): 对每个遍历的值,转入函数体执行
9.flat()深度遍历展开数组
方法 | 描述 |
---|---|
concat() | 连接俩个或者更多的数组,并返回结果 |
join() | 把数组的所有元素放入一个字符串, 元素通过指定的分隔符进行分割 |
poop() | 删除并返回数组的最后一个元素 |
push() | 向数组的末尾添加一个或者多个元素, 并返回新的长度 |
reverse() | 点到数组中的顺序 |
shift() | 删除并返回数组中的第一个元素 |
slice() | 从某个已有的数组返回选定的元素 |
sort() | 对数组进行排序 |
splice() | 删除数组 |
toSource() | 返回该对象的源代码 |
toString() | 将数组转换成字符串, 并返回结果 |
toLocaleString() | 将数组转换成本地数组, 并返回结果 |
unshift() | 向数组的开头添加一个或者多个, 并返回长度 |
valueOf() | 返回数组对象的原始值 |
时间 — 时间戳相互转换
var timestamp = Date.parse(new Date()); // 省略后三位
var timestamp=new Date().getTime();// 返回精确毫秒
//js中的日期时间函数
var date = new Date();
date.getYear(); //获取年份(2位)
date.getFullYear(); //获取完整的年份(4位,1970-)
date.getMonth(); //获取月份(0-11,0代表1月)
date.getDate(); //获取日(1-31)
date.getDay(); //获取星期?(0-6,0代表星期天)
date.getTime(); //获取时间(从1970.1.1开始的毫秒数)
date.getHours(); //获取小时数(0-23)
date.getMinutes(); //获取分钟数(0-59)
date.getSeconds(); //获取秒数(0-59)
date.getMilliseconds(); //获取毫秒数(0-999)
date.toLocaleDateString(); //获取日期
date.toLocaleTimeString(); //获取时间
date.toLocaleString(); //获取日期与时间
//数字时间戳转换成日期时间函数,time为传入的数字时间戳,如果数字时间戳先前作了/1000运算,请先*1000再传入
function changeTimeFormat(time) {
var date = new Date(time);
var month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
var currentDate = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
var hh = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
var mm = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
return date.getFullYear() + "-" + month + "-" + currentDate+" "+hh + ":" + mm;
//返回格式:yyyy-MM-dd hh:mm
}
// 聊天时间
export const timeChange = timeValue => {
timeValue = new Date(timeValue).getTime()
var timeNew = new Date().getTime() // 当前时间
// console.log('传入的时间', timeValue, timeNew)
var timeDiffer = timeNew - timeValue // 与当前时间误差
// console.log('时间差', timeDiffer)
var returnTime = ''
if (timeDiffer <= 60000) { // 一分钟内
returnTime = '刚刚'
} else if (timeDiffer > 60000 && timeDiffer < 3600000) { // 1小时内
returnTime = Math.floor(timeDiffer / 60000) + '分钟前'
} else if (timeDiffer >= 3600000 && timeDiffer < 86400000 && isYestday(timeValue) === false) { // 今日
returnTime = formatTime(timeValue).substr(11, 5)
} else if (timeDiffer > 3600000 && isYestday(timeValue) === true) { // 昨天
returnTime = '昨天' + formatTime(timeValue).substr(11, 5)
} else if (timeDiffer > 86400000 && isYestday(timeValue) === false && isYear(timeValue) === true) { // 今年
returnTime = formatTime(timeValue).substr(5, 11)
} else if (timeDiffer > 86400000 && isYestday(timeValue) === false && isYear(timeValue) === false) { // 不属于今年
returnTime = formatTime(timeValue).substr(0, 16)
}
return returnTime
}
function isYestday (timeValue) { // 是否为昨天
const date = new Date(timeValue)
const today = new Date()
if (date.getFullYear() === today.getFullYear() && date.getMonth() === today.getMonth()) {
if (date.getDate() - today.getDate() === 1) {
return true
} else {
return false
}
} else {
return false
}
}
function isYear (timeValue) { // 是否为今年
const dateyear = new Date(timeValue).getFullYear()
const toyear = new Date().getFullYear()
// console.log(dateyear, toyear)
if (dateyear === toyear) {
return true
} else {
return false
}
}
// 函数:formatTime 格式化时间 返回时间字符串如 2018-07-06 11:11:37
function formatTime (date) {
var t = getTimeArray(date)
return [t[0], t[1], t[2]].map(formatNumber).join('-') + ' ' + [t[3], t[4], t[5]].map(formatNumber).join(':')
}
function getTimeArray (date) {
date = new Date(date)
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds()
return [year, month, day, hour, minute, second].map(formatNumber)
}
// 转化日期 如2018-7-6 -->(2018-07-06)
function formatNumber (n) {
n = n.toString()
return n[1] ? n : '0' + n
}
if()
if () {} else if (){}
switch(表达式){
case 值1:
语句体:
break;
}
for () { }
while () {}
do {
// 循环体代码 - 条件表达式为 true 时重复执行循环体代码
} while(条件表达式);
continue 关键字用于立即跳出本次循环,继续下一次循环(本次循环体中 continue 之后的代码就会少执行一次)。
break 关键字用于立即跳出整个循环(循环结束)。
var 数组名 = new Array() ;
var arr = new Array(); // 创建一个新的空数组
数组遍历
arr.forEach(function (value, index, arr) {
value // 数组的值
index // 索引号
arr // 数组本身
})
function 构造函数名(形参1,形参2,形参3) {
this.属性名1 = 参数1;
this.属性名2 = 参数2;
this.属性名3 = 参数3;
this.方法名 = 函数体;
}
var obj = new 构造函数名(实参1,实参2,实参3)
/* 1. 普通函数 */
function fn() {
console.log('人生的巅峰');
}
fn();
/* 2. 对象的方法 */
var o = {
sayHi: function() {
console.log('人生的巅峰');
}
}
o.sayHi();
/* 3. 构造函数*/
function Star() {};
new Star();
/* 4. 绑定事件函数*/
btn.onclick = function() {}; // 点击了按钮就可以调用这个函数
/* 5. 定时器函数*/
setInterval(function() {}, 1000); 这个函数是定时器自动1秒钟调用一次
/* 6. 立即执行函数(自调用函数)*/
(function() {
console.log('人生的巅峰');
})();
说明方式 | this指向 |
---|---|
普通函数调用 | window |
构造函数调用 | 实例对象,原型对象里面的方法也指向实例对象 |
对象方法调用 | 该方法所属对象 |
事件绑定方法 | 绑定事件对象 |
定时器函数 | window |
立即执行函数 | window |
call方法
方法调用一个对象。简单理解为调用函数的方式,但是它可以改变函数的 this 指向
fn.call(o,1,2)//此时的this指向的是对象o,参数使用逗号隔开,运行结果为3
apply方法
方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。
fn.apply(o,[1,2])//此时的this指向的是对象o,参数使用数组传递 运行结果为3
bind()
方法不会调用函数,但是能改变函数内部this 指向,返回的是原函数改变this之后产生的新函数
var f = fn.bind(o, 1, 2); //此处的f是bind返回的新函数
f();//调用新函数 this指向的是对象o 参数使用逗号隔开
var star = {
name : 'pink',
age : 18,
sex : '男',
sayHi : function(){
alert('大家好啊~');
}
};
var andy = new Obect();
andy.name = 'pink';
andy.age = 18;
andy.sex = '男';
andy.sayHi = function(){
alert('大家好啊~');
}
function 构造函数名(形参1,形参2,形参3) {
this.属性名1 = 参数1;
this.属性名2 = 参数2;
this.属性名3 = 参数3;
this.方法名 = 函数体;
}
var obj = new 构造函数名(实参1,实参2,实参3)
for (变量 in 对象名字) {
// 在此执行代码
}
for (var k in obj) {
console.log(k); // 这里的 k 是属性名
console.log(obj[k]); // 这里的 obj[k] 是属性值
}
语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为 k 或者 key。
Object.keys(obj) // 名
Object.values(obj) // 值
堆
存放复杂数据类型:数组,对象,data时间
栈
存放简单数据类型:布尔值,Number,null,string,underfind
var el = document.querySelector('#demo');
el.style.setProperty('background-color', '#f00', 'important');
keyup | 键盘松开时触发 |
keydown | 摁下时触发 |
keypress | 摁下时触发, 但不支持功能键 |
document.addEventListener('keyup', function(e) {
// console.log(e);
console.log('up:' + e.keyCode);
// 我们可以利用keycode返回的ASCII码值来判断用户按下了那个键
if (e.keyCode === 65) {
alert('您按下的a键');
} else {
alert('您没有按下a键')
}
})
innerHTML 和 innerText 的区别是一个操作,html元素一个是,文本
img.className = ‘a’ 将 img 标签增加 a 这个class 类名
document.body.style.backgroundImage = ‘url(’ + this.src + ‘)’;
// 点击事件
let ls = document.getElementById('ldh')
ldh.onclick = function(){
ls.style.width = '500px'
text.className = 'sadsa' // 修改class 类名
添加一个类名
获取元素名.classList.add("类名");
添加多个类名用逗号隔开
获取元素名.classList..add("类名1","类名2","类名3",...); 每个类名需要用引号引起来
移除一个类名
获取元素名.classList.remove("类名");
移除多个类名
获取元素名.classList.remove("类名1","类名2","类名3",...); 每个类名需要用引号引起来
//添加和删除类名
this.classList.toggle('open');
}
给五个元素绑定一个事件
<html>
<p></p>
<p></p>
</html>
<script>
let btns = document.ge..('p')
for(let i = 0; i < btns.lenght; i++){
btns.onclick = function() {
this.style.color = 'pink' //当前元素颜色添加
for(let y = 0; y < ; y++){
btns[i].style.color = ''
}
}
}
</script>
用这个方法, 以下的了解OK
div.dataset.index = 'om'.// 设置自定义属性
div.dataset.index|| div.dataset[index] // 打印了自定义的index 属性
俩个横岗用驼峰命名法
div.setAttribute('data-time', 20) // 设置了一个自定义属性为20
console.log(div.getAttribute('data-p')); // 获取了自定义属性
// class 不是className
// 3 移除属性 removeAttribute(属性)
div.removeAttribute('index')
<div id="demo" index="1" class="nav"></div>
<script>
var div = document.querySelector('div');
// 1. 获取元素的属性值
// (1) element.属性
console.log(div.id);
//(2) element.getAttribute('属性') get得到获取 attribute 属性的意思 我们程序员自己添加的属性我们称为自定义属性 index
console.log(div.getAttribute('id'));
console.log(div.getAttribute('index'));
</script>
element.属性 // 获取内置属性值
element.setAttribute('属性', '值')
区别:
element.属性 // 获取内置属性值(元素本身自带的属性)
element.getAttribute('属性') // 主要设置自定义的属性(标准)
// 2. 设置元素属性值
// (1) element.属性= '值'
div.id = 'test';
div.className = 'navs';
// (2) element.setAttribute('属性', '值'); 主要针对于自定义属性
div.setAttribute('index', 2);
div.setAttribute('class', 'footer'); // class 特殊 这里面写的就是
主要用下面的方法
div.dataset.index = 'om'.// 设置自定义属性
div.dataset.index|| div.dataset[index] // 打印了自定义的index 属性
俩个横岗用驼峰命名法
div.setAttribute('data-time', 20) // 设置了一个自定义属性为20
console.log(div.getAttribute('data-p')); // 获取了自定义属性
// class 不是className
// 3 移除属性 removeAttribute(属性)
div.removeAttribute('index');
// 1. 创建节点元素节点
var li = document.createElement('li');
// 2. 添加节点 node.appendChild(child) node 父级 child 是子级 后面追加元素 类似于数组中的push
var ul = document.querySelector('ul');
ul.appendChild(li);
// 3. 添加节点 node.insertBefore(child, 指定元素);
var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);
// 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素1
// 父元素最后一个子节点 .lastElementChild , 父.children[0]
// 父元素第一个子节点 .firstElementChild , 父.children[children.length - 1]
// 查找父节点 子.parentNode // 上一级父节点亲爸爸的
//下一个兄弟节点 .nextElementSibling
// 上一个兄弟节点 .previousElementSibling
// 删除子节点 node.removeChild(child)
查找子节点
父元素最后一个子节点
.lastElementChild
父.children[0]
父元素最后一个子节点
父元素.firstElementChild
父.children[children.length - 1]
查找父节点
子.parentNode // 上一级父节点亲爸爸的
查找兄弟节点
下一个兄弟节点
.nextElementSibling
上一个兄弟节点
.previousElementSibling
创建节点
. 添加节点
node.appendChild(child) // 方法是将一个节点添加到指定节点的子节点的末尾, 类似于 css 的 after 伪元素
node.insertBefo(child) // 方法是将一个节点添加到指定节点的子节点的前面, 类似于 css 的 before 伪元素
// 1. 创建节点元素节点
var li = document.createElement('li');
// 2. 添加节点 node.appendChild(child) node 父级 child 是子级 后面追加元素 类似于数组中的push
var ul = document.querySelector('ul');
ul.appendChild(li);
// 3. 添加节点 node.insertBefore(child, 指定元素);
var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);
// 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素1
删除节点
node.removeChild(child)
//
ul.removeChild(ul.children[0]);
node.removeChild() 方法从 node节点中删除一个子节点,返回删除的节点。
复制(克隆)节点
node.cloneNode()
//
var lili = ul.children[0].cloneNode(true);
ul.appendChild(lili);
const linkCoords = this.getBoundingClientRect();
rectObject.top:// 元素上边到视窗上边的距离;
rectObject.bottom:// 元素下边到视窗上边的距离;
rectObject.right:// 元素右边到视窗左边的距离;
rectObject.left:// 元素左边到视窗左边的距离;
rectObject.width:// 是元素自身的宽度
rectObject.height: // 是元素自身的高度
const coords = {
width: linkCoords.width, // 返回元素的宽度
height: linkCoords.height, // 返回元素的高度
top: linkCoords.top + window.scrollY, // 返回元素距离浏览器左侧的位置
left: linkCoords.left + window.scrollX// 返回元素距离浏览器顶部的位置
};
// 获取 元素距离浏览器的位置
function getElementTop(el) {
if (el.offsetParent) {
return this.getElementTop(el.offsetParent) + el.offsetTop
}
return el.offsetTop
}
const res = getElementTop(sadsa)
console.log(res);
offset系列属性 | 作用 |
---|---|
element.offsetParent | 返回该元素有定位的父级元素, 如果估计元素没有定位就返回body |
element.offsetTop | 返回元素相对带有定位元素的上方偏移 |
element.offsetLeft | 返回元素相对带有定位元素的左方偏移 |
element.offsetWidth | 该元素的宽度(包括padding,边框,内容的宽度,) |
element.offsetHeight | 该元素的高度(包括padding,边框,内容的宽度,) |
element.clientTop | 返回元素上边框的大小 |
element.clientLfet | 返回元素左边框的大小 |
element.clientWidth | 该元素的宽度(包括padding,容的宽度,不包含边框) |
element.clientHeight | 该元素的高度(包括padding,容的宽度,不包含边框) |
getBoundingClientRect() | 获取元素位置,这个方法没有参数 |
scrollLeft 、scrollTop: | 设置或获取位于对象最顶/左端和窗口中可见内容的最顶/左端之间的距离。即当前上滚或左滚的距离。 |
scrollHeight scrollWidth: | 获取对象可滚动的总高度/宽度 |
e.offsetX | 鼠标距离点击元素的距离事件发生时鼠标相对于事件源元素的坐标,获取数据类似pageX/Y,但是受到子元素影响。意思就是pageX/Y总是相对于网页左上角。但是offsetX/Y是相对于触发事件源那个盒子左上角 |
---|---|
e.pageX/Y | 鼠标距离浏览器的位置 |
scrollTop() | //卷起来的高度 |
<div id="box"></div>
var object=document.getElementById('box');
rectObject = object.getBoundingClientRect();
rectObject.top:元素上边到视窗上边的距离;
rectObject.right:元素右边到视窗左边的距离;
rectObject.bottom:元素下边到视窗上边的距离;
rectObject.left:元素左边到视窗左边的距离;
rectObject.width:是元素自身的宽
rectObject.height是元素自身的高
const divs = document.querySelectorAll('div')
function log(e){
// e.stopPropagation();
// console.log(this);
console.log(e.target);
}
divs.forEach(item => item.addEventListener('click', log,{
capture: false, // true 的话是由外向里,捕获阶段, false 是磨人的由内向外
once: true// 被调用的次数,只会被触发一次
}))
但有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行),
这时候this指向的是父元素,因为它是绑定事件的元素对象,
而target指向的是子元素,因为他是触发事件的那个具体元素对象。
说白了就是,不给子元素注册事件,给父元素注册事件,把处理代码在父元素的事件中执行。
给父元素注册事件,利用事件冒泡,当子元素的事件触发,会冒泡到父元素,然后去控制相应的子元素。
// 鼠标事件对象 MouseEvent
document.addEventListener('click', function(e) {
// 1. client 鼠标在可视区的x和y坐标
console.log(e.clientX);
console.log(e.clientY);
console.log('---------------------');
// 2. page 鼠标在页面文档的x和y坐标
console.log(e.pageX);
console.log(e.pageY);
console.log('---------------------');
// 3. screen 鼠标在电脑屏幕的x和y坐标
console.log(e.screenX);
console.log(e.screenY);
})
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qNaQ7HsB-1666187859833)(img/image-20220924225538755.png)]
window 对象给我们提供了 2 个非常好用的方法-定时器。
setTimeout() 几秒后执行
setInterval() 持续
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。
一般是由服务器生成,可设置失效时间。如果在浏览器生成,则默认为浏览器关闭后失效。
sessionStorage约5M、
存储数据:sessionStorage.setItem(key, value)
获取数据: sessionStorage.getItem(key)
删除数据: sessionStorage.removeItem(key)
清空数据:(所有都清除掉):sessionStorage.clear()
localStorage约20M
存储数据:localStorage.setItem(key, value)
获取数据: localStorage.getItem(key)
删除数据: localStorage.removeItem(key)
清空数据:(所有都清除掉): localStorage.clear()
location.assgin('地址') // 跳转页面,能后腿
location.replace('地址') // 跳转页面,不能后腿
重新加载(刷新)
location.reload() // 刷新,加上ture强制刷新
navigator
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = ""; //手机
} else {
window.location.href = ""; //电脑
}
navigator.go(1,-1) // 1 为前进, -1 后腿
history.back() 后退
history.forward() 前进
可视化区域
滚动距离
scroll // 滚动事件
本身.scrollWidth //全部文字宽度,包括超出的
本身.scrollHeight // 全部文字高度,包括超出的
本身.scrollTop // 文字超出的高度
盒子加上overflow:auto,加上滚动条
不带边框,内容超出盒子 = 盒子大小+超出内容
页面被减去的头部
window.pageYoffset
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oaiDKaWS-1666187859834)(img/image-20220924225558065.png)]
//步骤1 使用class关键字
class name {
// class body
}
// 1. 创建类 class 创建一个类
class Star {
// 类的共有属性放到 constructor 里面 constructor是 构造器或者构造函数
constructor(uname, age) {
this.uname = uname;
this.age = age;
}//------------------------------------------->注意,方法与方法之间不需要添加逗号
sing(song) {
console.log(this.uname + '唱' + song);
}
}
// 2. 利用类创建对象 new
var ldh = new Star('刘德华', 18);
console.log(ldh); // Star {uname: "刘德华", age: 18}
ldh.sing('冰雨'); // 刘德华唱冰雨
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-estY7kkE-1666187859835)(img/image-20220924225610787.png)]
// 父类
class Father{
}
// 子类继承父类
class Son extends Father {
}
class Father {
constructor(surname) {
this.surname= surname;
}
say() {
console.log('你的姓是' + this.surname);
}
}
class Son extends Father{ // 这样子类就继承了父类的属性和方法
}
var damao= new Son('刘');
damao.say(); //结果为 你的姓是刘
每一个函数类型的数据,都有一个叫做prototype的属性,这个属性指向的是一个对象,就是所谓的原型对象
而原型对象有个 prototype.constructor 属性来指向构造函数
每一个实例对象又有一个 proto 属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有__proto__属性,这样一层一层往上找就形成了原型链。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-txIPAsFE-1666187859836)(img/image-20220924225620563.png)]
Object.keys(obj) // 名
Object.values(obj) // 值
'use strict'
num = 10
console.log(num)//严格模式后使用未声明的变量
--------------------------------------------------------------------------------
var num2 = 1;
delete num2;//严格模式不允许删除变量
--------------------------------------------------------------------------------
function fn() {
console.log(this); // 严格模式下全局作用域中函数中的 this 是 undefined
}
fn();
---------------------------------------------------------------------------------
function Star() {
this.sex = '男';
}
// Star();严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.
var ldh = new Star();
console.log(ldh.sex);
----------------------------------------------------------------------------------
setTimeout(function() {
console.log(this); //严格模式下,定时器 this 还是指向 window
}, 2000); xxxxxxxxxx 'use strict'num = 10 console.log(num)//严格模式后使用未声明的变量--------------------------------------------------------------------------------var num2 = 1;delete num2;//严格模式不允许删除变量--------------------------------------------------------------------------------function fn() { console.log(this); // 严格模式下全局作用域中函数中的 this 是 undefined}fn(); ---------------------------------------------------------------------------------function Star() { this.sex = '男';}// Star();严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.var ldh = new Star();console.log(ldh.sex);----------------------------------------------------------------------------------setTimeout(function() { console.log(this); //严格模式下,定时器 this 还是指向 window}, 2000);
ES6中允许从数组中提取值,按照对应位置,对变量赋值,对象也可以实现解构
数组解构
let [a, b, c] = [1, 2, 3];
console.log(a)//1
console.log(b)//2
console.log(c)//3
//如果解构不成功,变量的值为undefined
对象解构
let person = { name: 'zhangsan', age: 20 };
let { name, age } = person;
console.log(name); // 'zhangsan'
console.log(age); // 20
let {name: myName, age: myAge} = person; // myName myAge 属于别名
console.log(myName); // 'zhangsan'
console.log(myAge); // 20
let ary = [1, 2, 3];
...ary // 1, 2, 3
console.log(...ary); // 1 2 3,相当于下面的代码
console.log(1,2,3);
合并数组
let ary3 = [...ary1, ...ary2];
// 方法二
ary1.push(...ary2);
//转成数组
Array.from(数组)
$.ajax({
type: 'GET/post',
url: '地址',
data: {
数据
},
success: function (res) {
console.log(res)
}
})
中文官首页:http://aui.github.io/art-template/zh-cn/index.html
循环
{{each 数组 }}
{{/each}}
js代码
template('id', 数据)
html代码
<script type="text/html" id=" ">
{{each 数组名}}
<!--搜索建议项-->
{{index}} // 索引
{{value}} // 值
{{/each}}
JSONP(JQ)只支持get不支持post
$.ajax({
url: '地址',
// 如果要使用 $.ajax() 发起 JSONP 请求,必须指定 datatype 为 jsonp
dataType: 'jsonp',
success: function (res) {
console.log(res)
}
})
在多个相重叠的时间段内,保证只执行一次事件处理函数。 将事件处理函数内的代码封装一个定时器内,再定时器之前清除这个定时器
let timer = null
oHtml.onclick = function () {
clearTimer(timer)
debounce()
}
let timer = null
function debounce() {
timer = setTimeout(function () {
// ....
// ...
}, 2000)
}
每间隔一段时间执行1次事件处理函数
let timer = null
oHtml.onclick = function () {
if (timer) { return }
timer = setTimeout(function () {
// ....
timer = null
}, 2000)
$.ajaxPrefilter(function (options) {
// 在发起真正的 Ajax 请求之前,统一拼接请求的根路径
options.url = '跟路径' + options.url
if (options.url.indexOf('/my/') !== -1) {
options.headers = {
Authorization: localStorage.getItem('token') || ''
}
}
options.complete = function (res) {
// console.log('执行了 complete 回调:')
// console.log(res)
// 在 complete 回调函数中,可以使用 res.responseJSON 拿到服务器响应回来的数据
if (res.responseJSON.status === 1 && res.responseJSON.message === '身份认证失败!') {
// 1. 强制清空 token
localStorage.removeItem('token')
// 2. 强制跳转到登录页面
location.href = '/login.html'
}
}
})
git init - 初始化仓库。
git add 文件名 ===添加到暂存区
git add . ===全部添加到暂存区
git status === 查看文件状态
(修改文件)
git checkout 文件名 === 恢复到原来文件 暂存区覆盖源文件
git rm --cached 文件名 === 将文件从暂存中删除
git commit -m "提交消息" === 提交到库
git log === 获取提交信息
git rest --hard commitID
git rm --cached 文件名 === 删除
分支
git branch === 查看分支
git branch 分支名 ===创建分支命令
git checkout 文件名 ===切换分支命令
$ git branch -d 分支名 === 删除分支rank
git merge 分支名 === 合并分支 (创建分支 创建分支文件 切换分支工作区 添加到暂存区 提交到库 切换主分区 合并)
git branch -d 分支名 ===删除合并分支
git branch -D 分支名 === 强制删除分支
git stash ===储存临时改动
git clone(git push http://github.com/xx/ooo) 远程地址 === 克隆远程数据
git clone -b <分支名> <远程仓库地址>
git pull 远程地址 分支名称 === 拉去远程仓库最新版本
git push -u 地址 分之名称 // 此方法是记住提交的地址, 下次直接git push 即可
第一次提交: git push 远程地址(https://github.com/QuanGHub/git-deom.git) ==远程提交数据 (提交暂停区 提交库 远程提交数据 git push)
第二次提交git remote add 别名 远程仓库地址=》更改文件内容 =>提交到暂存区=>提交到库=>git push 别名 master
第三次提交 git push -u 别名 master
第四次提交 git push
cd-文件夹名字 === 切换到该文件夹master
// 拉去远程仓库所有分之
git clone http://myrepo.xxx.com/project/.git ,这样在git_work目录下得到一个project子目录
git branch -a //,列出所有分支名称如下:
remotes/origin/dev
remotes/origin/release
git checkout -b 分支名 origin/分支名 //,作用是checkout远程的dev分支,在本地起名为dev分支,并切换到本地的dev分支
git checkout -b release origin/release //,作用参见上
分支合并
将本地的 tabbar 分支进行本地的 commit 提交:
git add .
git commit -m "完成了 tabBar 的开发"
将本地的 tabbar 分支推送到远程仓库进行保存:
git push -u origin tabbar
将本地的 tabbar 分支合并到本地的 master 分支:
git checkout master
git merge tabbar
删除本地的 tabbar 分支:
git branch -d tabbar
pull 和 clone 的区别, pull 是拉去最新的代码, clone 是本地没有代码,全部拉去
// 执行操作, 多人协作开发流程
git init - 初始化仓库。
git add 文件名 ===添加到暂存区
git add . ===全部添加到暂存区
git status === 查看文件状态
git commit -m '提交信息' === 向仓库提交代码
git push 地址 分支 === 推送分支
git clone 地址 === 克隆仓库中的代码
// 修改后, 提交到仓库中的代码
// B若修改了代码, A在拉去最新的代码
git pull 地址 分支名称
// 发生冲突后解决办法
ssh 免密登陆
第一步: 在终端输入 ssh-keygen , 一路回车
然后, 在系统盘下的用户文件下的 .ssh 文件夹下,下有 id_rsa 和 id_rsa.pub 俩个文件。
将 id_rsa.pub 放入gitee的 ssh中
问题1: 什么是ES6?
答案: ECMAScript2015 (2015年指定的js标准)-语法标准, 规定了很多新的语法 (例如: let, const声明变量, 箭头函数…模块化语法)
关键字:
导入: import
导出: export (暴露给外面用, 不暴露外面用不了)
每个js文件都是独立作用域的, 需要导出别人才能导入使用
package.json中添加 type: ‘module’
默认导出语法: (一次)
export default 对象
默认导入语法:
import 变量名 from '目标js文件的路径'
效果: 变量名的值就是导出的对象
好处: 需要什么才导入什么, 不必全都导入过来
按需导出语法: (多次)
export 声明变量关键字 变量名 = 值
export 声明变量关键字 变量名 = 值
export 声明变量关键字 变量名 = 值
例:
export const no = () => {
}
export function getDepartment() {
}
按需导入语法:
import { export变量名一致 } from '目标js文件的路径'
注意(了解)
在导入的时候可以用as关键字重命名
import { a as strA } from '目标文件'
以后使用strA变量
可以混合使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qFKJrFZS-1666187859837)(img/image-20220924225634639.png)]
直接导出语法:
无导出, 直接写一些要执行的js代码
直接导入语法:
import '目标js文件路径'
概念: ES6标准时指定的一个新的对象
回调地狱: 异步任务的结果是在回调函数里接收, 在这里再次发起一个异步任务, 形成了回调地狱…
创建Promise对象实例 (包裹一个异步任务)
const p = new Promise(function(resolve, reject){
// 异步代码
// 如果成功了, resolve(成功值) 导致 then()函数体里代码执行了
// 如果失败了, reject(失败值) 导致 catch()函数体里代码执行
})
.then() 用于等待异步任务的结果
p.then(function(result){
}, function(error){
})
p.then(function(result){
}).catch(function(error){
})
// 等价的, then()里第二个函数体可以写成后续.catch()这种模式
Promise.all([Promise对象, Promise对象]) - 所有顺序
把多个Promise对象合并成一个大的Promise
特点: 等待所有小Promise对象成功后, 触发最外面大的Promise对象.then()拿到的结果是数组, 顺序就是Promise对象顺序
Promise.race([Promise对象, Promise对象]) - 赛跑
把多个Promise对象合并成一个大的Promise
特点: 只要有一个小的Promise对象成功后, 触发最外面大的Promise对象.then()
在Promise对象.then()里函数体中, return出来一个Promise对象, 返回在原地
// 细节: Promise对象内异步成功后才执行then()里函数体
// 细节(口诀): then()函数体里return的Promise对象, 会返回到then()函数原地
let p = thenFs.readFile('./files/1.txt', 'utf8') // Promise对象
let p2 = p.then(r1 => { // p2就是读2文件的Promise对象
console.log(r1);
return thenFs.readFile('./files/2.txt', 'utf8') // Promise对象
})
let p3 = p2.then(r2 => {
console.log(r2);
return thenFs.readFile('./files/3.txt', 'utf8') // Promise对象
})
p3.then(r3 => {
console.log(r3);
})
// 没有回调函数嵌套, 而是用then的链式调用解决了回调地狱(但是这种还是很难理解, 后面ES7出了async+await关键字)
例:
import { homeCategory } from '@/api/category'
import { ref } from 'vue'
const inm = ref([])
// const p = homeCategory()
homeCategory().then((res) => { // p2就是读2文件的Promise对象
// return res // Promise对象
inm.value = res.result // 记得要return出去
})
俩个异步函数时, 怎么获取接口
Promise.all([findNew(), findBanner()]).then((res) => {
console.log(res)
})
JS代码里只要报错了, 你没有写代码进行错误捕获和处理, 代码就会停止往下执行
如果你不想让报错阻止代码往下走, 你需要自己捕获和处理错误
概念: 当JS主线程执行栈空闲时, 从任务队列里取出回调函数执行, 又空闲了, 接着再去任务队列里取出回调函数执行, 这样的一个过程就叫事件循环EventLoop
中文: 事件循环(辅助你来理解代码执行顺序)
JS是单线程的, 同一时间只能执行一行代码(一个任务)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KfRXyM2f-1666187859837)(img/image-20220924225659697.png)]
代码/任务分类:
同步任务
异步任务
不必等待当前代码结果, 直接继续向下执行
console.log(10);
let a = 5 + 2;
setTiemout(() => {
console.log('hello')
}, 10000)
console.log('ok')
计时器
定时器
fs读文件
ajax
事件绑定
特点: 都是在宿主环境, 都有回调函数接收结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7iT4q9lF-1666187859838)(img/image-20220924225705119.png)]
宏任务:
微任务:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-650J52jV-1666187859838)(img/image-20220924225714125.png)]
渲染: 浏览器运行html文件(js代码+ajax请求回来) 动态创建DOM+数据渲染页面
前端ajax -> 请求数据
后端-> 返回只是json数据 -> 数据接口地址
优点: 开发体验好, 效率高(前端任务比较多), 减轻了服务器端压力
缺点: 不利于SEO, 解决方案( Vue->SSR技术 )
概念: 在后端把数据+DOM标签拼接生成好. 页面标签返回给前端渲染
前端 -> 请求网页
后端 -> 网页所需要的所有标签数据填充完了
优点: 前端耗时少, 有利于SEO (搜索引擎排名) -百度搜索排名
缺点: 占用服务器资源多, 不利于前后端分离, 效率低
跨域:
网页打开时所在地址栏的地址和内嵌ajax请求的地址
协议/域名/端口号 有一个对应不上 就会跨域访问
浏览器默认不支持跨域的, 但是现代浏览器已经支持跨域资源共享(前提: 后端开启cors)
Cookie缺点: 遇到跨域问题很麻烦, 所以解决方案是用jwt
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f2jdjtio-1666187859839)(img/image-20220924225724588.png)]
jwt字符串是保存在前端的
之前cookie是保存在服务器端内存里
一大串字符串中间用.分隔开, 分为3段
Header部分
Payload(载体)部分-> 包含了用户的身份信息
Sign(签名加密)部分
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jV1lsIOZ-1666187859840)(img/image-20220924225734426.png)]
前端使用: 拿到Jwt字符串保存在LocalStorage/SessionStorage本地, 以后发请求的时候, 添加到请求头上, 拼接发给后台
后端使用:(了解)
需要自己随便定义一个秘钥在后端 (秘钥作用: 一些列的数学算法, 把原本的明文->加密后的字符)
a -> 7 -> 加密后 abcdefg (h)
a -> 5 -> 加密后 (f)
登录接口调用: 前端->调用登录接口, 传递账号密码->后端接收后判断生成jwt字符串(包含{username: ‘名字’} -> 返回给前端
获取用户信息接口调用: 前端要带上上一步jwt字符串在请求头里, 后端expressJwt解析, 挂载req.user, 返回给前端查看
有错误提示, 先看关键信息
再看哪个是自己的文件, 多少行代码引发的错误
// Regular
console.log('输入字符串');
// Interpolated
console.log('ssss%s','rive'); // %s 是第二个参数为值
// Styled
console.log('ssss%c','red'); // $c 是第二个参数是颜色和字体的变化
// warning!
console.warn('ss'); // 警告
// Error :|
console.error('Error') // 报错的信息
// Grouping together // 打印的分组
console.group();
console.log(333);
console.groupEnd();
// 1.DOM对象转换成jQuery对象,方法只有一种
var box = document.getElementById('box'); // 获取DOM对象
var jQueryObject = $(box); // 把DOM对象转换为 jQuery 对象
// 2.jQuery 对象转换为 DOM 对象有两种方法:
// 2.1 jQuery对象[索引值]
var domObject1 = $('div')[0]
// 2.2 jQuery对象.get(索引值)
var domObject2 = $('div').get(0)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ugA7Y6rw-1666187859840)(img/image-20220924225833181.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OIf5AnGW-1666187859840)(img/image-20220924225838410.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IOH1P4Et-1666187859841)(img/image-20220924225826272.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hOLRZmoH-1666187859841)(img/image-20220924225818041.png)]
// 1.添加类
$("div").addClass("current");
// 2.删除类
$("div").removeClass("current");
// 3.切换类
$("div").toggleClass("current");
// 1.参数只写属性名,则是返回属性值
var strColor = $(this).css('color');
// 2. 参数是属性名,属性值,逗号分隔,是设置一组样式,属性必须加引号,值如果是数字可以不用跟单位和引号
$(this).css(''color'', ''red'');
// 3. 参数可以是对象形式,方便设置多组样式。属性名和属性值用冒号隔开, 属性可以不用加引号
$(this).css({ "color":"white","font-size":"20px"});
自定义动画非常强大,通过参数的传递可以模拟以上所有动画,方法为:animate() ;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-07F2gvM8-1666187859841)(img/image-20220924225809748.png)]
<body>
<button>动起来</button>
<div></div>
<script>
$(function() {
$("button").click(function() {
$("div").animate({
left: 500,
top: 300,
opacity: .4,
width: 500
}, 500);
})
})
</script>
</body>
jQuery 常用属性操作有三种:prop() / attr() / data() ;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NeeYD9Dl-1666187859846)(img/image-20220924225802333.png)]
用户自己给元素添加的属性,我们称为自定义属性。 比如给 div 添加 index =“1”。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dMLqHzNB-1666187859846)(img/image-20220924225755994.png)]
2. $.each() 方法遍历元素 主要用于遍历数据,处理数据
$.each($("div"), function (i, ele) {
console.log(i);
console.log(ele);
});
遍历对象
$.each({
name: "andy",
age: 18
}, function (i, ele) {
console.log(i); // 输出的是 name age 属性名
console.log(ele); // 输出的是 andy 18 属性值
})
遍历数组
$.each(arr, function (i, ele) {
console.log(i);
console.log(ele);
})
jQuery方法操作元素的创建、添加、删除方法很多,则重点使用部分,如下:
<body>
<ul>
<li>原先的li</li>
</ul>
<div class="test">我是原先的div</div>
<script>
$(function() {
// 1. 创建元素
var li = $("<li>我是后来创建的li</li>");
// 2. 添加元素
// 2.1 内部添加
// $("ul").append(li); 内部添加并且放到内容的最后面
$("ul").prepend(li); // 内部添加并且放到内容的最前面
// 2.2 外部添加
var div = $("<div>我是后妈生的</div>");
// $(".test").after(div);
$(".test").before(div);
// 3. 删除元素
// $("ul").remove(); 可以删除匹配的元素 自杀
// $("ul").empty(); // 可以删除匹配的元素里面的子节点 孩子
$("ul").html(""); // 可以删除匹配的元素里面的子节点 孩子
})
</script>
</body>
jQuery 尺寸操作包括元素宽高的获取和设置,且不一样的API对应不一样的盒子模型。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-udAcgkpM-1666187859847)(img/image-20220924225747172.png)]
元素.tigger(事件)
元素.事件()
e.stopPropagation()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。