first commit

This commit is contained in:
编码猿
2024-09-27 02:06:13 +08:00
commit 852d94fbb9
36760 changed files with 3274413 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
class Ajax{
constructor() {
this.ajax = new XMLHttpRequest ()
}
/**
* * @param{*}params
* {
* 请求的网址 url:"",
*
* 请求的参数 data:{
* (对象) id:1,
* page:2
* },
*
* 请求头 header:{
* (对象) 'Content-Type':'application/json;charset=UTF-8'
* },
*
* 请求成功的回调 success:(res)=>{},
* (方法)
*
* 请求失败的回调 erro:(err)=>{不同地方的错误提示也不一样,可以不用但必须要有},
* }
*/
get(params){
ajax.open("GET","http://localhost")
}
post(){}
}

View File

@@ -0,0 +1,142 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>promise</title>
</head>
<body>
<!-- promise是es6的时候才更新出来的:promise本身是同步的,但调用promise的过程是异步的(then通过回调拿结果) -->
<!-- Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理且更强大。
它最早由社区提出并实现,ES6将其写进了语言标准,统一了用法,并原生提供了Promise对象。
JS执行——Promise: Pending状态(进行中)
Fulfilled状态(已成功)
Rejected状态(已失败)
一旦状态改变就不会再变 (两种状态改变:成功或失败)
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。
resolve:将Promise对象状态由“未完成”变为“成功”,即Pending -> Fulfilled,在异步操作成功时调用,并将异步操作的结果作为参数传递出去
reject:将Promise对象状态由“未完成”变为“失败”,即Pending -> Rejected,在异步操作失败时调用,并将异步操作的结果作为参数传递出去。
Promise实例生成后,可用then方法分别指定两种状态回调参数。then 方法可以接受两个回调函数作为参数:
在Promise新建后会立即执行,然后,then方法指定的回调函数将在当前脚本所有同步任务执行完后才会执行。
then在Promise对象状态改为Resolved时调用 (必选);Promise对象状态改为Rejected时调用 (可选)
拓展 async/await
async:异步——————————async 函数必定返回 Promise,我们把所有返回 Promise 的函数都可以认为是异步函数。
特点体现在以下四点: 内置执行器
更好的语义
更广的适用性
返回值是 Promise
await:等待——————————await命令后面一般是一个 Promise 对象,返回该对象的结果(利用await来等待一个Promise。)如果不是 Promise 对象,就直接返回对应的值。
另一种情况是,await命令后面是一个thenable对象(即定义then方法的对象),那么await会将其等同于 Promise 对象。
Promise优缺点:
优点 缺点
解决回调 无法监测进行状态
链式调用 新建立即执行且无法取消
减少嵌套 内部错误无法抛出 -->
<!-- 链式调用:当一个方法执行结束以后直接把返回值用于下一个方法
例:
num = 0;
test(){
this.num += 1
return this.num
}
test2(){
this.num += 100
return this.num
}
按理说test() 和 test2() 分别调用两次 ,console.log(ajax.test2())即1+100=101;
num = 0;
test(){
this.num += 1
return this (返回了一个this指向)
}
test2(){
this.num += 100
return this.num
}
链式调用写法:var result = ajax.test().test2() console.log(result)即可
因此,一定要确认this指向的正确性!!! -->
</body>
<script src="./ajax promise.js"></script>
<!-- promise异步方案 -->
<!-- <script>
console.log(1);
ajax.get({
url:"http://localhost",
data:{
id:1,
page:2
},
header:{
'Content-Type':'application/json;charset=UTF-8'
}
}).then(res => {
console.log("2",res);
}).catch(err => {
console.log(err);
})
console.log(3);
</script> -->
<!-- promise同步方案:将promise的异步调用转为同步调用 -->
<script>
// console.log(1);
ajax.get({
url:"http://localhost",
data:{
id:1,
page:2
},
header:{
'Content-Type':'application/json;charset=UTF-8'
}
}).then(res => {
console.log("2",res);
}).catch(err => {
console.log(err);
})
// console.log(3);
// async写在最近的方法名前面,和await配套使用
var a = async () => {
console.log(1);
var res = await ajax.get({
url:"http://localhost",
data:{
id:1,
page:2
},
header:{
'Content-Type':'application/json;charset=UTF-8'
}
})
console.log("2",res);
console.log(3);
}
console.log(4);
// a外部方法调用是异步的,a内部是同步的,先跑完异步再来跑同步
a();
console.log(5);
// 结果:4 1 5 23
// 原因如下:首先从上往下同步执行4,到a(),执行了1,发现await内部等待,外部就跑去执行5,最后等待得到2和3
</script>
</html>

View File

@@ -0,0 +1,38 @@
class Ajax{
constructor() {
this.ajax = new XMLHttpRequest();
}
get(params){ //(success,error)
return new Promise((resolve,reject) => {
var str = ""
for (const key in params.data) {
str += `&${key}=${params.data[key]}`
}
str = str.replace("&", "?")
this.ajax.open("GET", `${params.url}${str}`)
this.ajax.send()
this.readystatechange(resolve, reject)
})
}
post() { }
readystatechange(resolve, reject) {
this.ajax.onreadystatechange = () => {
if (this.ajax.readyState == 4) {
if (this.ajax.status == 200) {
var data = JSON.parse(this.ajax.responseText)
// console.log(data);
resolve(data)
} else {
reject(this.ajax)
}
}
}
}
}
var ajax = new Ajax();

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- ajax请求代码的封装一般分为三层: config 配置层 serve 请求中间层 ajax 封装层 -->
顺序: 配置 ————> 工具函数 ————>ajax ————> sever ————> page
</body>
<script src="./ajax回调函数.js"></script>
<script>
// 异步转同步 回调函数callback微信小程序常使用
ajax.get({
url:"http://localhost",
data:{
id:1,
page:2
},
header:{
'Content-Type':'application/json;charset=UTF-8'
},
success:(res)=>{
console.log(res);
},
error:(err)=>{},
})
</script>
</html>

View File

@@ -0,0 +1,75 @@
class Ajax {
constructor() {
this.ajax = new XMLHttpRequest();
// 请求监听全局只运行一次,是异步的,有需要(先send再监听)就运行,不需要就待机
// 监听放这里参数很难回调出去,原因是get和readystate是相互独立(局部)的
// this.readystatechange();
// 局部变全局
this.success = null
}
// java中“@”大多代表注解的意思。那么@param是用来在DAO层中声明参数的注解方式。
// @ param标签可以归档方法或构造器的某个单一参数,或者归档类、接口以及泛型方法的类型参数。
// 在使用@ param标签时,我们应该针对方法的每一个参数都使用一个该标签。
// 每个段落的第一个词会被当作参数名,而余下的部分则会被当作是对它的描述。
/**
* 接收多个参数,所以封装一个对象直接接收对象
*
* @param{*}params
* {
* 请求的网址 url:"",
*
* 请求的参数 data:{
* (对象) id:1,
* page:2
* },
*
* 请求头 header:{
* (对象) 'Content-Type':'application/json;charset=UTF-8'
* },
*
* 请求成功的回调 success:(res)=>{},
* (方法)
*
* 请求失败的回调 error:(err)=>{不同地方的错误提示也不一样,可以不用但必须要有},
* }
*/
get(params) {
this.success = params.success
var str = ""
// get的传参形式是url+?key=value,但我们的参数是对象,所以要转换(字符串拼接和符号替换)
// 对对象遍历,拿到值
// this.ajax.open("GET","http://localhost")
for (const key in params.data) {
// console.log("key",key);
str += `&${key}=${params.data[key]}`
}
str = str.replace("&", "?")
this.ajax.open("GET", `${params.url}${str}`)
// console.log(`${params.url}${str}`);
this.ajax.send();//send必须要有状态监听,多个共用一个状态监听即可
// 监听放在这里用可以直接把后端的参数回调出去
this.readystatechange(params.success, params.error)
}
post() { }
readystatechange(success,error) {
this.ajax.onreadystatechange = () => {
// console.log(this.ajax.readyState);
if (this.ajax.readyState == 4) {
// 后端给我们的数据保存在response和responseText里
if (this.ajax.status == 200) {
var data = JSON.parse(this.ajax.responseText)
// console.log(date);
success(data)
this.success(data)
} else {
error(this.ajax)
}
}
}
}
}
var ajax = new Ajax();

View File

@@ -0,0 +1,148 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
</ul>
<!-- <form action="">
<input type="text" name="id">
</form> -->
<!-- ajax如何调试(接口不通)控制台无数据/渲染页面不进行:
解决方案——————网络——>1 Fetch/XHR 请求状态是否为200——>2 载荷 查询参数是否传递成功——>3 预览 后端是否返回相关数据
都没问题,查找自己的代码是否有错。 -->
<!-- ajax:前后端交互的工具(无刷新的数据交互方式) -->
<!-- 数据格式:json格式=对象object+数组array (曾经用的xml——标签套标签) -->
<!-- 请求<————————>响应 -->
<!-- http(超文本传输协议)请求:
1 请求头:存放客户端亲请求基本信息
2 请求体:
3 响应头:存放服务器基被请求本信息
4 请求状态码: 200请求成功 202请求接收到但还未处理完成 204成功处理请求但不需返回信息
404找不到对应资源或请求地址 406无法响应 408请求发送超时
500 服务器内部错误无法完成请求
5 请求方式: (rsa超级加密)
① GET 要
传参在网址后面添加(?key=vaule&key=vaule...) 即:"http://127.0.0.1/index.php?id=1"
简单好用,但不适合提交一些敏感数据(账户密码等)
② POST 给
传参放在请求体里面ajax.send(参数)
请求头种类:application/json(最常用)
application/x-www-form-urlencoded form表单
multipart/form-data 上传文件
get和post的区别:参数:get———— url传递 ;post————— requestbody传递 ;
长度:get———— url长度有限(实际上是浏览器和服务器对url的限制) ;post————— 没有 ;
安全:get———— 将参数直接暴露在url上所以不能产地敏感信息 ;post————— 没有 ;
编码:get———— 只能进行url编码 ;post————— 多种 ;
速度:get———— data都在url里,所以速度较快 ;post————— ;
缓存:get———— 可以被浏览器缓存 ;post————— 不会 ;
数据包:get———— http将header和data一并发送所以只残生一个数据包服务器响应200 ;post————— 浏览器先header服务器响应100再data响应200 ;
本质:总得来说没有差别,底层都是tcp/ip协议,但由于http的规定和浏览器的限制,导致使用过程中出现差别。
③ PUT 更新 请求体
④ DELETE 删除 请求体
⑤ OPTIONS 预检测
-->
<!-- 跨域 解决 浏览器 同源策略(协议http/域名 中间内容 /端口 默认:http80——https443) -->
<!-- 三种解决方案: 1 cors 后端设置请求头 允许跨域
(只能发get请求)2 jsonp 把 ajax请求 伪装成 js文件请求,绕过 同源策略 达到 发送请求 的目的,通过 回调函数 拿回数据
3 服务器代理 a前端————>(http://127.0.0.1/my(自己后端).php) a后端 请求内容:($data = file_get_contents("http://127.0.0.1/index(别人后端).php"); echo $data()得到参数————>b后端 -->
<!-- http的请求状态码大于ajax的请求状态 -->
<!-- console.log(ajax): readyState (存储的ajax的状态(0——4),当readyState属性改变时,就会调用该函数)
0_请求未初始化 1_服务器连接已建立 2_请求已接收 3_请求处理中 4_请求已完成,且相应已就绪 -->
</body>
<script>
// 步骤:
// 1 创建一个新的ajax对象
// 2 配置需要访问的后端地址和请求方式
// 3 发送请求(传参)并监听请求
// 1 创建一个新的ajax对象
// XMLHttpRequest 和 fetch(es6) 都是ajax的请求方式
var ajax = new XMLHttpRequest()
// 2 配置需要访问的后端地址和请求方式 ajax.open("请求方式","地址")
ajax.open("GET", "http://localhost?id=1")
// 3 发送请求(传参)并监听请求
ajax.send()
// 例:post传参
// ajax.open("POST","http://localhost")
// var params = {
// id : 1
// }//"对象"
// 手动更改请求头
// ajax.setRequestHeader('Content-Type','application/json;charset=UTF-8')
// ajax.send(JSON.stringify(params)//“对象转字符串”)
// 例:form表单
// var form = new FormData();
// form.append("username",1)
//var a = "id=1"
// ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset=UTF-8')
// ajax.send(a)
ajax.onreadystatechange = function () {
// console.log(ajax);
if (ajax.readyState == 4) {
// 后端给我们的数据保存在response和responseText里,但浏览器在网络传输过程中只能以 字符串 的形式。
// (询问数据类型可用typeof),因此需要手动转变一下: 字符串————对象 :JSON.parse
// 对象————字符串 :JSON.stringify
if (this.ajax.ststus == 200) {
var data = JSON.parse(ajax.responseText)
console.log(data);
date.result.forEach(v => {
document.querySelector("ul").innerHTML += `<li>${v.title}</li>`
});
}
} else {
alert("网络请求失败")
}
}
// jsonp跨域
// 前端:
// function getDate(res){
// console.log(res);
// }
// <script src="http://localhost?cb=getDate"></script>
<!-- 后端:
$cb = $_GET['getDate'];
echo json_encode($arr);
getDate(参数)
echo $cb."(".json_encode($arr).")"; -->
</script>
</html>

View File

@@ -0,0 +1,33 @@
/* 清除浏览器默认样式 */
body,h1,h2,h3,h4,h5,h6,ul,li,p {
margin: 0;
padding: 0;
}
body {
font-size: 0;
}
li {
list-style: none;
}
input {
border: none;
outline: none;
padding: 0;
}
a {
text-decoration: none;
color: #333;
}
::-webkit-scrollbar {
width: 0;
height: 0;
}
img {
width: 100%;
}

View File

@@ -0,0 +1,21 @@
.title {
padding: 0 15px;
font-size: 16px;
font-weight: 400;
padding-top: 20px;
margin-bottom: 10px;
}
.menu_list {
padding: 0 15px;
display: flex;
flex-wrap: wrap;
}
.menu_list li {
padding: 3px 10px;
font-size: 14px;
background: var(--themeColor);
margin-right: 10px;
color: #fff;
border-radius: 20px;
margin-bottom: 7px;
}

View File

@@ -0,0 +1,151 @@
.header {
position: fixed;
width: 100%;
height: 1.6rem;
top: 0;
left: 0;
right: 0;
z-index: 99;
}
.header .header_logo {
background: var(--themeColor);
height: 0.88rem;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 0.3rem;
}
.header .header_logo i {
font-size: 0.45rem;
color: var(--whiteColor);
}
.header .header_logo .search {
flex: 1;
background: var(--whiteColor);
height: 0.6rem;
border-radius: 0.6rem;
margin-left: 10px;
margin-right: 10px;
display: flex;
align-items: center;
}
.header .header_logo .search span {
font-size: var(--fontSize12);
color: var(--textColor);
}
.header .header_logo .search i {
color: var(--textColor) !important;
font-size: 0.26rem !important;
margin-right: 0.1rem;
padding-top: 0.02rem;
margin-left: 0.26rem;
}
.header_menu {
height: 0.72rem;
display: flex;
align-items: center;
background: #fe7fa2;
}
.header_menu a {
color: #fff;
text-decoration: none;
width: 0.8rem;
height: 0.72rem;
text-align: center;
line-height: 0.72rem;
}
.header_menu ul {
display: flex;
flex: 1;
overflow-x: scroll;
padding-left: 0.3rem;
}
.header_menu ul li {
font-size: 0.26rem;
margin-right: 0.26rem;
color: #d3d2d2;
flex-shrink: 0;
}
.header_menu ul .active {
color: var(--whiteColor) !important;
}
.content {
margin-top: 1.6rem;
margin-bottom: 1rem;
}
.swiper {
width: 100%;
}
/* 固定contant可视区域,超出部分则滚动 */
.swiper-slide {
height: calc(100vh - 1.6rem - 1rem);
overflow-y: scroll;
}
.list {
padding: 10px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.list .item {
width: 48%;
flex-shrink: 0;
margin-bottom: 0.24rem;
}
.list .item_top {
position: relative;
}
.list .item_top img {}
.list .item_top span {
bottom: 0.1rem;
right: 0.16rem;
position: absolute;
font-size: 0.24rem;
background: var(--themeColor);
color: #fff;
padding: 0.02rem 0.12rem;
border-radius: 0.16rem;
}
.list .item_text {}
.list .item_text .title {
font-size: 0.34rem;
font-weight: 400;
margin-top: 0.2rem;
}
.list .item_text .model {
font-size: 0.28rem;
color: #bdb7b7;
}
.list .item_text .source {
font-size: 0.28rem;
color: #bdb7b7;
}
.list .item_tag {
margin-top: 0.1rem;
display: flex;
flex-wrap: wrap;
}
.list .item_tag .tage_item {
font-size: 0.24rem;
flex-shrink: 0;
padding: 0.08rem 0.18rem;
background: var(--themeColor);
margin-right: 0.1rem;
color: #fff;
border-radius: 0.2rem;
margin-bottom: 0.1rem;
}

View File

@@ -0,0 +1,54 @@
.hot{
height: calc(100vh - 0.9rem - 1rem);
overflow-y: scroll;
}
.hot_model{
padding-top: 30px;
font-size: 18px;
margin-left: 10px;
}
.hot_modelAll{
display: flex;
flex-wrap: wrap;
padding: 4px 7px;
box-sizing: border-box;
}
.model{
width: 60px;
margin: 15px;
}
.model a{}
.model .model_top{
position: relative;
}
.model .model_top img{
width: 100%;
border-radius: 50%;
}
.model .model_top span{
color: var(--whiteColor);
font-size: 10px;
height: 18px;
width: 40px;
background: #3333338f;
position: absolute;
text-align: center;
line-height: 18px;
border-radius: 10px;
bottom: -2px;
left: 10px;
transform: scale(0.8);
}
.model_bottom{
color: var(--textColor);
font-size: 10px;
transform: scale(0.8);
margin-top: 8px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

View File

@@ -0,0 +1,80 @@
/* 公共使用率高的css代码 */
:root {
--themeColor: #fb7299;
--whiteColor: #fff;
--blackColor: #000;
--textColor: #999;
--fontSize12: 0.24rem;
--fontSize13: 0.26rem;
--fontSize14: 0.28rem;
--fontSize15: 0.3rem;
--fontSize16: 0.32rem;
--fontSize17: 0.34rem;
--fontSize18: 0.36rem;
--fontSize19: 0.38rem;
--fontSize20: 0.4rem;
--fontSize21: 0.42rem;
}
.ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.footer {
justify-content: space-around;
display: flex;
height: 1rem;
align-items: center;
position: fixed;
border-top: 0.02rem solid #e2e2e2;
width: 100%;
bottom: 0;
left: 0;
right: 0;
z-index: 99;
background: var(--whiteColor);
}
.footer li {
text-align: center;
}
.footer li p {
font-size: 0.24rem;
margin-top: 0.04rem;
}
.footer .active a {
color: var(--themeColor);
}
.pub_header {
height: .9rem;
width: 100%;
position: fixed;
left: 0;
top: 0;
right: 0;
background: var(--themeColor);
color: #fff;
display: flex;
align-items: center;
padding: 0 10px;
box-sizing: border-box;
}
.pub_header i {
font-size: .4rem;
}
.pub_header .text {
font-size: .36rem;
flex: 1;
margin-left: .28rem;
}
.content {
margin-top: .9rem;
}

View File

@@ -0,0 +1,75 @@
class Ajax{
constructor(){
// 1 创建一个新的ajax对象
this.ajax = new XMLHttpRequest();
}
// 2 配置需要访问的后端地址和请求方式
// get请求
get(params){
return new Promise((success,error) =>{
//传参数?key=value格式
var str = ""
for (const key in params.data) {
str += `&${key}=${params.data[key]}`
}
str = str.replace("&", "?")
//请求基地址+接口+参数
this.ajax.open("GET",`${config.checkUrl()}${params.url}${str}`)
// 3 发送请求
this.ajax.send()
//并监听请求
this.readystatechange(success,error)
})
}
post(){}
//状态监听
readystatechange(success,error){
//状态改变就会触发
this.ajax.onreadystatechange = () => {
//ajax请求状态
if(this.ajax.readyState == 4){
//http请求状态
if(this.ajax.status == 200){
//JSON.parse一般用于将JSON字符串转化为JSON对象
var data = JSON.parse(this.ajax.responseText)
//成功走接口状态判断
success(this.checkStatus(data))
}else{
error(this.ajax)
}
}
}
}
//接口状态码判断,程序员随意定义
//所有接口都要走状态码判断,处理方式不一样的都要写,一样的写一个就可以了
checkStatus(data){
switch (data.status) {
case 200:
return data.result
break;
case 404:
//msg接口状态码解释
alert(data.msg);
//抛出一个错误,throw(打断浏览器代码运行) new error
throw new Error(data.msg)
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,48 @@
var config = {
//不同阶段 不同使用地址
devBaseUrl: 'http://127.0.0.1:3000/api/json', // 开发阶段
testBaseUrl: 'http://127.0.0.1:3000/api/test', // 测试阶段
prodBaseUrl: 'http://192.168.31.100:3000/api/json', // 上线阶段
// 选择阶段循环判断使用不同地址
stage: 'dev', // dev test prod
// 总接口汇集
apiList:{
index: '/index',
//详情接口
info: '/info',
//分类列表
classList: '/class',
//分类详情列表
classListArr: '/classList',
model:`/allModel`
},
// 页面底部信息地址储存
footerList:[
{ title: '首页', icon: 'icon-home', url: 'index.html' },
{ title: '机构', icon: 'icon-jigou', url: 'mechanism.html' },
{ title: '模特', icon: 'icon-me', url: 'model.html' },
{ title: '我的', icon: 'icon-wo', url: 'my.html' },
],
//循环判断添加请求基地址
checkUrl: function () {
switch (this.stage) {
case "dev":
return this.devBaseUrl
break;
case "test":
return this.testBaseUrl
break;
case "prod":
return this.prodBaseUrl
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,112 @@
class Edit {
constructor() {
header("分类编辑")
//将存储的数据提取出来使用 JSON.parse字符串转对象
this.principal = JSON.parse(localStorage.getItem("principal"))
this.additional = JSON.parse(localStorage.getItem("additional"))
this.renderPrincipal()
this.renderAdditional()
}
//渲染已选菜单
renderPrincipal() {
//生成网页
this.principal.forEach(v => {
$(".principal").html(`
<li>${v.title}</li>
`)
});
//绑定事件
this.PrincipalClick()
}
//已选菜单点击事件
PrincipalClick() {
var self = this;
//先绑定事件
click(_(".principal li"), function () {
// 首先去除首页,不可点击不可选择
if (this.index != 0) {
console.log("index: ",this.index);
// 深拷贝
// var oldArr = JSON.parse(JSON.stringify(self.principal));
//删除已选
//c先存储在a additional,再删掉b principal里面的c
self.additional.push(self.principal[this.index])
//已选里被删除的项 splice删除数组里的某元素
var deleteAItem = self.principal.splice(this.index, 1)
// 然后将修改后的内容,更新保存在本地 JSON.stringify对象转字符串
localStorage.setItem("principal", JSON.stringify(self.principal))
localStorage.setItem("additional", JSON.stringify(self.additional))
//可选追加删除项
$(".additional").html(`
<li>${deleteAItem[0].title}</li>
`)
//并为追加整体 重新绑定点击事件
self.AdditionalClick()
//已选去除删除项
$(".principal").removeChild(this)
//并为删除整体 重新绑定点击事件
self.PrincipalClick()
}
})
}
//渲染可选菜单
renderAdditional() {
//生成网页
this.additional.forEach(v => {
$(".additional").html(`
<li>${v.title}</li>
`)
});
//绑定事件
this.AdditionalClick()
}
//可选菜单点击事件
AdditionalClick() {
var self = this;
click(_(".additional li"), function () {
//已选追加
//c先存储在b,再删掉a里面的c
self.principal.push(self.additional[this.index])
//可选里的被删除项
var deleteAItem = self.additional.splice(this.index, 1)
// 然后将修改后的内容,更新保存在本地 JSON.stringify对象转字符串
localStorage.setItem("principal", JSON.stringify(self.principal))
localStorage.setItem("additional", JSON.stringify(self.additional))
// 已选追加删除项
$(".principal").html(`
<li>${deleteAItem[0].title}</li>
`)
//重新绑定点击事件
self.PrincipalClick();
//可选移除删除项
$(".additional").removeChild(this)
//重新绑定点击事件
self.AdditionalClick();
})
}
}
new Edit()

View File

@@ -0,0 +1,178 @@
class Index{
constructor(){
this.index = 0;
this.principal = []
//网页重新渲染innerhtml会导致之前绑定的事件解绑
footer();
this.getClassList()
}
//菜单列表
async getClassList(){
var that = this;
var res = await indexServe.classList();
// console.log(res);
this.principal = res.principal
// 如果本地没有储存数据,则发出请求并进行存储
if (localStorage.getItem("principal") == null) {
var res = await indexServe.classList();
this.principal = res.principal
//JSON.stringify转为字符串 principal固定菜单 additional可选菜单
localStorage.setItem("principal", JSON.stringify(this.principal))
localStorage.setItem("additional", JSON.stringify(res.additional))
} else {
// 有数据则提取出来
this.principal = JSON.parse(localStorage.getItem("principal"))
}
res.principal.forEach((v, i) => {
$(".header_menu ul").html(
` <li class="${i == 0 ? 'active' : ''}">${v.title}</li>`
)
$(".page_wrapper").html(
`<div class="swiper-slide">
<div class="list">
</div>
</div>`
);
//绑定滑动事件并判断是否滑动到底部,是否需要追加数据
_(".swiper-wrapper .swiper-slide").forEach(v => {
v.onscroll = () => {
const {clientHeight, scrollHeight, scrollTop} = v;
const distance = scrollHeight- scrollTop - clientHeight;
console.log(clientHeight, scrollHeight, scrollTop, distance);
//预加载阈值(提前加载)常在30~50之间
if(distance <= 10) {
// 首页
console.log("滚动到底部...");
if (this.index == 0) {
this.getIndex()
} else {
this.principal[this.index].page += 1
if (this.principal[this.index].page <= this.principal[this.index].total_page) {
//传一个more区别于默认的click点击事件
this.getClassListArr("more")
} else {
console.log("已经没有数据了!!!");
}
}
}
}
})
})
//箭头函数会解绑this指向,所以不能用
click(_(".header_menu ul li"), function () {
that.changeActive(this.index)
})
this.getIndex()
this.initPage()
}
//分类详情列表
//接收参数 默认点击事件
async getClassListArr(type = "click") {
//将传参方式封装起来,需要的地方直接调用即可
var getData = async () => {
var res = await indexServe.classListArr({
page: this.principal[this.index].page,
id: this.principal[this.index].id
});
//请求存储总页数详情
this.principal[this.index].total_page = res.total_page
//总内容=旧内容+新追加
this.principal[this.index].content = [
...this.principal[this.index].content,
...res.data
];
item(
//数组加下标
_(".swiper-slide .list")[this.index],
// this.principal[this.index].content
res.data
)
}
//当是点击事件时执行
if (type == "click") {
if (this.principal[this.index].id != -1) {
//数组为空请求数据(避免重复请求的问题出现)
if (this.principal[this.index].content.length == 0) {
getData()
}
}
} else {
getData()
}
}
// 更改激活态
changeActive(index) {
//最新下标保存到全局
this.index = index
_(".header_menu ul li").forEach(v => v.remove("active"))
_(".header_menu ul li")[index].add("active")
//slideTo滑向(下标)
this.mySwiper.slideTo(index)
}
//请求数据首页接口内容
//扩展运算符(...)是ES6的语法,用于取出参数对象的所有可遍历属性,然后拷贝到当前对象之中。
async getIndex() {
var res = await indexServe.index();
console.log('this.principal[this.index].content',this.principal,this.index);
this.principal[this.index].content = [
...this.principal[this.index].content,
...res.list
];
item(_(".swiper-slide .list")[this.index], res.list)
}
//滑动
initPage() {
var that = this;
// this.name在当前类里面定义一个全局变量
this.mySwiper = new Swiper('.swiper-container', {
direction: 'horizontal',
//监听滑动是否结束,结束取的其下标this.activeIndex
on:{
slideNextTransitionEnd: function() {
that.changeActive(this.activeIndex)
that.getClassListArr()
},
},
})
}
}
new Index()

View File

@@ -0,0 +1,91 @@
class Info {
constructor() {
//默认没收藏
this.isLike = false
this.Storage = []
this.indexOfStorage()
//参数= 标题 + 图标(标签)
//判断是否收藏进行相关图标更改
header("详情", `<i class="iconfont ${ this.isLike ? 'icon-aixin' : 'icon-xin' } xin"></i>`)
this.getInfo();
this.clickXin()
}
async getInfo() {
// console.log("res: ", res);
var res = await indexServe.info({
//利用query方法取得地址栏参数
id: query("id"),
quantity: query("total")
});
//循环插入图片地址
res.forEach(v => {
$(".content").html(`<img src="${v}" alt="">`)
});
// console.log("res: ", res);
}
// 执行删除元素
indexOfStorage(){
// 获取本地like数据,判断是否有值,有则以对象形式取出来,没有则依旧为[]
this.Storage = localStorage.getItem("like")? JSON.parse(localStorage.getItem("like")) : []
//为空不执行,直接return
if(this.Storage.length == 0){
return;
}
//不为-1则有值
if(this.Storage.indexOf(query("id")) != -1){
// 默认收藏
this.isLike = true
//this.Storage.indexOf(query("id"))包含则返回query("id")的下标
//splice(下标,个数)删除数组里的某个元素
this.Storage.splice( this.Storage.indexOf(query("id")) ,1)
console.log('this.Storage',this.Storage);
//删除后进行重新存储
localStorage.setItem('like',JSON.stringify(this.Storage))
}
}
//给图标绑定点击事件
clickXin() {
var that = this
// console.log('_(".iconfont .icon-xin"',_(".icon-xin"));
click(_(".xin"), function () {
//收藏
//this就是_(".xin")
// indexOf可以查找字符串值,有则返回下标,没有则返回-1
if(this.className.indexOf(("icon-xin")) != -1){
//localStorage.setItem将数据存储到本地(传输形式只有字符串),JSON.stringify将对象转为字符串
//收藏存储到本地,将id存进去,因为可能会有多个,所以是数组。
//。。。追加进去,原来的加上新的
localStorage.setItem("like", JSON.stringify([ ...that.Storage,query("id") ]))
this.remove("icon-xin")
this.add("icon-aixin")
//取消收藏
}else if(this.className.indexOf(("icon-aixin"))){
that.indexOfStorage()
this.remove("icon-aixin")
this.add("icon-xin")
}
})
}
}
new Info();

View File

@@ -0,0 +1,91 @@
class Info {
constructor() {
header("详情", `<i id="collection" class="iconfont icon-xin"></i>`)
this.getInfo();
this.Like()
}
setLike(id) {
const like = this.getLike()
//“&&”连接两个表达式,当两侧表达式都为真时,返回TRUE
//当这个是数组的时候,追加id
if (!!like && Array.isArray(like)) {
like.push(id)
// 更新本地数据
localStorage.setItem("like", JSON.stringify(like))
} else {
// 返回空数组则追加单个id
localStorage.setItem("like", JSON.stringify([id]))
}
}
//获取本地数据,有则返回数组,没有则返回空
getLike() {
const like = JSON.parse(localStorage.getItem("like"))
if (!!like && Array.isArray(like)) {
return like
}
return []
}
removeLinke(id) {
let like = this.getLike()
like = like.filter(v => v !== id)
localStorage.setItem("like", JSON.stringify(like))
}
changeLikeStyle() {
const collectionDom = $("#collection")
const id = query("id")
const like = this.getLike()
if (like.indexOf(id) === -1) {
collectionDom.remove("icon-aixin")
collectionDom.add("icon-xin")
} else {
collectionDom.remove("icon-xin")
collectionDom.add("icon-aixin")
}
}
onLinke() {
const id = query("id")
const like = this.getLike()
if (like.indexOf(id) === -1) {
this.setLike(id)
this.changeLikeStyle()
} else {
this.removeLinke(id)
this.changeLikeStyle()
}
}
Like() {
const collectionDom = $("#collection")
this.changeLikeStyle()
click(collectionDom, () => {
this.onLinke()
})
}
async getInfo() {
var res = await indexServe.info({
id: query("id"),
quantity: query("total")
});
res.forEach(v => {
$(".content").html(`<img src="${v}" alt="">`)
});
//console.log("res: ", res);
}
}
new Info();

View File

@@ -0,0 +1,32 @@
class Like{
constructor(){
header("我的收藏")
}
}

View File

@@ -0,0 +1,31 @@
class collection {
constructor() {
header("我的收藏")
this.like = JSON.parse(localStorage.getItem("like"))
this.getlike()
this.renderlike()
}
async getlike() {
var self = this;
if (localStorage.getItem("like") == null) {
var res = await indexServe.classList();
this.like = res.like
localStorage.setItem("like", JSON.stringify(this.like))
}
else {
this.like = JSON.parse(localStorage.getItem("like"))
}
}
renderlike() {
this.like.forEach(v => {
$(".item").html(`
<div>${v.title}</div>
`)
});
this.PrincipalClick()
}
}
new collection

View File

@@ -0,0 +1,10 @@
class mechanism{
constructor(){
footer();
}
}
new mechanism()

View File

@@ -0,0 +1,73 @@
class Model {
constructor () {
header("模特")
footer();
this.getModel()
this.hotscroll()
}
async getModel() {
var res = await indexServe.model()
// console.log(res);
model($('.hot_modelAll'),res)
// for(var key in data){ }
// var data = _(".hot_modelAll .model")
// for(var key in data){
// // console.log(_(".hot_modelAll .model"));
// console.log(key, data[key]);
// key = 0
// data[key].onscroll = (v => {
// const {clientHeight, scrollHeight, scrollTop} = v;
// const distance = scrollHeight- scrollTop - clientHeight;
// console.log(clientHeight, scrollHeight, scrollTop);
// if(distance <= 10){
// console.log("滚动到底部...");
// this.getModel()
// }
// })
// }
// NodeList转为数组
// _(".hot_modelAll .model") = [..._(".hot_modelAll .model")]
// Object.keys( _(".hot_modelAll .model")).forEach((value) => {
// // console.log(_(".hot_modelAll .model"));
// console.log(Object.keys( _(".hot_modelAll .model")));
// value.onscroll = () => {
// const {clientHeight, scrollHeight, scrollTop} = value;
// const distance = scrollHeight- scrollTop - clientHeight;
// console.log(clientHeight, scrollHeight, scrollTop);
// if(distance <= 10){
// console.log("滚动到底部...");
// this.getModel()
// }
// }
// })
};
hotscroll() {
console.log("$('.hot')",$('.hot'));
$('.hot').onscroll = () => {
// console.log('123');
const {clientHeight, scrollHeight, scrollTop} = $('.hot');
const distance = scrollHeight- scrollTop - clientHeight;
console.log(clientHeight, scrollHeight, scrollTop);
if(distance <= 10){
console.log("滚动到底部...");
this.getModel()
}
}
}
}
new Model()

View File

@@ -0,0 +1,11 @@
class my{
constructor(){
footer();
}
}
new my()

View File

@@ -0,0 +1,87 @@
class IndexSever{
//用接口名,方便后面的config接口数据发生更改
//apiList 的 index接口(首页)
async index(data = {}){
//调接口的时候生成独立的一个ajax保存变量,互不干扰
var ajax = new Ajax()
var res = await ajax.get({
//接口+参数
url:config.apiList.index,
data:data,
});
// 使用完以后删除ajax,减少内存占用
ajax = null;
return res
}
//apiList 的 index接口(首页)
async classListArr(data = {}){
return await (new Ajax()).get({
//接口+参数
url:config.apiList.classListArr,
data:data,
});
}
//apiList 的 classList接口(菜单)
async classList(data = {}){
var res = await (new Ajax()).get({
//接口+参数
url:config.apiList.classList,
data:data,
});
//后端数据没有首页 手动添加首页
//push 追加内容(最后) unshift追加数据(从头)
//principal后端菜单列表命名
res.principal.unshift({
id: -1,
page: 1,
title: "首页",
})
// 添加内容
res.principal.forEach(v => {
v.content = [];
//后端page从1开始
v.page = 1;
//总页数
v.total_page = 0
})
return res;
}
async info(data = {}) {
return await (new Ajax()).get({
url: config.apiList.info,
data: data,
});
}
async model(data = {}) {
return await (new Ajax()).get({
url: config.apiList.model,
data: data,
});
}
}
var indexServe = new IndexSever()

View File

@@ -0,0 +1,175 @@
class Util {
inject() {
//prototype给对象的构造函数 添加 新的属性
//去类名
Element.prototype.remove = function (removeClassName) {
this.classList.remove(removeClassName);
}
//加类名
Element.prototype.add = function (addClassName) {
this.classList.add(addClassName);
}
//返回标签内的文本值
HTMLElement.prototype.text = function (text) {
this.innerText = text;
}
//返回标签内的html
//当它插入元素时,会导致先前元素绑定的事件丢失
HTMLElement.prototype.html = function (text) {
this.innerHTML += text;
}
// HTMLElement.prototype.html = function (text) {
// this.insertAdjacentHTML += text;
// }
}
//公共头部
//参数=标题 + 图标(直接把标签作为参数传入)
header(title = "", icon) {
$("body").html(`
<div class="pub_header">
<i class="iconfont icon-back1"></i>
<div class="text">${title}</div>
${icon}
</div>
`)
//为(".icon-back1")图标绑定点击事件
click($(".icon-back1"), function() {
//返回历史记录
history.back()
})
}
//循环插入 内容 ul里面的li
//接收一个父元素(返回的虚拟dom)和数组
item(father, data) {
// 对数组进行循环
data.forEach(v => {
//${v.img_src (首页接口名称) ||(或) v.preview (其他列表接口名称)},其他同理
//详情页a标签 :参数=id+图片地址
father.html(`
<div class="item">
<a href="./info.html?id=${v.id}&total=${v.total || v.shuliang}">
<div class="item_top">
<img src="${v.img_src || v.preview}" alt="">
<span>${v.total || v.shuliang}</span>
</div>
<div class="item_text">
<div class="title ellipsis">${v.title}</div>
<div class="model ellipsis">模特:${v.user || v.renwulist[0].name}</div>
<div class="source ellipsis">机构:${v.source || v.jigoulist[0].name}</div>
</div>
</a>
<div class="item_tag">
${(v.biaoqianlist || v.tags).map(j => {
return `<div class="tage_item">${j.name || j.title}</div>`
}).toString().replaceAll(",", "")
}
</div>
</div>
`)
})
}
model(father,data){
data.forEach(v => {
father.html(`
<div class="model">
<a href="./modelinfo.html?id=${v.id}">
<div class="model_top">
<img src="${v.img}" alt="">
<span>63套</span>
</div>
<div class="model_bottom">${v.title}</div>
</a>
</div>
`)
})
}
footer(){
var ul = `
<ul class="footer">
${config.footerList.map((v, i) => {
return ` <li class="${location.href.includes(v.url) ? 'active' : ''}">
<a href="${v.url}">
<i class="iconfont ${v.icon}"></i>
<p>${v.title}</p>
</a>
</li>`
}).toString().replaceAll(",", "")
}
</ul>
`;
// console.log(ul);
$("body").html(ul)
}
//正则表达式,用来截取接口url
query(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
}
//Array.isArray() 可判断是否是数组
// NodeList类似数组的对象 转化为数组后不为空: [ Element, Element ]
// Element对象表示HTML里的元素 转换后数组为空: [ ]
//因此,将其转化为数组后,判断长度来决定如何绑定点击事件
click(className, callback) {
//Array.from浅拷贝数组实例(将实例转化为数组),返回一个新数组
var domArr = Array.from(className);
//如果是数组,就循环为每一个都绑定点击事件
if (domArr.length != 0) {
className.forEach((v, i) => {
v.onclick = function (e) {
v.index = i;
v.e = e;
//call() bind() apply()调整this指向
callback.call(this)
}
})
} else {
//单个绑定点击事件
className.onclick = function (e) {
className.e = e;
callback.call(this)
}
}
}
//对象{}
$(className){
return document.querySelector(className)
}
//数组[]
_(className){
return document.querySelectorAll(className)
}
}
var {$, _, inject, header, item, footer, query, click ,model} = new Util()
inject()

View File

@@ -0,0 +1,12 @@
; (function (doc, win, undefined) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in win ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (clientWidth === undefined) return;
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
};
if (doc.addEventListener === undefined) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false)
})(document, window);

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/util/rem.js"></script>
<link rel="stylesheet" href="http://at.alicdn.com/t/font_2124975_xxjerwhwts.css">
<link rel="stylesheet" href="../css/clear.css">
<link rel="stylesheet" href="../css/public.css">
<link rel="stylesheet" href="../css/edit.css">
</head>
<body>
<!-- 数据存储到本地。首页数据和编辑数据公用一个接口。 -->
<div class="content">
<div class="title">已选菜单</div>
<ul class="menu_list principal">
</ul>
<div class="title">可选菜单</div>
<ul class="menu_list additional">
</ul>
</div>
</body>
<script src="../js/util/index.js"></script>
<script src="../js/config/index.js"></script>
<script src="../js/ajax/index.js"></script>
<script src="../js/serve/index.js"></script>
<script src="../js/page/edit.js"></script>
</html>

View File

@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 滑动 -->
<link href="https://cdn.bootcdn.net/ajax/libs/Swiper/4.3.0/css/swiper.min.css" rel="stylesheet">
<script src="../js/util/rem.js"></script>
<link rel="stylesheet" href="http://at.alicdn.com/t/font_2124975_xxjerwhwts.css">
<link rel="stylesheet" href="../css/clear.css">
<link rel="stylesheet" href="../css/public.css">
<link rel="stylesheet" href="../css/index.css">
</head>
<body>
<div class="header">
<div class="header_logo">
<i class="iconfont icon-taozi1"></i>
<div class="search">
<i class="iconfont icon-search"></i>
<span>200万张图,有你想要的...</span>
</div>
<i class="iconfont icon-wo"></i>
</div>
<div class="header_menu">
<ul> </ul>
<a class="iconfont icon-edit" href="./edit.html"></a>
</div>
</div>
<div class="content">
<div class="swiper-container">
<div class="swiper-wrapper page_wrapper">
</div>
</div>
</div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/Swiper/4.3.0/js/swiper.min.js"></script>
<script src="../js/config/index.js"></script>
<script src="../js/util/index.js"></script>
<script src="../js/ajax/index.js"></script>
<script src="../js/serve/index.js"></script>
<script src="../js/page/index.js"></script>
</html>

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/util/rem.js"></script>
<link rel="stylesheet" href="http://at.alicdn.com/t/font_2124975_xxjerwhwts.css">
<link rel="stylesheet" href="../css/clear.css">
<link rel="stylesheet" href="../css/public.css">
<link rel="stylesheet" href="../css/info.css">
</head>
<body>
<div class="content">
</div>
</body>
<script src="../js/util/index.js"></script>
<script src="../js/config/index.js"></script>
<script src="../js/ajax/index.js"></script>
<script src="../js/serve/index.js"></script>
<script src="../js/page/info.js"></script>
</html>

View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/util/rem.js"></script>
<link rel="stylesheet" href="http://at.alicdn.com/t/font_2124975_xxjerwhwts.css">
<link rel="stylesheet" href="../css/clear.css">
<link rel="stylesheet" href="../css/public.css">
<link rel="stylesheet" href="../css/like.css">
</head>
<body>
</body>
<script src="../js/util/index.js"></script>
<script src="../js/config/index.js"></script>
<script src="../js/ajax/index.js"></script>
<script src="../js/serve/index.js"></script>
<script src="../js/page/like.js"></script>
</html>

View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/util/rem.js"></script>
<link rel="stylesheet" href="http://at.alicdn.com/t/font_2124975_xxjerwhwts.css">
<link rel="stylesheet" href="../css/clear.css">
<link rel="stylesheet" href="../css/public.css">
<link rel="stylesheet" href="../css/mechanism.css">
</head>
<body>
</body>
<script src="../js/util/index.js"></script>
<script src="../js/config/index.js"></script>
<script src="../js/ajax/index.js"></script>
<script src="../js/serve/index.js"></script>
<script src="../js/page/mechanism.js"></script>
</html>

View File

@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/util/rem.js"></script>
<link rel="stylesheet" href="http://at.alicdn.com/t/font_2124975_xxjerwhwts.css">
<link rel="stylesheet" href="../css/clear.css">
<link rel="stylesheet" href="../css/public.css">
<link rel="stylesheet" href="../css/model.css">
</head>
<body>
<div class="content">
<div class="hot">
<div class="hot_model">热门模特</div>
<div class="hot_modelAll">
</div>
</div>
</div>
</body>
<script src="../js/util/index.js"></script>
<script src="../js/config/index.js"></script>
<script src="../js/ajax/index.js"></script>
<script src="../js/serve/index.js"></script>
<script src="../js/page/model.js"></script>
</html>

View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/util/rem.js"></script>
<link rel="stylesheet" href="http://at.alicdn.com/t/font_2124975_xxjerwhwts.css">
<link rel="stylesheet" href="../css/clear.css">
<link rel="stylesheet" href="../css/public.css">
<link rel="stylesheet" href="../css/my.css">
</head>
<body>
</body>
<script src="../js/util/index.js"></script>
<script src="../js/config/index.js"></script>
<script src="../js/ajax/index.js"></script>
<script src="../js/serve/index.js"></script>
<script src="../js/page/my.js"></script>
</html>

View File

@@ -0,0 +1,205 @@
1802 1.19
【张婷】5:模特 列表页面
接口:7
map() 方法返回一个新数组 {.toString().replaceAll(",", "")————————>手动转为字符串},数组中的元素为原始数组元素调用函数处理后的值。
使用 prototype 属性就可以给对象的构造函数 添加 新的属性:
Element 对象可以拥有类型为元素节点、文本节点、注释节点的子节点。
NodeList 对象表示节点列表,比如 HTML 元素的子节点集合。
元素也可以拥有属性 https://blog.csdn.net/m0_53170889/article/details/119414222
location.href 可设置或返回当前显示的文档的完整 URL。
window.location.assign(url) : 加载 URL 指定的新的 HTML 文档。就相当于一个链接,跳转到指定的url,当前页面会转为新页面内容,可以点击后退返回上一个页面。
window.location.replace(url) : 通过加载 URL 指定的文档来替换当前文档,这个方法是替换当前窗口页面,前后两个页面共用一个窗口,所以是没有后退返回上一页的
正则表达式 RegExp
query(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
}
^ 从开始行开始匹配
| 或运算符,匹配|符号前或后的字符
[] 内为字符集,匹配 [ ] 内任一字符
* 匹配 >= 0 个 * 号前的字符。
[^ ] 匹配除了方括号里的任意字符
正则表达式用于定义一些字符串的规则。计算机可以根据正则表达式,来检查一个字符串是否符合指定的规则,或者将字符串中符合规则的内容提取出来。
search 从问号 (?) 开始的 URL(查询部分)
substr(start, length)方法是用来截取字符串的 start是要截取字符串的开始下标,length是要截取的长度。
match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。返回值数组
unescape() 函数可对通过 escape() 编码的字符串进行解码 unescape() 函数已经从 Web 标准中删除,所以尽量不使用该函数,可以使用 decodeURI 或 decodeURIComponent 代替。
click(className, callback) {
var domArr = Array.from(className);
if (domArr.length != 0) {
className.forEach((v,i) => {
v.onclick = function (e) {
v.index = i;
v.e = e;
callback.call(this)
}
})
} else {
className.onclick = function (e) {
className.e = e;
callback.call(this)
}
}
}
只针对数组和对象
浅拷贝:两者之间可以相互影响,用的一个内存空间;
例:var a = [1,2,3]
var b = a
b[0] = 100 输出b=[100,2,3]
输出a=[100,2,3]
深拷贝:两者互不干扰,各用各的内存空间(方法1 对a遍历,将元素取出来依次赋值给b)
例:方法2 var a = [1,2,3]
var b = JSON.parse(JSON.stringify(a))
b[0] = 100 输出b=[100,2,3]
输出a=[1,2,3]
Array.from() 方法对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。 返回值 一个新的数组实例。
Array.from(arrayLike[, mapFn[, thisArg]])
arrayLike 想要转换成数组的伪数组对象或可迭代对象。
mapFn 可选 如果指定了该参数,新数组中的每个元素会执行该回调函数。
thisArg 可选 可选参数,执行回调函数 mapFn 时 this 对象。
2022.6.30
JavaScript 支持不同类型的循环:
for - 循环代码块一定的次数
for/in - 循环遍历对象的属性
while - 当指定的条件为 true 时循环指定的代码块
do/while - 同样当指定的条件为 true 时循环指定的代码块
注意: 不要使用 for/in 语句来循环数组的索引,你可以使用 for 语句替代。
每当readyState发生变化是都会触发onreadystatechange函数,总共会触发4次
JSON.parse一般用于将JSON字符串转化为JSON对象
JSON 是用于存储和传输数据的格式。
语法规则:
数据为 键/值 对。
数据由逗号分隔。
大括号保存对象
方括号保存数组
this.principal[this.index].content = [
...this.principal[this.index].content,
...res.list
];
//扩展运算符(...)是ES6的语法,用于取出参数对象的所有可遍历属性,然后拷贝到当前对象之中。
this.principal[this.index].content = 新对象[
{},{},{},{},旧对象
{},{},{},{},追加对象
];
2022.7.4
history.back() 返回历史记录(后退一步)
分类编辑和首页菜单公用的一个接口,所以要将其数据存储到本地。
存储:
cookie、localstorage和sessionStorage三者都是在开发中用到的临时存储客户端会话信息或者数据的方法。
三者区别:
一、存储的时间有效期不同
1、cookie的有效期是可以设置的,默认的情况下是关闭浏览器后失效
2、sessionStorage的有效期是仅保持在当前页面,关闭当前会话页或者浏览器后就会失效
3、localStorage的有效期是在不进行手动删除的情况下是一直有效的
二、存储的大小不同
1、cookie的存储是4kb左右,存储量较小,一般页面最多存储20条左右信息
2、localStorage和sessionStorage的存储容量是5Mb(官方介绍,可能和浏览器有部分差异性)
三、与服务端的通信
1、cookie会参与到与服务端的通信中,一般会携带在http请求的头部中,例如一些关键密匙验证等。
2、localStorage和sessionStorage是单纯的前端存储,不参与与服务端的通信
四、读写操作的便捷程度
cookie操作起来较为繁琐,并且部分数据不可以读取操作
设置cookie: document.cookie = "key=value;";
localStorage和sessionStorage相似:
存储:localStorage || sessionStorage.setItem("数据名",“数据值”)[数据名和数据值均要求为字符串]
读取:let data = localStorage || sessionStorage.getItem("数据名")
清除:localStorage || sessionStorage.removeItem("数据名")
移除所有:localStorage || sessionStorage.clear()
splice() 方法用于添加或删除数组中的元素。
返回值:如果删除一个元素,则返回一个元素的数组。 如果未删除任何元素,则返回空数组。
splice(“要删除的元素下标”,“删除几个”)
insertAdjacentHTML() 将指定的文本解析为HTML或XML,并将结果节点插入到DOM树中的指定位置。它不会重新解析它正在使用的元素,因此它不会破坏元素内的现有元素
语法:element.insertAdjacentHTML(position,text)
position是相对于元素的位置,并且必须是以下字符串之一:
beforebegin: 元素自身的前面。
afterend: 元素自身的后面。
beforebegin和afterend位置,仅在节点在树中且节点具有一个parent元素(父元素)时工作.
afterbegin: 插入元素内部的第一个子节点之前。
beforeend: 插入元素内部的最后一个子节点之后。
text是要被解析为HTML或XML,并插入到DOM树中的字符串。
var / let / const
var 声明的变量属于函数作用域,let 和 const 声明的变量属于块级作用域;
var 存在变量提升现象,而 let 和 const 没有此类现象;
var 变量可以重复声明,而在同一个块级作用域,let 变量不能重新声明,const 变量不能修改。

View File

@@ -0,0 +1,33 @@
页面写完再写功能
完整地址加信息: config.checkerurl请求基地址 + 请求短地址 + 请求参数
apilist:保存请求短地址(即 接口 ),方便更改
sever:页面 <————> sever <————> ajax
对接口返回的数据做统一处理,然后返回给页面“一对多!”
sever____config:页面调sever里面的方法,sever从config里面拿到url地址,然后去ajax里调接口,并接收返回值,retur给页面。
类里面的方法根据页面来定,相关接口放相关类里面
状态码:ajax 1~4 ; http ; 接口状态码(后端决定:状态+中文提示信息)
所有接口都要走状态码判断,处理方式不一样的都要写,一样的写一个就可以了
throw(打断浏览器代码运行) new error
config作用:存放各个阶段的基地址/接口
sever作用:page 请求中间层,sever去调ajax封装,ajax需要请求参数(短地址:sever自动读取config得到+参数:page给的) 接收数据统一处理后返回给page
ajax作用:状态码监听 状态码判断 返回数据
css定义全局变量 .root{--变量:值} 一般有颜色和字体大小(字体改rem)
调用 color:var(--变量)
rem.js放在util里面

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 请求示例:(http://127.0.0.1:3000/api <——————请求基地址) /index/class?type=1&page=1 -->
<ul>
</ul>
<button class="more">下一页</button>
</body>
<script src="./js/ajax.js"></script>
<script src="./js/utils.js"></script>
<script src="./js/index.js"></script>
</html>

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>详情页</title>
</head>
<body>
<!-- 请求示例:(http://127.0.0.1:3000/api <——————请求基地址) /index/class?type=1&page=1 -->
<div class="main">
<img src="" alt="">
<p class="posttime"></p>
<p class="title"></p>
</div>
</body>
<script src="./js/ajax.js"></script>
<script src="./js/utils.js"></script>
<script src="./js/information.js"></script>
</html>

View File

@@ -0,0 +1,51 @@
class Ajax {
constructor() {
this.ajax = new XMLHttpRequest();
}
/**
*
* @param {*} params
* {
* url: '',
* data: {
* id: 1,
* page: 2
* },
* header: {
* 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
* }
* }
*/
get(params) {
return new Promise((success, error) => {
var str = ""
for (const key in params.data) {
str += `&${key}=${params.data[key]}`
}
str = str.replace("&", "?")
this.ajax.open("GET", `${params.url}${str}`)
this.ajax.send()
this.readystatechange(success, error)
})
}
post() { }
readystatechange(success, error) {
this.ajax.onreadystatechange = () => {
if (this.ajax.readyState == 4) {
if (this.ajax.status == 200) {
var data = JSON.parse(this.ajax.responseText)
// console.log(data);
success(data)
} else {
error(this.ajax)
}
}
}
}
}
var ajax = new Ajax();

View File

@@ -0,0 +1,39 @@
class Index {
constructor() {
this.page = 1
this.getClassList()
this.bindEvent()
}
bindEvent() {
click(".more", (e) => {
this.page += 1
this.getClassList()
// console.log("下一页");
})
}
async getClassList() {
var res = await ajax.get({
url: 'http://127.0.0.1:3000/api/index/class',
data: {
type: 1,
page: this.page
},
});
var data = res.result.items;
data.forEach(v => {
$("ul").innerHTML += `
<li>
<a href="./information.html?url=${v.path}">
<img src="${v.img}" alt="">
<p>${v.title}</p>
</a>
</li>
`
})
}
}
new Index();

View File

@@ -0,0 +1,27 @@
class information {
constructor (){
this.getInformation ()
}
async getInformation (){
var res = await ajax.get({
url: 'http://127.0.0.1:3000/api/index/info',
data: {
url: query("url")
},
});
$(".main img").src = res.result.backImg
$(".main img").src = res.result.backImg
$(".main img").src = res.result.backImg
}
}
new information()

View File

@@ -0,0 +1,37 @@
class Util {
inject() {
Element.prototype.remove = function (removeClassName) {
this.classList.remove(removeClassName);
}
Element.prototype.add = function (addClassName) {
this.classList.add(addClassName);
}
}
click(className,callback) {
$(className).onclick = () => {
callback()
}
}
//地址栏获取多个参数
query(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
}
$(className) {
return document.querySelector(className)
}
_(className) {
return document.querySelectorAll(className)
}
}
var { $, _, click, inject, query} = new Util()
inject()

View File

@@ -0,0 +1,93 @@
<!-- 案例一: 激活态菜单和内容的切换(foreach循环) -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.title{
display: flex;
list-style: none;
}
.title .active{
color: red;
}
.title li{
margin-right: 30px;
}
.content{
display: flex;
list-style: none;
}
.content .active{
display: block;
}
.content li{
margin-right: 30px;
display: none;
}
</style>
<body>
<ul class="title">
<li class="active">推荐</li>
<li>电视剧</li>
<li>电影</li>
<li>综艺</li>
</ul>
<ul class="content">
<li class="active">推荐内容</li>
<li>电视剧内容</li>
<li>电影内容</li>
<li>综艺内容</li>
</ul>
</body>
<script>
// 步骤:1读取事件2绑定事件3事件处理函数
// 有很多个li 所以是数组
// 数组的循环 用foreach
var title_li = document.querySelectorAll(".title li")
var content_li = document.querySelectorAll(".content li")
// 循环解读:外——中——内
// 首先读取到第一个li的dom节点,然后对
// (最外层: 读取dom节点,得到每个li标签存储的内容)
title_li.forEach(function(item, index){
// 中间层: 给被点击到的li标签添加激活态
// console.log('title_li',item,index);
item.onclick = function(e){
// 最内层: 清楚所有li标签的激活态
console.log('e',e.target.className);
title_li.forEach(function(t,i){
t.className = ''
content_li[i].className = ''
})
// e.target.className = 'active'
// 下标从0开始循环,且目录和内容的下标相同,因此激活态实现同步
item.className = 'active'
content_li[index].className = 'active'
}
})
// for (var i = 0; i < titleLi.length; i++) {
// console.log(titleLi[i]);
// }
// NodeList.prototype.forLb = function(callback) {
// for (let i = 0; i < this.length; i++) {
// callback(this[i], i, this)
// }
// }
</script>
</html>

View File

@@ -0,0 +1,64 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 鼠标悬浮改变效果 */
.one:hover {
color: red;
}
/* 平滑过渡(由一种状态到另一种状态) */
.two {
width: 200px;
transition: all ease 1s ;
}
/* 聚焦 */
.two:focus {
width: 500px;
}
.far{
display: flex;
height: 200px;
width: 200px;
border: 1px solid;
align-items: center;
justify-content: center;
flex-direction: column;
}
</style>
</head>
<body>
<!-- <div class="one">
<p>hahahaha</p>
</div>
<input class="two" type="text" placeholder="输入">
<input class="three" type="text" placeholder="输入">
<input class="four" type="text" placeholder="输入"> -->
<div class="far">
<span>1</span>
<p>2</p>
<div>3</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,252 @@
<!-- <HTML>标签练习</HTML> -->
<!-- <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul style="list-style: none;">
<li>王一鸣是1猪</li>
<li>王一鸣是2猪</li>
<li>王一鸣是3猪</li>
</ul>
<div>
<div class="item">王一鸣是1猪</div>
<div class="item">王一鸣是2猪</div>
<div class="item">王一鸣是3猪</div>
</div>
<form action="">
<input type="password" placeholder="请输入密码">
<input type="button" value="登录">
<button>登录</button>
<input type="submit" value="登录">
<input type="reset" value="登录">
</form>
<select name="城市" id="地点">
<option value="">-请选择-</option>
<option value="">四川</option>
<option value="">成都</option>
<option value="">猪头</option>
</select>
<textarea name="" id="" cols="30" rows="10" placeholder="听到滴声请留言"></textarea>
<video src="视频地址" autoplay loop muted controls poster="图片地址"></video>
<audio src="音乐地址" 其他属性相同></audio>
</body>
</html> -->
<!-- css标签练习 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 所属 */
/* .one > a {
color: aqua;
} */
/* 嵌套(所有a) */
/* .one a {
color: blue;
} */
/* 同时选中 */
/* .one h1 , .one h2 {
color: blueviolet;
} */
/* 同一级别 效果作用于第二个a*/
/* .one a + a {
color: blueviolet;
} */
/* 先写默认再写过程 */
/* 例如:h2默认隐藏,然后再写出经过(悬浮h1)后得到的结果(显现h2) */
/* .one h2 {
display: none;
} */
/* 在h1悬浮的同时作用于同级的h2,并对h2设置实现效果 */
/* .one h1:hover+h2 {
display: block;
} */
/* (网页格式 手动格式化) */
/* html {
font-size: 0;
} */
/* .one , .two{
width: 100px;
height: 100px;
border: 1px solid;
display: inline-block;
} */
/* 本地的插入有格式+在线的直接复制粘贴即可 */
/* .one{
width: 1000px;
height: 1000px;
background-image: url('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.fengjinwei.com%2F2021%2F08%2F20210813100136196.png&refer=http%3A%2F%2Fimg.fengjinwei.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1656683650&t=cc2cda93b3071d8088c022782456e231');
}
*/
body,
h1,
h2,
h3,
h4,
h5,
h6,
ul,
li,
p {
margin: 0;
padding: 0;
list-style: none;
}
a {
text-decoration: none;
}
.menu {
width: 100%;
height: 38px;
background-color: blueviolet;
}
.menu ul {
margin: 0 auto;
}
.menu ul li {
float: left;
}
</style>
</head>
<body>
<!-- <img src="地址" alt="出现问题的时候,设置字体"> -->
<!-- <div class="one">
<h1>111111111111</h1>
<h2>222222222222</h2>
<a href="">333333333333</a>
<a href="">4444444444444</a>
<div class="two">
<h3>55555555555555</h3>
<a href="">666666666</a>
</div>
</div> -->
<div class="one">
</div>
<!-- <div class="one">
</div>
<div class="two">
</div> -->
<!-- 实体字符练习 -->
<!-- 1、空格 -->
<div>好好学习&nbsp&nbsp&nbsp&nbsp&nbsp天天向上</div>
<!-- 大于 -->
<div>好好学习&gt&gt&gt&gt&gt&gt天天向上</div>
<!-- 小于 -->
<div>好好学习&lt&lt&lt&lt&lt天天向上</div>
<!-- emmet语法练习 -->
<!-- >后代节点:下一级(所属关系) -->
<!-- 写作:.one>.two>.three -->
<div class="one">
<div class="two">
<div class="three"></div>
</div>
</div>
<!-- >兄弟节点:同一级别(并列关系) -->
<!-- 写作:.top>.one+.two+.three -->
<div class="top">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>
<!-- 上级节点^:返回上一级别 -->
<!-- 写作:.top>.top1>.one>.two^.top2 -->
<div class="top">
<div class="top1">
<div class="one">
<div class="two"></div>
</div>
<div class="top2"></div>
</div>
</div>
<!-- 浮动练习 -->
<div class="menu">
<ul>
<li>菜单</li>
<li>菜单</li>
<li>菜单</li>
<li>菜单</li>
<li>菜单</li>
<li>菜单</li>
<li>菜单</li>
<li>菜单</li>
<li>菜单</li>
</ul>
</div>
</body>
</html>

View File

@@ -0,0 +1,135 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="one">A</button>
<button class="two">B</button>
<button class="three">C</button>
<a href=""></a>
</body>
<script>
console.log(window)
var name = 250
// if (name >= 200 && name <= 300 ) {
// console.log("王一鸣是250");
// }else{
// console.log("王一鸣还是250");
// }
if (name < 200 || name > 300) {
console.log("王一鸣是250");
} else {
console.log("王一鸣还是250");
}
var cj = 75,
fl;
if (cj < 60) {
fl = "不及格"
} else if (cj >= 60 && cj < 70) {
fl = "及格"
} else if (cj >= 70 && cj < 80) {
fl = "良好"
} else {
fl = "优秀"
}
console.log(fl)
// 只有当i<50成立的时候即ture 才会执行i++。 例:i>50,false,不执行 输出undefined。
for (var i = 1; i < 50; i++) {
console.log(i);
}
// 九九乘法表 一层套一层
// 外层总共九行,所以定义一个名=公式 自动换行总共九行
for (var i = 1; i <= 9; i++) {
var all = ""
// 内层无数行,所以打印日志在外层,轻松实现换行
for (var j = 1; j <= i; j++) {
// all += j + "*" + i + "=" + i*j + ' '
all += `${j}*${i}=${i*j} `
}
all += `</br>`
// document.write(all)
}
var A = new Object({
Number: 20,
sex: "男",
name: "猪"
})
console.log(A);
console.log(A.name);
console.log(A["name"]);
// Key 是基于for in才被访问到的。key可以被定义为各种名称的常量
// B基于for in才被访问到 所以是局部常量
for (const B in A) {
console.log(B)
}
var A = new Object();
A.name = "哈1";
A.age = "哈2";
console.log(A);
FFF = 1
console.log(FFF);
// 去掉var,变量提升,且只提升一级
function a() {
var b = function () {
aaa = 1
}
console.log(aaa);
}
// 回调函数
function testa(n) {
// 执行n,n接收的ttt所以实际执行的是ttt的function,即123
n()
}
var tttt = function () {
console.log(123);
}
testa(tttt)
// 回调案例
function test(call, n) {
console.log('call', call);
var a = call()
n += a
console.log('n', n);
}
function b() {
return 1 + 1
}
test(b, 2)
// <button class="one">A</button>
// <button class="two">B</button>
// <button class="three">C</button>
// 事件的写法
// querySelector只能查询第一个
var all = document.querySelectorAll("button")
for (var i = 0; i < all.length; i++) {
all[i].innerText = "你好"
console.log('all', all[i]);
}
</script>
</html>

View File

@@ -0,0 +1,56 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>滚动固定</title>
<style>
body {
height: 30000px;
background: #0000ff5e;
}
.header {
width: 100%;
height: 50px;
background: #ff00003d;
margin-top: 200px;
}
.fixed {
position: fixed;
width: 100%;
left: 0;
top: 0;
margin-top: 0;
}
</style>
</head>
<body>
<div class="header"></div>
</body>
<script>
var header = document.querySelector('.header')
console.log('header',header);
document.querySelector('body').onscroll = function(){
// (定义c即这个元素距离顶部的距离)
// 要获取当前页面的滚动条纵坐标位置,用:
// document.documentElement.scrollTop;
// 而不是:
// document.body.scrollTop;
// documentElement 对应的是 html 标签,而 body 对应的是 body 标签。
var C = document.documentElement.scrollTop;
// console.log('c',C);
if(C >= 200){
header.className = 'header fixed'
}else{
header.className = 'header'
}
}
</script>
</html>

View File

@@ -0,0 +1,101 @@
const request = require('request');
const iconv = require('iconv-lite');
const cheerio = require('cheerio');
const fs = require('fs');
//网页基地址
var baseUrl = `https://pic.netbian.com`
//网页地址共1034页
//用于存放页面地址(一页一页的下载)
var pageArr = []
var pageIndex = 0
//用于存放详情页地址
var hrefArr = []
var hrefIndex = 0
//循环先爬3页
for (var i = 1; i <= 2; i++) {
if (i == 1) {
pageArr.push(`${baseUrl}/index.html`)
} else {
pageArr.push(`${baseUrl}/index_${i}.html`)
}
}
// console.log("pageArr:", pageArr);
function requestPage() {
//调用getHtml方法请求
getHtml(pageArr[pageIndex], ($) => {
//each遍历(下标,元素)
$(".slist li").each(function (index, element) {
//去除下一页图片(21下一页)总共20张图片
if (!$(this).hasClass("nextpage")) {
// console.log( $(this).find("a").attr("title"));
hrefArr.push(
//attr打印标签属性
//基地址 + 图片地址
`${baseUrl}${$(this).find("a").attr("href")}`
)
}
})
requestInfo()
// console.log("hrefArr:",hrefArr);
})
}
function requestInfo() {
getHtml(hrefArr[hrefIndex], ($) => {
//A 利用request去请求图片地址
request(`${baseUrl}${$(".photo-pic img").attr("src")}`)
//管道符: 将A的数据流入B
.pipe(
//B fs创建写入数据流 //图片命名方式,随机数+时间戳避免名字重复
fs.createWriteStream(`./img/${ Math.random() * 1000000 + `${Date.now()}` }.jpg`)
)
// console.log(`${baseUrl}${$(".photo-pic img").attr("src")}`);
hrefIndex += 1
if(hrefIndex < hrefArr.length){
requestInfo()
}else{
pageIndex += 1
if(pageIndex < pageArr.length){
requestPage()
}
}
})
}
//每一页和每一页的每个图片,都需要发送请求,所以统一封装一下
function getHtml(url, callback) {
request({
uri: url,
method: 'GET',
encoding: 'binary'
//转码
}, function (error, response, body) {
var str2 = iconv.decode(new Buffer(body, 'binary'), 'gbk');
const $ = cheerio.load(str2)
callback($)
// console.log(str2);
});
}
requestPage()

View File

@@ -0,0 +1,14 @@
const http = require('http');
const server = http.createServer((req, res) => {
//手动设值请求头和输出格式等等
res.writeHead(200, { 'Content-Type': 'application/json' });//'Content-Type': 'text/html; charset=UTF-8'
//浏览器输出
res.end(JSON.stringify({
data: 'Hello World!'
}));
});
server.listen(8000);

View File

@@ -0,0 +1,496 @@
{
"name": "node",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"asn1": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
"requires": {
"safer-buffer": "~2.1.0"
}
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA=="
},
"aws4": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
},
"axios": {
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"requires": {
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
},
"dependencies": {
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
}
}
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
"requires": {
"tweetnacl": "^0.14.3"
}
},
"boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
},
"cheerio": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
"integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
"requires": {
"cheerio-select": "^2.1.0",
"dom-serializer": "^2.0.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"htmlparser2": "^8.0.1",
"parse5": "^7.0.0",
"parse5-htmlparser2-tree-adapter": "^7.0.0"
}
},
"cheerio-select": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
"requires": {
"boolbase": "^1.0.0",
"css-select": "^5.1.0",
"css-what": "^6.1.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1"
}
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
},
"css-select": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
"requires": {
"boolbase": "^1.0.0",
"css-what": "^6.1.0",
"domhandler": "^5.0.2",
"domutils": "^3.0.1",
"nth-check": "^2.0.1"
}
},
"css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
"requires": {
"assert-plus": "^1.0.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"requires": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
}
},
"domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
},
"domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"requires": {
"domelementtype": "^2.3.0"
}
},
"domutils": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
"integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
"requires": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.1"
}
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
"requires": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"entities": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz",
"integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg=="
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g=="
},
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"follow-redirects": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw=="
},
"form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
"requires": {
"assert-plus": "^1.0.0"
}
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q=="
},
"har-validator": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
"requires": {
"ajv": "^6.12.3",
"har-schema": "^2.0.0"
}
},
"htmlparser2": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz",
"integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==",
"requires": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"domutils": "^3.0.1",
"entities": "^4.3.0"
}
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
"requires": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
}
},
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
},
"json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
},
"jsprim": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.4.0",
"verror": "1.10.0"
}
},
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"requires": {
"mime-db": "1.52.0"
}
},
"nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"requires": {
"boolbase": "^1.0.0"
}
},
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
},
"parse5": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz",
"integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==",
"requires": {
"entities": "^4.3.0"
}
},
"parse5-htmlparser2-tree-adapter": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
"integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
"requires": {
"domhandler": "^5.0.2",
"parse5": "^7.0.0"
}
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
},
"psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"qs": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA=="
},
"request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
"requires": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.3",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
}
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sshpk": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
"integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
"requires": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
}
},
"tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"requires": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
}
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
},
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"requires": {
"punycode": "^2.1.0"
}
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
"requires": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
}
}
}

View File

@@ -0,0 +1,18 @@
{
"name": "node",
"version": "1.0.0",
"description": "",
"main": "PaChong.js",
"scripts": {
"start": "node-dev PaChong.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.27.2",
"cheerio": "^1.0.0-rc.12",
"iconv-lite": "^0.6.3",
"request": "^2.88.2"
}
}

View File

@@ -0,0 +1,98 @@
服务端渲染
Node.js : js在服务器上的运行环境
V8是Google的开源的JavaScript和WebAssembly引擎,用C++编写。它用于Chrome和Node.js等。
npm :(命令行工具,是一个软件,nodejs出厂自带)NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。
前端开发三个阶段:
1 html css table [table标签即表格,tr标签是行,th是表格的头,td是列。tr和td需要多少写多少,一行(列)写一个,多行(列)写多个]
2 html + css + js (jquery) 操作dom [http://t.zoukankan.com/liuafan-p-9523773.html]
mvc框架 [MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。]
模型 视图 控制器 m和v代码分离,c控制m和v更新改变同步
3 mvvm框架 (其发展基于node.js的蓬勃发展)
模型 视图 视图模型 控制器 MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model):
1. 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
2. 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
3. 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码。
4. 可测试。界面素来是比较难于测试的,测试可以针对ViewModel来写。
mvvm angular.js [是一个应用设计框架与开发平台,用于创建高效、复杂、精致的单页面应用,通过新的属性和表达式扩展了 HTML,实现一套框架,多种平台,移动端和桌面端。AngularJS有着诸多特性,最为核心的是:MVVM、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。]
react [用于构建用户界面的JavaScript库,主要用于构建UI] 1.声明式设计:React 使创建交互式 UI 变得轻而易举。为你应用的每一个状态设计简洁的视图,当数据变动时 React能高效更新并渲染合适的组件。
2.组件化: 构建管理自身状态的封装组件,然后对其组合以构成复杂的 UI。
3.高效:React通过对DOM的模拟,最大限度地减少与DOM的交互。
4.灵活:无论你现在使用什么技术栈,在无需重写现有代码的前提下,通过引入React来开发新功能。
vue [是一套用于构建用户界面的渐进式JavaScript框架] https://blog.csdn.net/wu246051/article/details/123060620
终端显示:运行————————node 文件名(例:node index.js)
存储插件—————node_modules: 存放项目开发中所有下载的插件
npm: 初始化——————npm init ——————npm init -y(默认生成pack...)————package.json [scripts:运行命令“存储各种命令”,可以放很多个,但最后一个不能有逗号][dependencies:(devDependencies开发阶段)上线阶段的插件依赖 npm i自动寻找并下载所有依赖插件]
运行命令————npm run XXX (运行scripts里的XXX命令) !!如果命令名为start,run可以省略掉 npm start!!
安装插件————npm install XXX(XXX插件名称)————简写:npm i XXX————!!在哪里安装就在哪里打开终端,路径不能错!!(npm下载默认国外,cnpm国内下载)
———— npm install 插件名 参数——————参数:--save(简写:-s)将插件保存到上线阶段dependencies一般情况下默认
--save-dev(简写:-D)将插件保存到开发阶段devDependencies
--g 将插件安装到操作系统全局 [npm i -g node-dev]
全局插件文件夹安装在使用者下方文件
删除插件————npm uninstall 插件名 (package-lock.json本地存储install里插件的下载地址)
安装插件并指定版本————npm install XXX@版本号
插件包括系统自带的和用户下载的,但都要先引入才能使用:const XX = require(“XX”);
解构赋值:ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。es6中对变量的赋值遵循一个规则,只要!!左右两边的模式相同,就可以进行合法赋值!!右给左赋值
——————node.js——————
node.js事件循环:web serve接受请求————关闭————服务下一个web请求——————统一放进处理列队,依次处理后返回值
模块间的相互调用: utils.js 和 index.js
导出:module.exports = new utils() 接收:const A = require("./utils"); A.test() utils里面要调用的方法(假装有一个test()方法)
module.exports = new utils() const { test } = require("./utils");
exports.util = new utils() const A = require("./utils"); A.util.test()
fs文件系统:fs.writeFileSync("./生成文件路径",“文件内容”) Sync:同步 没有则需要回调函数 传参包含callback
var html = fs.readFileSync("./index.html"路径)
http超文本传输协议: const http = require ("http")
res.end(html. .toString())
buffer二进制数据 .toString()buffer转字符串
————————爬虫————————
总共有1034页数,第一页为index 其余一次加1
https://pic.netbian.com/index.html
https://pic.netbian.com/index_2.html
图片地址
小图 https://pic.netbian.com/uploads/allimg/170609/123945-1496983185 6c4d.jpg
大图 https://pic.netbian.com/uploads/allimg/170609/123945-1496983185 ad61.jpg
.each遍历(下标,元素)
attr打印标签属性 例.attr("title")

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>状态切换和颜色随机</title>
</head>
<body>
<button>哈喽,点我有惊喜</button>
<div style="display: none;" class="text">嘻嘻,想不到吧</div>
</body>
<script>
var button = document .querySelector("button")
var text = document .querySelector(".text")
console.log(button);
button.onclick = function(){
// console.log('123');打印尝试绑定点击事件是否成功
if(text.style.display == "block"){
text.style.display = "none"
}else{
text.style.display = "block"
// 以上三行,实现点击文本显示和隐藏的相互切换
text.style.color = `hsl(${Math.random()*360},100%,50%)`
// 实现文本显示时,文本颜色随机切换
}
}
</script>
</html>

View File

@@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.title {
display: flex;
list-style: none;
}
.title .active {
color: red;
}
.title li {
margin-right: 30px;
}
.content {
display: flex;
list-style: none;
}
.content .active {
display: block;
}
.content li {
margin-right: 30px;
display: none;
}
</style>
</head>
<body>
<ul class="title">
<li class="">推荐</li>
<li>电视剧</li>
<li>电影</li>
<li>综艺</li>
</ul>
<ul class="content">
<li class="">推荐内容</li>
<li>电视剧内容</li>
<li>电影内容</li>
<li>综艺内容</li>
</ul>
</body>
<script>
function $(className) {
return document.querySelectorAll(className)
}
var title_li = $('.title li')
var content_li = $('.content li')
// console.log(title_li);能打印出来所以获取节点成功
title_li.forEach(function (item, index) {
// console.log('内容',item, index);title_li里li标签的内容和下标都打印出来,所以获取节点成功
// 绑定点击事件
item.onclick = function () {
// console.log('e',e.target.className);
// 判断数组里面被点击的值是否具有激活态,如果有则去除该值和其包含的内容的激活态
if(item.className == 'active'){
item.className = ''
content_li[index].className = ''
}
// 除此之外,给点击的没有的加上激活态,方法采取以下内容
else{
// 先清楚所有值的激活态
title_li.forEach(function (A, a) {
// A已经就是title_li里面具体的值了
A.className = ''
// 数组+下标可以取到数组里面具体的值,然后content_li是一个数组;
// 所以要想清楚里面li标签的类名,需要具体到某一个上值上,
// 加之title_li和content_li的下标是一致的,所以可以直接+[a]
content_li[a].className = ''
})
// 再给具体被点击到的值加上激活态
item.className = 'active'
content_li[index].className = 'active'
}
// 同上,是加上激活态
}
})
</script>
</html>

View File

@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>头部滚动固定</title>
<style>
body{
height: 1000px;
}
.header {
width: 100%;
height: 50px;
margin-top: 120px;
background: red;
}
/* 首先,顶部滑动到一定条件距离,会出现固定的状态。
因此,给这个状态添加一个类名;并通过js动态的在达成条件后加入此状态。 */
.position{
width: 100%;
position: fixed;
left: 0;
top: 0;
/* 顶部距离会受margin-top的影响,因此也要为0 */
margin-top: 0;
}
</style>
</head>
<body>
<div class="header"></div>
</body>
<!-- 首先判断,所谓的顶部header在父元素body上,实际上是没有变动的,变动的距离是父元素body到顶部的距离
因此变动的实际上是父元素。
思路:我们可以先获取body和header这个元素,然后通过判定body的scrollTop(滚动条的垂直位置,向下滑动值随之增大);
当scrollTop>margin-top120时,header和vh小于等于0,因此实现固定,否则就还是原有的header状态。 -->
<script>
function $(className){
return document.querySelector(className)
}
// 实际上,直接 $('.header') $('body')这样,就已经可以获取节点了
// 下面这样是为了简写和方便一点
// 1: 获取节点并赋值
var header = $('.header')
var body = $('body')
// 2: 绑定事件和处理函数
body.onscroll = function(){
// console.log(11);滚动显示11说明事件绑定成功
// document.documentElement.scrollTop包含整个html,我们所能看到的距离顶部的距离
if (document.documentElement.scrollTop >= 120){
// header position实际上就类似于公共css里面的类名直接追加到html上的书写方式
header.className = "header position"
}else{
header.className = "header"
}
}
</script>
</html>

View File

@@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
</head>
<body>
<div>
<input type="text" placeholder="请输入搜索关键字">
<!-- 空一个ul用来将空数组里存储的匹配值放到html上显示给用户选择 -->
<ul>
</ul>
</div>
</body>
<script>
// 这是推荐词组具体包含内容
var words = ['今天天气真好', 'html学习', '不喜欢html', '热爱学习', '天气不好,是阴天', '不喜欢学习'];
function $(className) {
return document.querySelector(className)
}
var input = $('input')
// console.log(input);能打印出来,所以获取节点成功
var ul = $('ul')
// 绑定事件:oninput用户输入事件
input.oninput = function () {
// console.log(input);能打印出来,绑定事件成功
var pipei = []
// 定义一个空数组来存储我输入内容能匹配上推荐词组里面相关的具体值
// 输入时触发,所以首先用if判断input里面有无输入值(由input.value获取具体文本值),有则执行下一个内容
// 用输入值的长度是否为0判断,有无输入值
if (input.value.length != 0) {
// console.log(input.value);能获取input里面具体输入的文本值,所以属性选择成功
// 有值则判断该值是否为定义词组所包含的值,因为定义词组是一个数组,所以需要循环比较数组里的每一项是否包含该值
words.forEach((value, index) => {
// console.log(value,index)//当输入时能获取定义词组里的每一项值,所以循环成功
// 拓展:indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置(即下标)。如果没有找到匹配的字符串则返回 -1。
// if判断是否为数组含有内容,用父 indexof 子 返回值判断,>-1则包含,
// 然后将数组符合值取出,追加到新数组里进行后续使用
if (value.indexOf(input.value) > -1) {
// 定义一个span标签放入用户输入的值,值的颜色变红
var span = `<span style="color: red;">${input.value}</span>`
// 拓展:直接使用“str.replace("需要替换的字符串","新字符串")”来替换;
// 定义一个li标签,便于将词组里面的每一项放入html上,供用户选择
// 然后在li标签定义词组里面,将用户输入的值替换标红的span标签
var li = `<li> ${ value.replace(input.value, span) } </li>`
// 完成以后,将数组符合值取出,追加到新数组里进行后续使用
pipei.push(li)
// var span = `<span style="color: red;">${ $("input").value }</span>`
// searchList.push(v.replace($("input").value, span))
}
})
// console.log(pipei);新组装数组打印成功,数组导入成功
}
// 清楚是为了删除上一次得到的结果。
// 例:在不加的情况下,我输入1,得到的结果是1的结果,然后我追加一个2,得到的结果是12.
// 以上总共得到的结果是1和12的结果。
// 然而应该得到的是当前输入的结果匹配的集合,即只需要给我12的结果就可以了。
// 空数组理由同上
ul.innerHTML = ''
// 具体着手操作,将ul、li添加到html
// 考虑到li的数量没办法确定,所以用循环来判断和控制li的数量
if (pipei.length > 0) {
pipei.forEach((item, ind) => {
ul.innerHTML += item
})
}
}
</script>
</html>

View File

@@ -0,0 +1,104 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
height: 100vh;
}
body,
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
ul {
width: 152px;
border-radius: 6px;
box-shadow: 2px 2px 9px #d7d7d7;
display: none;
position: fixed;
}
li {
height: 40px;
padding: 0 15px;
box-sizing: border-box;
line-height: 40px;
}
</style>
</head>
<body>
<ul>
<li>新建文件夹</li>
<li>上传文件</li>
<li>上传文件夹</li>
<li>刷新网页</li>
</ul>
</body>
<!-- 1 获取事件; 2 绑定事件; 3 事件处理函数。
(阻止默认事件:e.preventDefault();) (阻止事件冒泡(子元素冒泡):e.stopPropagation())
该事件:首先,阻止网页默认的右键菜单,并将自制菜单固定并隐藏在网页上;
其次,(e)监听鼠标的点击位置(x轴和y轴),通过判断右击菜单和vh、vw的距离来动态调整右击菜单。
甲方需求:自制一个右击菜单,然后通过获取鼠标点击的位置,给网页动态的加上右击菜单。 -->
<script>
// 返回值
function $(className) {
return document.querySelector(className)
}
// 返回数组
function _(className) {
return document.querySelectorAll(className)
}
var body = $('body')
var ul = $('ul')
// console.log(1);
// 判断给谁绑定事件:菜单在用户可视范围区域都能打开,所以不可能是给ul绑定,vh+vw=body。因此,是给body绑定右击菜单事件
// .oncontextmenu在用户点击鼠标右键打开上下文菜单时触发
body.oncontextmenu = function(e){
e.preventDefault();
var { x , y } = e
// console.log("x , y",x,y);
var { clientWidth , clientHeight } = document.body
// console.log('1,2',clientWidth , clientHeight);
// 判断:首先判断菜单会出现的情况,xy轴都不够即在屏幕角落,然后是x或者y单方面不够等三个特殊情况以及正常情况。
// 菜单长宽160,152;右边框:clientWidth-x<菜单宽度152,就放左边——怎么放:x-152其他同理
if(clientWidth - x < 152 && clientHeight - y < 160){
ul.style =
`left:${x-152}px;
top:${y - 160}px;
display:block`
}else if(clientWidth - x < 152){
ul.style =
`left:${x-152}px;
top:${y}px;
display:block`
}else if(clientHeight - y < 160){
ul.style =
`left:${x}px;
top:${y - 160}px;
display:block`
}else{
ul.style =
`left:${x}px;
top:${y}px;
display:block`
}
}
</script>
</html>

View File

@@ -0,0 +1,142 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
height: 100vh;
}
body,
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
span {
position: fixed;
}
</style>
</head>
<body>
<!-- 1 获取事件; 2 绑定事件; 3 事件处理函数。
该事件:首先:是词组的每一项在鼠标点击以后能出现在屏幕:
{1、定义词组;2、获取鼠标的x、y值,为其绑定点击事件;3、用js创建span标签用来存储定义词组里面的每一项;
4、span标签出现的xy轴位置是根据鼠标决定的,所以将获取的鼠标xy值给span标签,并在html显示; }
其次:设置动画。
甲方需求:通过鼠标点击屏幕按顺序循环出现定义词组里的每一项,并且每一项都会动态的向上运动一段距离以后消失不见 -->
</body>
<script>
// 返回值
function $(className) {
return document.querySelector(className)
}
// 返回数组
function _(className) {
return document.querySelectorAll(className)
}
var body = $('body')
var words = ['富强', '民主', '文明', '和谐', '自由', '平等', '公正', '法治', '爱国', '敬业', '诚信', '友善'];
var index = 0
body.onclick = function (e) {
var {
x,
y
} = e
// console.log('1,2',x,y);
var span = document.createElement("span");
span.innerText = words[index]
console.log(span);
index += 1
if (index > 11) {
index = 0
}
span.style = `
left: ${x}px;
top: ${y}px;
`;
body.appendChild(span)
var tops = span.style.top.split('px')[0] //点击的起始位置(split字符串分割)
// 开始思考怎么做动画
//元素上移过渡动画
// function moves(){
// // console.log('span',span.style.top.split('p'));
// var tops = span.style.top.split('px')[0] //点击的起始位置(split字符串分割)
// //分步处理到目标位置
// function toTop(){
// // debugger
// var now = Number(span.style.top.split('px')[0]) //当前位置
// if(now > tops-60){
// setTimeout(()=>{
// span.style.top = `${now - 1}px`
// toTop()
// },10)
// }else{
// body.removeChild(span)
// }
// }
// toTop()
// }
// function moves() {
// var now = Number(span.style.top.split('px')[0]) //当前位置
// if (now > tops - 60) {
// setTimeout(() => {
// span.style.top = `${now - 1}px`
// moves()
// }, 5)
// } else {
// setTimeout(function(){
// body.removeChild(span)
// },100)
// }
// }
var moveId = null;//用于保存 重绘动画 id 在取消动画时需要使用
function moves() {
var now = Number(span.style.top.split('px')[0]) //当前位置
if (now > tops - 60) {
span.style.top = `${now - 1}px`
// moves()
moveId = window.requestAnimationFrame(moves)//动画+(具体怎么处理)
} else {
window.cancelAnimationFrame(moveId)
setTimeout(function(){
body.removeChild(span)
},100)
}
}
moves()
}
</script>
</html>
<!-- 转化为number
'12px'.split('px')
(2) ['12', '']0: "12"1: ""length: 2[[Prototype]]: Array(0)
'12px'.split('px')[0]
'12'
Number('12px'.split('px')[0])
12
Number('12')
12 -->

View File

@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" placeholder="请输入文本">
<ul></ul>
</body>
<script>
// 1 获取事件; 2 绑定事件; 3 事件处理函数。
// 该事件:首先要获取用户输入的文本,需要先判断有无文本,有文本才能进行获取;
// 其次,文本获取后,要判断默认词组里是否有某一项与之匹配,随后将符合条件的词条统一放入html上;
// 甲方需求:将词库里和用户输入匹配上的关键词标红。
var words = ['今天天气真好', 'html学习', '不喜欢html', '热爱学习', '天气不好,是阴天', '不喜欢学习'];
// 1 获取事件
function $(className) {
return document.querySelector(className)
}
function _(className) {
return document.querySelectorAll(className)
}
var input = $('input')
var ul = $('ul')
// console.log(1);
// 2 绑定事件
input.oninput = function () {
// console.log(2);
var pipei = []
if (input.value.length > 0) {
words.forEach((value, index) => {
if (value.indexOf(input.value) > -1) {
// console.log("返回3",value, index);
var span = `<span style="color: red;">${input.value}</span>`
var li = `<li> ${ value.replace(input.value, span) } </li>`
pipei.push(li)
}
})
}
ul.innerHTML = ''
if (pipei.length > 0) {
pipei.forEach((item, ind) => {
ul.innerHTML += item
})
}
}
</script>
</html>

View File

@@ -0,0 +1,196 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
margin: 0;
padding: 0;
width: 100%;
height: 100vh;
}
img {
width: 80px;
height: 96px;
position: fixed;
top: -96px;
}
.dialog {
position: fixed;
width: 100%;
height: 100%;
background: #0000008c;
z-index: 9999;
display: none;
}
.center {
width: 40%;
background: #fff;
padding: 15px 10px;
border-radius: 4px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.title {
height: 40px;
line-height: 40px;
border-bottom: 1px solid #ebe9e9;
}
.content {
padding: 20px 0;
text-align: center;
}
.footer {
display: flex;
justify-content: flex-end;
}
.footer .ok {
padding: 3px 15px;
background: #2a6bf4;
color: #fff;
font-size: 13px;
border-radius: 4px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="dialog">
<div class="center">
<div class="title">提示</div>
<div class="content"></div>
<div class="footer">
<div class="ok">确定</div>
</div>
</div>
</div>
<!-- 1 获取事件; 2 绑定事件; 3 事件处理函数。
该事件:首先:红包随机出现在屏幕上:
1、获取屏幕的长宽,用来计算红包出现的位置;2、创建红包,引入红包图片,并给它设置在x轴上随机出现Math.random();
3、给红包绑定点击事件,并限制3次点击次数;3、点击确定红包消失;4、红包展现在html上;
其次:设置动画:1、红包从屏幕顶部上方随机生成,之后开始下落,完全下降到底部以后消失;
最后:打开并去除红包:1、红包被点击以后被打开;2、规定中奖几率和次数;3、点击确定按钮以后,关闭红包;4、红包随即消失;
甲方需求:屏幕上随机生成红包雨,用户可点击,点击时红包雨暂停,确定后该红包消失,红包雨继续。要规定中奖机率和抽奖次数 -->
</body>
<script>
//返回值
function $(className) {
return document.querySelector(className)
}
// 返回数组
function _(className) {
return document.querySelectorAll(className)
}
var dialog = $('.dialog')
var center = $('.center')
var content = $('.content')
var ok = $('.ok')
var body = $('body')
var {clientWidth,clientHeight} = document.body;
var click = 0
// 红包相关属性创建
function HB() {
var img = document.createElement("img");
var x = Math.random() * (clientWidth - 80)
img.src = "../hb.png";
img.style.left = `${x}px`;
img.style.top = '-96px'
img.onclick = function () {
clickImg = img
click += 1
//清除红包向下滚动定时器
_('img').forEach((value, index) => {
clearTimeout(value.time)
})
//清除创建红包定时器
clearInterval(createdNumber)
if (click > 3) {
content.innerText = "三次抽奖已经用完"
dialog.style.display = "block"
} else {
rate()
dialog.style.display = "block"
}
}
body.appendChild(img)
move(img)
}
// 定义中奖几率
function rate() {
var num = Math.random();
if (num > 0 && num <= 0.5) {
content.innerText = "恭喜您中了九折"
} else if (num > 0.5 && num <= 0.9) {
content.innerText = "恭喜您中了八折"
} else {
"恭喜您中了五折"
}
}
// 红包定时生成
createdNumber = setInterval(() => {
HB()
}, 1000)
// 红包运动
function move(tag) {
var now = Number(tag.style.top.split('px')[0])
if (now <= clientHeight) {
tag.time = setTimeout(() => {
tag.style.top = `${now + 3}px`
move(tag)
}, 15)
} else {
body.removeChild(tag)
}
}
// 红包关闭
ok.onclick = function (){
dialog.style.display = "none"
body.removeChild(clickImg)
//重新设置 创建红包定时器
createdNumber = setInterval(() => {
HB()
}, 1000)
//重新设置页面红包向下滚动
_('img').forEach((value, index) => {
value.time = setTimeout(() => {
move(value)
}, 15)
})
}
</script>
</html>

View File

@@ -0,0 +1,174 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
.title {
display: flex;
}
.title li {
margin-right: 10px;
}
.title .active {
color: red;
}
.content li {
display: none;
}
.content .active {
display: block;
}
</style>
</head>
<body>
<ul class="title"></ul>
<ul class="content"></ul>
</body>
<!-- 1 获取事件; 2 绑定事件; 3 事件处理函数。
思路:首先words里面的每一项都不是固定的,所以要考虑通过循环去加入到html中;
该事件:标题的内容: 首先,通过循环words得到里面的对象和下标,设置相关属性后,把它放到html上;
内容的内容: 同上 激活态还是通过下标实现同步-->
<script>
// 后端数据:
var words = [{
title: '首页',
content: [{
text: '首页的内容1'
},
{
text: '首页的内容2'
},
{
text: '首页的内容3'
},
{
text: '首页的内容4'
},
{
text: '首页的内容5'
},
]
},
{
title: '社会',
content: [{
text: '社会 的内容1'
},
{
text: '社会 的内容2'
},
{
text: '社会 的内容3'
},
]
},
{
title: '军事',
content: [{
text: '军事 的内容1'
},
{
text: '军事 的内容2'
},
{
text: '军事 的内容3'
},
]
},
{
title: '科技',
content: [{
text: '科技 的内容1'
},
{
text: '科技 的内容2'
},
{
text: '科技 的内容3'
},
]
}
]
//返回值
function $(className) {
return document.querySelector(className)
}
// 返回数组
function _(className) {
return document.querySelectorAll(className)
}
var title = $('.title')
var content = $('.content')
contentAll()
function titleAll() {
// 循环添加title的内容,并且判断title的class是否需要添加激活态
words.forEach((value, index) => {
title.innerHTML += `<li class="${index == 0 ? 'active':''}">${value.title}</li>`
})
// console.log(words);
var titleli = _(".title li")
var contentli = _(".content li")
// title里面的的内容也不确定,所以进行循环,并给里面的每一个对象绑定点击事件,然后同旧版样式,先清除再添加激活态
titleli.forEach((v, i) => {
v.onclick = function () {
titleli.forEach((valueli, index) => {
valueli.className = ''
contentli[index].className = ''
})
v.className = 'active'
contentli[i].className = 'active'
}
})
}
// 然后开始考虑如何插入li标签里的具体内容,同样不确定,用循环
function contentAll() {
// 同上,循环词组插入content的li标签,然后再li标签里面再循环插入li标签里面的具体文本
words.forEach((value, index) => {
content.innerHTML += `<li class="${index == 0 ? 'active':''}">${
// 这里将进行array.map(function(当前值, 下标))
// toString() 方法返回字符串。
// replaceAll()字符串替换。
value.content.map( v => { return `<p>${v.text}</p>` }).toString().replaceAll(',','')
}</li>`
})
}
titleAll()
</script>
</html>

View File

@@ -0,0 +1,161 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
var orderData = [
{
name: '路易斯女装旗舰店',
shopList: [{
img: '../img/22/产品图.png',
info: {
shopName: '真丝连衣裙2019春夏新款杭州大牌气质修……',
color: '黑白',
size: 'L',
price: '160.00',
number: '1'
}
}
],
remark: '12333',
postage: '0',
amount: '1000.00'
},
{
name: '路易斯女装旗舰店',
shopList: [{
img: '../img/22/产品图.png',
info: {
shopName: '真丝连衣裙2019春夏新款杭州大牌气质修……',
color: '黑白',
size: 'L',
price: '160.00',
number: '1'
}
},
{
img: '../img/22/产品图.png',
info: {
shopName: '真丝连衣裙2019春夏新款杭州大牌气质修……',
color: '黑白',
size: 'L',
price: '160.00',
number: '2'
}
}
],
remark: '12333',
postage: '0',
amount: '1000.00'
},
{
name: '路易斯女装旗舰店',
shopList: [{
img: '../img/22/产品图.png',
info: {
shopName: '真丝连衣裙2019春夏新款杭州大牌气质修……',
color: '黑白',
size: 'L',
price: '160.00',
number: '1'
}
},
{
img: '../img/22/产品图.png',
info: {
shopName: '真丝连衣裙2019春夏新款杭州大牌气质修……',
color: '黑白',
size: 'L',
price: '160.00',
number: '2'
}
},
{
img: '../img/22/产品图.png',
info: {
shopName: '真丝连衣裙2019春夏新款杭州大牌气质修……',
color: '黑白',
size: 'L',
price: '160.00',
number: '2'
}
}
],
remark: '',
postage: '0',
amount: '1000.00'
}
]
var box = $('#goodsBox')
function createData() {
orderData.forEach((v, i) => {
inner(v,box)
})
}
function inner(v,dom){
dom .innerHTML += `
<li class="goods">
<div class="goods_title">
<img class="l" src="../img/22/矢量智能对象.png" alt="">
<span>${v.name}</span>
<img class="r" src="../img/22/-e-右.png" alt="">
</div>
<ul>
${
v.shopList.map(key => { return `
<li class="information">
<img src="${ key.img }" alt="">
<div class="des">
<p>${key.info.shopName}</p>
<div class="up">
<span>颜色:${key.info.color}</span>
<span>尺码:${key.info.size}</span>
</div>
<div class="down">
<div class="number">
¥<span class="one">${key.info.price.split('.')[0]}</span>
<span class="two">.${key.info.price.split('.')[1]}</span>
</div>
<div class="amount">X${key.info.number}</div>
</div>
</div>
</li>
` })
}
</ul>
<div class="remarkes">
<p class="three">订单备注</p>
<p class="four">${ v.remark ? v.remark : '有什么想对商家留言的可以在这里说' }</p>
</div>
<div class="cost">
<div class="cost_up">
<p>优惠抵用</p>
<span>-¥5</span>
</div>
<div class="cost_down">
<p>快递费用</p>
<span>${v.postage>0?v.postage:'免费包邮'}</span>
</div>
</div>
<div class="money">
<p>商品金额</p>
<span>¥${v.amount}</span>
</div>
</li>
`
}
window.onload = createData
</script>
</html>

View File

@@ -0,0 +1,245 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body,
ul,
li {
margin: 0;
padding: 0;
}
.main {}
.main ul {
overflow: hidden;
}
.main ul li {
display: flex;
height: 45px;
align-items: center;
position: relative;
padding: 0 15px;
border-bottom: 1px solid #f4f0f0;
transition-duration: 0.3s;
}
.main .item {
width: 100%;
}
.main .action {
display: flex;
align-items: center;
height: 100%;
position: absolute;
right: -180px;
}
.main .action .item {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 0 14px;
color: #fff;
}
.action .top {
background: #c8c7cd;
}
.action .read {
background: #ff9c00;
}
.action .delete {
background: #ff3a31;
}
</style>
</head>
<body>
<div class="main">
<ul>
<li>
<div class="item">新闻1</div>
<div class="action">
<div class="item top">置顶</div>
<div class="item read">未读</div>
<div class="item delete">删除</div>
</div>
</li>
<li>
<div class="item">新闻2</div>
<div class="action">
<div class="item top">置顶</div>
<div class="item read">未读</div>
<div class="item delete">删除</div>
</div>
</li>
<li>
<div class="item">新闻3</div>
<div class="action">
<div class="item top">置顶</div>
<div class="item read">未读</div>
<div class="item delete">删除</div>
</div>
</li>
</ul>
</div>
</body>
<!-- 1 获取事件; 2 绑定事件; 3 事件处理函数。
思路:侧滑按钮,默认固定在屏幕右侧固定-180px,首先,要监听屏幕,获取x值,通过手指触摸屏幕的滑动距离来判断左滑、右滑,
该事件:标题的内容: 首先,通过循环words得到里面的对象和下标,设置相关属性后,把它放到html上;
内容的内容: 同上 激活态还是通过下标实现同步-->
<script>
// 事件的传递有两种方式:冒泡与捕获。
// 在冒泡中,内部元素的事件会先被触发,然后再触发外部元素; 【从里到外】
// 在捕获中,外部元素的事件会被先触发,然后才会触发内部元素的事件。【从外到里】
// 一、addEventListener()与removeEventListener()用于处理指定和删除事件处理程序操作。
// 它们都接受3个参数:如 addEventListener("事件名" , "事件处理函数" , "布尔值"); (注:事件名不含"on",如“click”)
// 现在的版本可以省略第三个参数,默认值为false.
// 总结:
// 1:相同事件绑定和解除,需要使用共用函数;绑定和解除事件时 事件没有"on" 即onclick写成click
// 2:共用函数不能带参数;
// 二.addEventListener()与removeEventListener()的第三个参数详解
// 布尔值参数是true,表示在捕获阶段调用事件处理程序;就是最不具体的节点先接收事件,最具体的节点最后接收事件
// 如果是false,在冒泡阶段调用事件处理程序;则是先寻找指定的位置,由最具体的元素接收,然后逐级向上传播至最不具体的
// 元素的节点(文档)
// 总结:
// 1:true的触发顺序总是在false前面
// 2:如果多个均为true,则外层触发先于内层
// 3:如果多个均为false,则内层触发先于外层
// 触点坐标选取
// touchstart和touchmove使用: e.targetTouches[0].pageX 或 (jquery)e.originalEvent.targetTouches[0].pageX
// touchend使用: e.changedTouches[0].pageX 或 (jquery)e.originalEvent.changedTouches[0].pageX
//返回值
function $(className) {
return document.querySelector(className)
}
// 返回数组
function _(className) {
return document.querySelectorAll(className)
}
var mainli = _('.main ul li')
var startX = 0
mainli.forEach(function (value, index) {
value.addEventListener('touchstart', function (event) {
// console.log('event.targetTouches[0]', event.targetTouches[0].screenX);
startX = event.targetTouches[0].screenX;
mainli.forEach(function (V, i) {
if (i != index) {
V.style.transform = `translateX(0px)`;
}
})
})
value.addEventListener('touchmove', function (event) {
var moveX = event.targetTouches[0].screenX;
// 在没有任何操作的情况下,起始状态都是关上的即false,也就是open取反
// 先判断右滑还是左滑,再判断是打开状态还是关闭状态,(定义value.open,true是打开,false是关上)。
// 然后打开的情况下,x值的计算以及再关上的状态下x轴的计算。
// 左滑
if(moveX < startX){
// 状态默认关闭
if (!value.open){
var x = moveX - startX
// 左滑打开成功
if(x < -180){
value.style.transform =`translateX(-180px)`
}else{
// 左滑打开失败
value.style.transform =`translateX(${x}px)`
}
value.open = true
}
// 右滑(movex > startx)
}else{
// 状态默认打开
if (value.open){
var newX = (moveX - startX) + (-180)
// 右滑关闭失败
if (newX <= 0){
value.style.transform =`translateX(${newX})px`
}else{
// 右滑关闭成功
value.style.transform =`translateX(0px)`
}
}
}
})
value.addEventListener('touchend', function (event) {
console.log('event.targetTouches', event);
var endX = event.changedTouches[0].screenX;
// 阈值
var distenceX = endX - startX
// 左滑
if (startX > endX) {
// 打开成功
if (distenceX < -60) {
value.style.transform = `translateX(-180px)`;
// 打开失败
} else {
value.style.transform = `translateX(0px)`;
value.open = false
}
// 右滑
} else {
// 打开成功
if (distenceX > 60) {
value.style.transform = `translateX(0px)`;
// 打开失败
} else {
value.style.transform = `translateX(-180px)`;
value.open = false
}
}
})
})
</script>
</html>

View File

@@ -0,0 +1,302 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body,
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
.header {
width: 100%;
height: 45px;
position: fixed;
left: 0;
right: 0;
top: 0;
background: #fff;
z-index: 999;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
box-sizing: border-box;
border-bottom: 1px solid #dadada;
}
.header img {
width: 15px;
height: 20px;
transform: scale(0.6);
}
.content {
margin-top: 45px;
/* touch-action: none; */
}
.content li {
height: 40px;
display: flex;
align-items: center;
border-bottom: 1px solid #dadada;
padding: 0 10px;
}
.refresh {
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
position: fixed;
left: 50%;
z-index: 998;
background: #fff;
border-radius: 100%;
box-shadow: 0px 0px 9px #858585;
margin-left: -15px;
transition: all 0.1s;
}
.refresh img {
width: 100%;
height: 100%;
}
.rotate {
animation: rotateAction 1s linear infinite;
}
@keyframes rotateAction {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div class="header">
<img src="../../../作业/img/64/左.png" alt="">
<span>热门视频</span>
<span></span>
</div>
<ul class="content">
<li>列表1</li>
<li>列表2</li>
<li>列表3</li>
<li>列表4</li>
<li>列表5</li>
<li>列表6</li>
<li>列表7</li>
<li>列表8</li>
<li>列表9</li>
<li>列表10</li>
<li>列表11</li>
<li>列表12</li>
<li>列表13</li>
<li>列表14</li>
<li>列表15</li>
<li>列表16</li>
<li>列表17</li>
<li>列表18</li>
<li>列表19</li>
<li>列表20</li>
<li>列表21</li>
<li>列表22</li>
<li>列表23</li>
<li>列表24</li>
<li>列表25</li>
<li>列表26</li>
<li>列表27</li>
<li>列表28</li>
<li>列表29</li>
<li>列表30</li>
<li>列表31</li>
<li>列表32</li>
<li>列表33</li>
<li>列表34</li>
<li>列表35</li>
<li>列表36</li>
<li>列表37</li>
<li>列表38</li>
<li>列表39</li>
<li>列表40</li>
</ul>
<div class="refresh" style="top: 10px;">
<img src="../../../作业/img/64/朋友圈.png" alt="">
</div>
</body>
<!-- 1 获取事件; 2 绑定事件; 3 事件处理函数。 -->
<!-- 思路:首先刷新这个方法是在滚动条到顶部的时候才会触发,因此要先判断滚动条是否在顶部,
然后再去调用该方法。然后去生成下拉刷新这一项功能:首先监听它的y值,开始/移动/结束
三过程,在移动的时候,为避免滚动条和下拉刷新事件冲突,因此要设置
避免默认事件e.preventDefault();
甲方需求:当滚动条到达顶部时,达到阈值,下拉刷新,否则无法触发该事件。 -->
<script>
// 知识拓展:pageX/pageY:
// 鼠标相对于整个页面的X/Y坐标。
// 注意,整个页面的意思就是你整个网页的全部。
// 比如说网页很宽很长,宽2000px,高3000px,那pageX,pageY的最大值就是它们了。
// screenX/screenY:
// 鼠标在屏幕上的坐标。screenX,screenY的最大值不会超过屏幕分辨率。
// function isTop() {
// if(document.documentElement.scrollTop === 0){
// return true
// }else{
// return false
// }
// // return document.documentElement.scrollTop === 0 ? true : false
// }
// if (isTop()) {
// addMove();
// } else {
// window.addEventListener('scroll', ()=>{
// // () => isTop() ? addMove() : ''
// if( isTop() ){
// addMove()
// }
// })
// }
function $(className) {
if (document.querySelectorAll(className).length > 1) {
return document.querySelectorAll(className)
} else {
return document.querySelector(className)
}
}
// 首先判断是否到达顶部,到达顶部返回true,否则false,定义一个方法判断顶部。
// 当在顶部的时候,调用刷新方法,不是顶部的时候,再为空。
function ifTop() {
if (document.documentElement.scrollTop == 0) {
return true
} else {
return false
}
}
// 判断是否为true,是就调用方法,不是则监听判断是否为0,是的时候调用
if (ifTop()) {
Refresh();
console.log('Refresh');
} else {
window.addEventListener('scroll', function () {
if (ifTop()) {
console.log('scroll',ifTop());
Refresh()
}
})
}
var startY = 0, moveY = 0, endY = 0;
function Refresh() {
// 获取开始的Y值
$('.content').addEventListener('touchstart', (e) => {
startY = e.targetTouches[0].pageY
console.log('touchstart');
});
// 获取移动的y值,首先判断页面状态,是true才继续下一步
$('.content').addEventListener('touchmove', (e) => {
console.log('touchmove',ifTop());
// 页面状态true
if (ifTop()) {
// 获取移动的y值
moveY = e.targetTouches[0].pageY
// 判断是否为下拉
if (moveY > startY) {
console.log('preventDefault');
// 防止向下浏览和向下刷新冲突,故阻止默认事件
e.preventDefault();
// 获取移动距离
var distanceY = moveY - startY;
// 当移动距离在100以内时,改变图标距离
if (distanceY <= 120) {
// 120*3=360跟手刚好一圈
$('.refresh').style = `
top:${distanceY}px;
transform:rotate(${distanceY * 3}deg);`;
console.log(distanceY);
}
}
}
});
// 获取结束y值
$('.content').addEventListener('touchend', (e) => {
// if(!ifTop()) return;
// 特别注意这里是changedTouches!!!!
var endY = event.changedTouches[0].pageY;
var distanceY = endY - startY;
if (distanceY <= 50) {
$('.refresh').style = `
top:10px;
transform:rotate(0deg);`;
}else {
// 添加了一个rotate包含了 animation: rotateAction 1s linear infinite;
// 以及@keyframes rotateAction,从0到360
$(".refresh").className = "refresh rotate"
// top: 80px;是为了固定图标悬浮转动的位置,无论大与小都固定在80px开始旋转
$('.refresh').style = `
top: 80px;
transform: rotate(0deg);`;//手动将旋转角度清为0,因为@keyframes rotateAction是从0开始
//如果不清0,旋转会从上次的值跳到0在开始
// 定时器,2秒以后再消失恢复默认
setTimeout(() =>{
$('.refresh').style = `
top: 10px;
transform: rotate(0}deg);`;
$(".refresh").className = "refresh"
},2000)
}
})
}
</script>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
.main img {
width: 200px;
}
</style>
</head>
<body>
<div class="main"></div>
</body>
<script src="./index.js"></script>
</html>

View File

@@ -0,0 +1,89 @@
const { Server } = require("socket.io");
//初始化
const io = new Server(3000, {
// 端口 路径 适配器 连接超时等等
});
//!!!数据分组!!!!
//群信息保存
var onlineUser = {
// "groupName":[
// {
// name:"",
// ronm:"",
// img:"",
// type:""//1群主 2管理 3成员
// }
// ]
}
//聊天记录八平村
var chatRecord = {
// "groupName":[
// {
// // name:"",
// // ronm:"",
// // img:"",
// // type:""//1群主 2管理 3成员
// }
// ]
}
//!!!前后端连接同样也要分组!!!!
io.on("connection", (socket) => {
console.log("客户端建立连接了...");
//监听登录页面
socket.on("UserLogin", function (arg) {
console.log(arg);
//群已存在 3群成员
if (onlineUser.hasOwnProperty(arg.room)) {
arg.type = 3
//创建群 1群主 建立群数组为空
} else {
arg.type = 1
onlineUser[arg.room] = []
}
//保存登陆数据
onlineUser[arg.room].push(arg);
//将客户端添加到相同的room里
socket.join(arg.room);
//系统消息 欢迎新人
io.in(arg.room).emit("SystemMessage", `欢迎${arg.name}加入群聊`);
// console.log("onlineUser",onlineUser);
});
//服务器监听消息发送消息
socket.on("sendMessage", (arg) => {
//判断聊天记录是否是第一次建立
if (!chatRecord.hasOwnProperty(arg.room)) {
//是 则追加一个room为空用于存储后续相关数据
chatRecord[arg.room] = []
}
//将聊天记录保存
chatRecord[arg.room].push(arg)
//服务器推送消息
//除开发送者将详细推送给房间内所有人
socket.to(arg.room).emit("PushMessage", arg);
})
//监听在线成员询问事件
socket.on("getOnlineUser", (arg) => {
io.in(arg.room).emit("PushOnlineUser", onlineUser[arg.room]);
})
//【2后端】服务器监听窗口抖动
socket.on("SetShake", (arg) => {
socket.to(arg.room).emit("PushShake");
});
socket.on("disconnect", () => {
console.log("客户端断开连接了...");
})
});

View File

@@ -0,0 +1,164 @@
{
"name": "backend",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/component-emitter": {
"version": "1.2.11",
"resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz",
"integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ=="
},
"@types/cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
},
"@types/cors": {
"version": "2.8.12",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz",
"integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw=="
},
"@types/node": {
"version": "18.0.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz",
"integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ=="
},
"accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"requires": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
}
},
"base64id": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
},
"component-emitter": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
},
"cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
},
"cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"requires": {
"object-assign": "^4",
"vary": "^1"
}
},
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"requires": {
"ms": "2.1.2"
}
},
"engine.io": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz",
"integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==",
"requires": {
"@types/cookie": "^0.4.1",
"@types/cors": "^2.8.12",
"@types/node": ">=10.0.0",
"accepts": "~1.3.4",
"base64id": "2.0.0",
"cookie": "~0.4.1",
"cors": "~2.8.5",
"debug": "~4.3.1",
"engine.io-parser": "~5.0.3",
"ws": "~8.2.3"
},
"dependencies": {
"ws": {
"version": "8.2.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA=="
}
}
},
"engine.io-parser": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
"integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg=="
},
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"requires": {
"mime-db": "1.52.0"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
},
"socket.io": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.1.tgz",
"integrity": "sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ==",
"requires": {
"accepts": "~1.3.4",
"base64id": "~2.0.0",
"debug": "~4.3.2",
"engine.io": "~6.2.0",
"socket.io-adapter": "~2.4.0",
"socket.io-parser": "~4.0.4"
}
},
"socket.io-adapter": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz",
"integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg=="
},
"socket.io-parser": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz",
"integrity": "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==",
"requires": {
"@types/component-emitter": "^1.2.10",
"component-emitter": "~1.3.0",
"debug": "~4.3.1"
}
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
},
"ws": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz",
"integrity": "sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ=="
}
}
}

View File

@@ -0,0 +1,16 @@
{
"name": "backend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node-dev index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"socket.io": "^4.5.1",
"ws": "^8.8.0"
}
}

View File

@@ -0,0 +1,17 @@
x64:
firstOrDefaultFilePatterns:
- '!**/node_modules'
- '!build{,/**/*}'
- '!build{,/**/*}'
- '*'
- package.json
- '!**/*.{iml,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,suo,xproj,cc,d.ts,pdb}'
- '!**/._*'
- '!**/electron-builder.{yaml,yml,json,json5,toml}'
- '!**/{.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,.DS_Store,thumbs.db,.gitignore,.gitkeep,.gitattributes,.npmignore,.idea,.vs,.flowconfig,.jshintrc,.eslintrc,.circleci,.yarn-integrity,.yarn-metadata.json,yarn-error.log,yarn.lock,package-lock.json,npm-debug.log,appveyor.yml,.travis.yml,circle.yml,.nyc_output}'
- '!.yarn{,/**/*}'
- '!.editorconfig'
- '!.yarnrc.yml'
nodeModuleFilePatterns:
- '**/*'
- '*'

View File

@@ -0,0 +1,16 @@
directories:
output: ./build
buildResources: build
appId: com.abandon.qq
productName: Abandon
asar: false
copyright: Copyright © 2022 abandon
extends: null
files:
- filter:
- ./*
win:
icon: ./logo.ico
target:
- msi
electronVersion: 19.0.8

View File

@@ -0,0 +1,21 @@
Copyright (c) Electron contributors
Copyright (c) 2013-2020 GitHub Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Some files were not shown because too many files have changed in this diff Show More