本文是在自己处理业务的一些总结,但是一直疲于整理,还是要不断的学习。本文含有一些JQ的内容,虽然说JQ在前端技术中有些过时,但不得不承认JQ在操作DOM上非常便利。
JQ常用
JQ操作元素节点
jQuery.parent(expr),找父亲节点,可以传入expr进行过滤,比如 ( " s p a n " ) . p a r e n t ( ) 或 者 ("span").parent()或者 ("span").parent()或者(“span”).parent(".class")
jQuery.parents(expr),类似于jQuery.parents(expr),但是是查找所有祖先元素,不限于父元素
jQuery.children(expr),返回所有子节点,这个方法只会返回直接的孩子节点,不会返回所有的子孙节点
jQuery.contents(),返回下面的所有内容,包括节点和文本。这个方法和children()的区别就在于,包括空白文本,也会被作为一个jQuery对象返回,children()则只会返回节点
jQuery.prev(),返回上一个兄弟节点,不是所有的兄弟节点
jQuery.prevAll(),返回所有之前的兄弟节点
jQuery.next(),返回下一个兄弟节点,不是所有的兄弟节点
jQuery.nextAll(),返回所有之后的兄弟节点
jQuery.siblings(),返回兄弟姐妹节点,不分前后
jQuery.find(expr),跟jQuery.filter(expr)完全不一样:
jQuery.filter(),是从初始的jQuery对象集合中筛选出一部分,而
jQuery.find(),的返回结果,不会有初始集合中的内容,比如 ( " p " ) . f i n d ( " s p a n " ) , 是 从 < p > 元 素 开 始 找 < s p a n > , 等 同 于 ("p").find("span"),是从<p>元素开始找<span>,等同于 ("p").find("span"),是从<p>元素开始找<span>,等同于(“p span”)
jq 对象数组转为js普通数组
$(item).find("p").toArray()
数组转换为对象
let title = initArrary.shift()
let itemBank = {title}
initArrary.map((curr,index)=>{
itemBank[String.fromCharCode(index + 65)] = curr.innerText
})
jq 对象遍历
注意:each方法和js自带的forEach()中使用return 无效!
在循环体内return false表示跳出each函数, return true表示跳出这一次循环。
$("p").each((index,item)=>{
})
JS forEach方法currentValue和index位置不同
array.forEach(function(currentValue, index, arr), thisValue)
thisValue:可选。传递给函数的值一般用 “this” 值。 如果这个参数为空, “undefined” 会传递给 “this” 值
eq方法
eq方法返回JQ数组对象数组某个下标的JQ对象
eg:
let a = $("p").eq(0)
console.log(a)
console.log(a.attr("id"))
箭头函数
当箭头函数箭头后面是简单操作时,直接去掉函数体“{ }”,这样可以不使用return 就能会返回值。
这里也有个坑!当我使用fetch请求完数据的时候,就因为这个问题,导致我一直找不到问题!
问题重现:
fetch('http://localhost:8080/quesBank/select', {
'method': 'POST',
'body': JSON.stringify(['测试而已']),
"headers": {
'Content-Type': 'application/json'
}
}).then(res => { /***return**/ res.json() }).then(res => { console.log(res.data) })
fetch请求后获取到数据,经过then
回调,箭头函数,有了函数体包裹,必须有return
,如果注释掉return
,那么后面将一直获取不到数据
所以,每一个细节,都务必重视。
splice 和slice的区别
splice():该方法向或者从数组中添加或者删除项目,返回被删除的项。(该方法会改变原数组)
splice(index,howmany,item1,…itemX)
- index参数:必须,整数,规定添加或者删除的位置,使用负数,从数组尾部规定位置。
- howmany参数:必须,要删除的数量,如果为0,则不删除项目。
- tem1,…itemX参数:可选,向数组添加的新项目。
slice(start,end):方法可从已有数组中返回选定的元素,返回一个新数组,包含从start到end(不包含该元素)的数组元素。该方法不会改变原数组,而是返回一个选定的子数组
- start参数:必须,规定从何处开始选取,如果为负数,规定从数组尾部算起的位置,-1是指最后一个元素。
- end参数:可选(如果该参数没有指定,那么切分的数组包含从start倒数组结束的所有元素,如果这个参数为负数,那么规定是从数组尾部开始算起的元素)。
JQ解析html字符串
fetch(`http://www.ehuixue.cn/index/study/workinclass?examid=${testId}`, {
}).then(res => res.text()).then(res=>{
let html = $(res).find("p")
})
JQ 替换dom
可能再某种情况下,我们需要替换dom内容。比如说:现在我爬取某题库的时候,例如某网站的题目都是被p标签包裹且有class叫title,那么可以直接使用获取
let titles = $("p[class*='title']")
title.each((index,item)=>{
console.log(item.text())
})
但是等见过的题目形式越来越多,你会发现没有那么简单,有些题目有图片,
比如是这样的
<p class='title'>NIO和BIO的区别,当并发数量激增,占比系统资源如图:<img src="http://demo.raven520.top/pic/2510222.png"/>请回答xxx</p>
直接text()题目是不全的!那如何解决?
直接换掉p标签里面的img即可!把img里的src最终的图片名提取出来就好,这个名字一般是不会变得。
let titles = $("p[class*='title']")
tranformDomImgSrc(titles)
title.each((index,item)=>{
console.log(item.text())
})
function tranformDomImgSrc(obj) {
$(obj).find("img").each((index, item) => {
let context = $(item).attr('src').match('.*/(.*)')[1]
console.log(`[[${context}]]`)
//添加图片地址,为了区别题目内容,图片地址由 [[]]包裹
item.after(`[[${context}]]`)
// 删除图片节点
item.remove()
})
}
匹配带有换行的内容
例如,提取html里面的内容:
"<p>hello\nraven</p>".match('<[A-Za-z]{1,4}.*>(.*)</[A-Za-z]{1,4}>')
运行完上述代码,发下根被提取不到!那该怎么办,其实 .
在正则是不匹配换行的,这也是被坑的一点,我之前一直以为.
是匹配任何字符的。事实上,.
匹配的是除了换行符之外的任意字符,我们应该将上面的代码替换成:
"<p>hello\nraven</p>".match('<[A-Za-z]{1,4}.*>([\\s\\S.]*)</[A-Za-z]{1,4}>')
异步
当要处理一个列表的请求,想等请求都结束后,再进行后续的事情,我首先想到这么去实现,但是人算不如天算,这样是不行的。百思不得其解,why? 我想要的是每一个处理完毕,再进行后面的内容。
forEach
默认是同步的,回调函数加了异步关键词后,也就是说他不会等待每一次循环执行完才开启下一次,而是异步触发每一项,结束完里面执行后面的代码。所以导致了,console.log('视频已处理完毕!')
先输出。至于深究原因,应该深入学习 javascript的任务队列机制。
courses.forEach(async (val, index) => {
await postData(val)
console.log(val + "处理完毕!");
})
console.log('视频已处理完毕!')
当要处理一个列表的请求,想等请求都结束后,再进行后续的事情,那么可以将列表调用map,对每一项都封装成一个Promise对象,然后调用Promise.all()即可。
即:
Promise.all(courses.map(e => {
// 返回Promise对象
return postData(e)
})).then(res => {
// res是每一个请求返回的内容,组装成列表,传入回调参数
console.log(res)
console.log('视频任务已处理完成')
})
有时候想实现一个功能,经过特定秒数再实行一个请求,直到请求列表暂无请求;
// 请求间隔时间
let time = 1000;
// 请求列表
let taskList = ['10086','10087']
(function start(){
startTask(taskList.shift())
})()
function startTask(testId){
if(testId == undefined){
console.log('请求列表为空,请求完毕!')
return
}
setTimeout(async () => {
console.log(`当前处理试卷id:${testId}`)
// 获取题目
let itemBanks = await getTestData(testId)
// 获取题目答案
let answers = await getAnswers(itemBanks)
// 提交测试
await submitTest(answers,testId)
console.log(`试卷id:${testId}已提交`)
startTask(taskList.shift())
}, time);
}