IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 前端 _ jQuery 之 小白版 ( 下 ) -> 正文阅读

[JavaScript知识库]前端 _ jQuery 之 小白版 ( 下 )

1.?jQuery?发送?ajax?请求 :

+?jQuery?内的?ajax?封装模式就是按照?回调函数?和?promise?两种形式进行封装的

+?你使用的时候,?可以按照 回调函数 的形式使用,?也可以按照?promise?的形式使用

?1.?ajax( )

+?专门用来发送?ajax?请求的方法

+?使用不需要选择到元素

+?语法:?$.ajax({?对本次请求的配置信息?})

=>?url :?必填 ,?表示 请求地址

=>?method?:?选填,?表示 请求方式 (默认是?GET)

??~>?method?可以写成?type?也可以写成?method

=>?data :?选填,?表示携带给后端的 参数 (默认是?空字符串)

??~>?在?jquery?内,?不光可以写查询字符串格式

??~>?也可以直接书写?对象?数据类型

=>?async :?选填,?表示是否 异步 (默认是?true?,?表示异步)

=>?dataType?:?选填,?表示是否 解析 后端返回的数据,

默认是?'string'?不解析,?选填?' json '?表示解析

=>?success :?选填,?表示 成功 的回调函数

=>?error :?选填,?表示 失败 的回调函数?(?jquery?认为失败就是失败?)

??~>?失败可以不光是请求失败

??~>?如果解析失败也会走失败?error?的回调函数

=>?timeout :?选填,?默认是?true(?表示永久?),?可以选填一个数字,?表示 超时时间 ,?单位是?ms

=>?cache :?选填,?表示是否 缓存?,?在发送?ajax?请求的时候默认是?true,?表示缓存

??~>?选填为?false?的时候,?表示不缓存

??~>?额外给你添加一个参数叫做?_?,?值是?时间戳

=>?context :?选填,?表示?ajax?回调函数的 上下文?,?回调函数内的?this?指向

??~>?默认是?jquery?自己封装的?ajax?对象

??~>?可以自己调整,?填写任意内容

=>?headers :?选填,?默认是没有,?当你需要额外设置 请求头 信息的时候

??~>?可以在这个?headers?内书写

??~>?注意:?headers?的值是一个?对象数据类型,

把你要设置的请求头直接书写在对象内就可以了

// ( 1 )
$.ajax({
  url: './ajax',    // 必填 , 请求的地址
  method: 'POST',   // 选填 , 请求的方式(默认是'GET')
  data: { name: 'Jack', age: 18 },// 选填, 发送请求时携带的参数
  dataType: 'json', // 选填, 默认是 string ,不解析, 'json'表示解析
  success: function (res) { console.log(res) }  // 选填, 成功的回调函数
})
// ( 2 )按照 promise 的形式书写
$.ajax({
  url: './ajax',    // 必填 , 请求的地址
  method: 'POST',   // 选填 , 请求的方式(默认是'GET')
  data: { name: 'Jack', age: 18 },// 选填, 发送请求时携带的参数
  dataType: 'json' // 选填, 默认是 string ,不解析, 'json'表示解析
}).then(res => console.log(res))  // 选填, 成功的回调函数
// ( 3 )
async function fn() {
  const res = await $.ajax({
    url: './ajax',    // 必填 , 请求的地址
    method: 'POST',   // 选填 , 请求的方式(默认是'GET')
    data: { name: 'Jack', age: 18 },// 选填, 发送请求时携带的参数
    dataType: 'json' // 选填, 默认是 string ,不解析, 'json'表示解析
  })
  console.log(res)
}
fn()
const obj = { name: '我是自己创建的一个 obj 对象' }
$.ajax({
  url: './ajax',
  method: 'GET',
  data: { name: 'Jack', age: 18 },
  dataType: 'json',
  success: function (res) { console.log('成功', this) },
  error: function (xhr, err, info) {
    // xhr: jquery 封装的 ajax 对象
    // err: 错误信息
    // info: 错误信息的描述
    console.log('请求失败了')
    console.log(xhr)
    console.log(err)
    console.log(info)
  },
  // 表示超过 1000ms 服务器还没有给出响应, 那么直接取消请求, 认定请求失败
  timeout: 1000,
  // 会在请求发送的时候, 额外添加一个参数
  // 表示不缓存, 会给你添加一个参数, 叫做时间戳
  cache: false,
  // 表示把 success 回调函数内的 this 指向 obj 这个对象
  context: obj,
  // 表示你所有需要额外设置的请求头信息
  headers: {
    authorization: 'abcdef',
    abc: 100
  }
})

1. $.get( ) - 专门发送 get 请求的方法

+ 语法: $.get(请求地址, 携带的参数, 回调函数, 是否解析)
? ? ? ? ? =>?携带的参数: 可以选填, 可以是查询字符串, 也可以是 对象
? ? ? ? +?按照 promise 和 回调函数 两种方式封装的

// 1. 发送一个 get 请求
$.get('./ajax.php', 'a=100&b=200', res => console.log(res), 'json')

2. $.post( ) - 专门发送 post 请求的方法

+ 语法: $.post(请求地址, 携带的参数, 回调函数, 是否解析)
?? ??? ??? ?=> 携带的参数: 可以选填, 可以是查询字符串, 也可以是 对象
? ? ? ? + 按照 promise 和 回调函数 两种方式封装的

// 2. 发送一个 post 请求
$.post('./ajax.php', { username: 'zhangsan', password: '123456' }).then(res => console.log(res))

2.?jQuery?发送?jsonp?请求 :?

回顾?+?jsonp?原理?:
+?利用?script?标签能把请求回来的内容当做?js?代码执行
+?利用?src?不受同源策略的影响
+?要求:
=>?后端返回的是一个可以执行的合法的?js?代码
=>?后端返回的内容是一个?'函数名(数据)'?这样的字符串
=>?前端在发送请求的时候,?把准备好的函数名给到后端

使用的方法是? $.ajax( )
+ 要求: dataType 必须写成 'jsonp'
? => dataType 你写成 json 或者 string 的时候, 都是发送 ajax 请求
? => dataType 你写成 jsonp 的时候, 就不会发送 ajax 请求了,?
? 而是 创建 script 标签 发送 jsonp 请求
+ 注意: 在配置项内有两个专门为 jsonp 请求设置的配置项
? 1. 会自动帮你添加一个参数叫做 callback, 表示我准备好的回调函数
?? ?=> 名字是 jquery 随机组成的
?? ?=> 名字可以修改
?? ?=> 使用 jsonpCallback 字段 : 表示函数名
? 2. jquery 默认添加的字段名字叫做 callback
?? ?=> 表示给后端传递回调函数名的字段
?? ?=> 可以修改的
?? ?=> 使用 jsonp 字段修改
? 3. cache 缓存机制
?? ?=> 当你发送 ajax 请求的时候, cache 默认值是 true, 表示缓存,?
?? ?不会添加一个时间戳作为参数
?? ?=> 当你发送 jsonp 请求的时候, cache 默认值是 false, 表示不缓存,?
?? ?会添加一个时间戳作为参数

$.ajax({
  url: './jsonp.php',
  // 表示发送一个 jsonp 请求
  dataType: 'jsonp',
  // success: function (res) { console.log(res) },
  jsonpCallback: 'fn',  // jsonp 请求的时候回调函数的名称
  jsonp: 'cb' // 表示在参数中把 回到函数的 字段名改成 cb
})
function fn(res) {
  console.log('我是 fn 函数')
  console.log(res)
}
// 百度搜索引擎
$.ajax({
      url: 'https://www.baidu.com/sugrec',
      data: {
        pre: 1,
        p: 3,
        ie: 'utf-8',
        json: 1,
        prod: 'pc',
        from: 'pc_web',
        sugsid: '34099,33970,34004,33855,33607,26350,22159',
        wd: 'a',
        req: 2,
        csor: 1
      },
      // 表示发送一个 jsonp 请求
      dataType: 'jsonp',
      // 表示我准备好的函数叫做 fn 函数
      jsonpCallback: 'fn',
      // 表示在参数中把 回到函数的 字段名改成 cb
      jsonp: 'cb',
      cache: true,
      success (res) {
        console.log(res)
      }
    })

3. jQuery?内的全局?ajax?生命周期函数 :

+?也叫作?ajax?的?钩子函数

1.?ajaxStart(?)?-?请求开始

??+?语法:?$(window).ajaxStart(function?()?{})

??+?时机:?同一个作用域下的第一个?ajax?发送的时候,?会触发执行

2.?ajaxSend(?)?-?发送之前

??+?语法:?$(window).ajaxSend(function?()?{})

??+?时机:?会在每一个请求发送出去之前?触发执行

3.?ajaxSuccess(?)?-?成功之后

??+?语法:?$(window).ajaxSuccess(function?()?{})

??+?时机:?会在每一个请求成功了之后?触发执行

4.?ajaxError(?)?-?失败之后

??+?语法:?$(window).ajaxError(function?()?{})

??+?时机:?会在每一个请求失败了之后?触发执行

5.?ajaxComplete(?)?-?完成之后

??+?语法:?$(window).ajaxComplete(function?()?{})

??+?时机:?会在每一个请求完成之后?触发执行,?不管成功还是失败,?都是完成

6.?ajaxStop(?)?-?请求结束

??+?语法:?$(window).ajaxStop(function?()?{})

??+?时机:?同一个作用域下的最后一个?ajax?完成以后,?触发执行

// 1. ajaxStart() - 请求开始
$(window).ajaxStart(function () { console.log('第一个请求发送之前, ajax 开始') })
// 2. ajaxSend() - 发送之前
$(window).ajaxSend(function () { console.log('有一个请求发送出去了') })
// 3. ajaxSuccess() - 成功之后
$(window).ajaxSuccess(function () { console.log('有一个请求成功了^_^') })
// 4. ajaxError() - 失败之后
$(window).ajaxError(function () { console.log('有一个请求失败了') })
// 5. ajaxComplete() - 完成之后
$(window).ajaxComplete(function () { console.log('有一个请求完成') })
// 6. ajaxStop() - 请求结束
$(window).ajaxStop(function () { console.log('最后一个请求完成了') })

?案例 :?利用钩子函数完成一个 loading 效果

button {
  padding: 20px;
  font-size: 20px;
}
div {
  width: 100%;
  height: 100%;
  position: fixed;
  left: 0;
  top: 0;
  background-color: rgba(255, 255, 255, .5);
  display: flex;
  justify-content: center;
  align-items: center;
  display: none;
}
<button>发送请求</button>
<div class="loading">
  <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fhbimg.b0.upaiyun.com%2F16f7121aedf9990f3ddd8725e99fe4d8369e06692d18-J0TUcl_fw658&refer=http%3A%2F%2Fhbimg.b0.upaiyun.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1630134491&t=e1a2d516e36c3b9be945e4faebf565da" alt="">
</div>
<script src="./jquery/jquery.min.js"></script>
// 1. 什么时候开始显示 loading 效果
// 只要有一个请求发送出去, 就要显示
$(window).ajaxSend(() => $('.loading').css('display', 'flex'))
// 2. 什么时候小时 loading 效果
// 只要有一个请求完成了, 就要消失
$(window).ajaxComplete(() => $('.loading').hide())
// 3. 点击按钮发送请求
//(可自己配置一个 ajax.php 文件, 需要在本地打开)
$('button').click(() => {
  $.get('./ajax.php')
})

可将网络切换到弱的 3G 状态下, 查看效果更佳 :?


4.?jQuery?的入口函数 :

+ 语法: $(window).ready(function () { ... })
+ 注意: 会在页面 DOM 结构加载完毕后执行
+ 类似于: window.onload = function () {}
+ 区别:
? => window.onload 是所有 资源 加载完毕后触发
? => jQuery 入口函数是只要 html 结构加载完毕就触发了
+ 简写:
? => jQuery 的入口函数有一个简写形式
? => $(function () { ... })

<img src="https://img2.baidu.com/it/u=3228549874,2173006364&fm=26&fmt=auto&gp=0.jpg" alt="">
<script src="./jquery/jquery.js"></script>
// 1. 入口函数
// 1-1. onload
window.onload = function () { console.log('页面所有资源加载完毕') }
// 1-2. 入口函数
$(window).ready(function () {
  console.log('jQuery 的入口函数')
  console.log('DOM 结构加载完毕了')
})
// 入口函数简写 :
$(function () {
  console.log('入口函数')
  console.log('DOM 结构加载完毕了')
})

5.?jQuery?的多库并存 :

+?如果你引入了别的框架插件等第三方文件内容也是使用? $? 和? jQuery? 这个名字

+?那么你把?jQuery?引入在最后面

+?通过?jQuery?的?语法来还原?$?和?jQuery

+?jQuery?可以交出?$?和?jQuery?的控制权给别人

?1.?还原?$

+?语法:?$.noConflict( )

??+?这个代码一旦执行,就会让出?$?这个变量的控制权

??+?jQuery?不再占用?$?这个名字了

? $.noConflict( )??

2.?还原?$?和?jQuery

+?语法:?$.noConflict(true)

??+?这个代码一旦执行,?就会让出?$?和?jQuery?的控制权

??+?jQuery?不再占用?$?和?jQuery?这两个名字了

??$.noConflict(true)??

3.?直接定义行的控制权

??+?直接接受?$.noConflict( )?的 返回值 ,?就是新的控制权

??+?你自己定义一个新的名字当做?jQuery?的名字

??const love?=?$.noConflict(true)??


6.?jQuery?实现深浅拷贝 :

1. 深浅拷贝

+?在复制一个数据类型的时候(特指复杂数据类型,?数组或者对象)

+?在?JS?内,?对于?"复制"?有三个级别 :

??1.?赋值

??2.?浅拷贝

??3.?深拷贝

1.?赋值 :

??+?简单的地址复制

??+?使用?赋值符号( = )?进行的操作

??+?对于基本数据类型,?赋值之后两个变量之间没有任何关系

??+?对于复杂数据类型,?赋值之后两个变量操作同一个数据存储空间

// 1. 赋值
let n1 = 5
// 把 n1 的值赋值给了 n2
let n2 = n1
console.log(n1, n2)    // 5  5
n2 = 10
console.log(n1, n2)    // 5  10

const o1 = { name: 'Jack' }
// 进行赋值操作, 把 o1 的值赋值给了 o2
// 因为 o1 这个变量内存储的是指向一个 对象数据类型 的空间地址
// 赋值的过程中, 就是把 o1 存储的地址赋值给了 o2
// 所以给到 o2 的依旧是一个 地址
// 从此以后 o1 和 o2 操作一个对象存储空间
const o2 = o1
console.log(o1, o2)
// 使用任意一个变量名修改对象空间内的成员
o2.name = 'Rose'
console.log(o1, o2)

?

?


2.?浅拷贝 :

=>?创建一个和原先数据结构一模一样的数据结构

+ 假如原先是个数组数据类型,?那么就新创建一个数组

+?假如原先是个对象数据类型,?那么就新创建一个对象

=>?通过?for?in?循环去遍历原先数据结构

+?把里面的每一个数据分别在新的数据结构中复制一份

+?对于一维数据结构有效

+?如果是多维数据结构,没有意义?,?那么从第二维度开始,?依旧是操作同一个存储空间

// 2. 浅拷贝
const o1 = { name: 'Jack', age: 18, info: { height: 180 } }
// 2-1. 创建一个和原先数据结构一模一样的结构
const o2 = {}
// 2-2. 循环遍历原始数据结构
for (const key in o1) {
  // 2-3. 分别在新的数据结构中进行赋值
  // 在进行 for in 遍历的时候
  // 在这里, 当 key === info 的时候
  // o1[key] 存储的也是一个地址
  // o2[key] 就是把 o1[key] 存储的地址复制了一份过去
  // 从此以后, o1 和 o2 虽然是两个数据空间
  // 但是 o1.info 和 o2.info 操作的是一个数据空间
  // o2.info = o1.info
  // 因为 info 内存储的是一个 地址
  // 赋值以后, o2.info 和 o1.info 存储的是同一个地址
  o2[key] = o1[key]
}
// 此时 o1 和 o2 不是一个对象存储空间
// 只是长得一模一样的两个对象存储空间
// 用任意一个区操作的时候, 另外一个不会改变
console.log(o1, o2)

// 修改
o2.name = 'Rose'
o2.age = 20
console.log(o1, o2)

// 修改第二维度 info 内的数据
o2.info.height = 200
console.log(o1, o2)


知识点扩展 :

// 准确的判断所有数据类型
// 语法: Object.prototype.toString.call(你要判断的数据类型)
// 返回值: 该数据类型的 类型字符串 '[object 类型]'
console.log(Object.prototype.toString.call({}))       //     Object
console.log(Object.prototype.toString.call([]))       //     Array
console.log(Object.prototype.toString.call(123))      //     Number
console.log(Object.prototype.toString.call('123'))    //     String
console.log(Object.prototype.toString.call(true))     //     Boolean
console.log(Object.prototype.toString.call(null))     //     Null
console.log(Object.prototype.toString.call(undefined))//     Undefined
console.log(Object.prototype.toString.call(/^$/))     //     RegExp
console.log(Object.prototype.toString.call(new Date()))//    Date
console.log(Object.prototype.toString.call(function () {}))//Function

?

// 如果一个数据是数组数据类型
// 那么当你访问他的 constructor 的时候, 自己没有, 就要去自己的 __proto__ 上查找
// 数组的 __proto__ 就是 Array.prototype
// Array.prototype 上面的 constructor 就是 Array

// 如果一个数据是对象数据类型
// 那么当你访问他的 constructor 的时候, 自己没有, 就要去自己的 __proto__ 上查找
// 对象的 __proto__ 就是 Object.prototype
// Object.prototype 上面的 constructor 就是 Object


3.?深拷贝 :

=>?不停地重复浅拷贝的工作

=>?复制出一份完全一模一样的数据结构

=>?不管多少维度的数据结构,?都能完整独立的复制过来

=>?实现方式:

+?使用?递归?的方式进行逐层数据结构的?遍历数据并赋值

+?当我循环遍历的时候,?如果碰到的还是复杂数据类型

+?那么就递归进行遍历

// 3. 深拷贝
const o1 = {
  name: 'Jack',
  age: 18,
  info: {
    weight: 180,
    height: 180,
    desc: {
      msg: '这个人很懒, 什么都没有留下!'
    }
  },
  hobby: ['吃饭', '睡觉', ['篮球', '足球']]
}
const o2 = {}
// 3-1. 书写函数来完成(递归函数)
// 使用递归的方式进行深拷贝
function deepCopy(o2, o1) {
  // 做: 把 o1 内的所有数据全部拷贝到 o2 内部
  // console.log(o1, o2)
  //3-2. 直接循环遍历 o1 数据
  for (let key in o1) {
    // console.log(key);
    // 判断, 如果是 对象数据类型 或者 数组数据类型, 不进行赋值
    // 否则, 才进行赋值
    // 如果 o1[key] 是一个对象数据类型
    // o2[key] 也要创建为一个对象数据类型
    // 如果 o1[key] 是一个数组数据类型
    // o2[key] 也要创建为一个数组数据类型
    // 如果 o1[key] 是一个基本数据类型
    // o2[key] 直接赋值
    if (Object.prototype.toString.call(o1[key]) === '[object Object]') {
      // 是对象
      // console.log('o1[key] 是一个对象数据类型 : ', key)
      o2[key] = {}
      // 在这个位置, o1[key] 是一个对象数据类型
      // o2[key] 也是一个数据类型
      // o1[key] 里面的每一个数据复制一份到 o2[key]
      deepCopy(o2[key], o1[key])
    } else if (o1[key].constructor === Array) {
      // 是数组
      // console.log('o1[key] 是一个数组数据类型 : ', key)
      o2[key] = []
      // 把 o1[key] 内部的所有数据放在 o2[key] 内
      deepCopy(o2[key], o1[key])
    } else {
      // console.log('o1[key] 是一个基本数据类型 : ', key)
      // 直接复制
      o2[key] = o1[key]
    }
  }
}
// 将来使用的时候
deepCopy(o2, o1)
console.log(o1, o2)
// 修改数据
o2.info.desc.msg = 'hello world'

4.?深拷贝?-?方案2

??+?只能是在?对象?和?数组?数据结构中使用

??+?不能有函数

??+?利用?json?格式字符串

??4-1.?把源数据转换成 json?格式字符串

??4-2.?把?json?格式字符串转换回?js?数据类型

// 4. 深拷贝 - 方案2
const o1 = { name: 'Jack', age: 18, info: { weight: 180, height: 180, desc: { msg: '你好 世界' } }, hobby: [ '吃饭', '睡觉' ] }
console.log(o1)
// 把 o1 转换成 json 格式字符串
// 现在的 jsonStr 就是基本数据类型
const jsonStr = JSON.stringify(o1)
console.log(jsonStr)
// 把 s 转换成一个 JS 的对象格式
const o2 = JSON.parse(jsonStr)
console.log(o2)
// 修改
o2.info.desc.msg = 'hello world'
console.log(o1, o2)

jQuery 内有实现深浅拷贝的方法 :
+ $.extend( )

const o1 = {
  name: 'Jack',
  age: 18,
  info: {
    weight: 180,
    height: 180,
    desc: {
      msg: '这个人很懒, 什么都没有留下!',
      title: '你好 世界'
    }
  },
  hobby: [ '吃饭', '睡觉', [ '篮球', '羽毛球', '足球' ] ]
}

+ 浅拷贝 :
? => 语法: $.extend(对象1, 对象2, 对象3, ...)
? => 作用: 把从 对象2 开始的所有对象内的数据进行浅拷贝到 对象1 内
? => 实现的是浅拷贝

// 1. 实现浅拷贝
// 把 o1 内的所有数据进行浅拷贝到 o2 身上
let o2 = {}
$.extend(o2, o1)
console.log(o1, o2)
// 修改一下数据
o2.name = 'Rose'
// 第二维度修改
o2.info.height = 200
console.log(o1, o2)

+ 深拷贝:
? => 语法: $.extend(true, 对象1, 对象2, 对象3, ...)
? => 作用: 把从 对象2 开始的所有对象内的数据进行深拷贝到 对象1 内
? => 实现的是深拷贝

// 2. 实现深拷贝
let o2 = {}
$.extend(true, o2, o1)
// console.log(o1, o2)
// 修改
o2.name = 'Tom'
o2.info.height = 250
o2.info.desc.msg = '这个人更懒'
console.log(o1, o2)


jQuery 简图 : ( 下?)?

总结一下 :?$(?)?

??1.?$('选择器')?=>?获取页面元素

??2.?$(DOM节点)?=>?把?DOM?节点转换成?jquery?的元素集合

??3.?$('html?结构字符串')?=>?创建节点

??4.?$(函数)

????=>?jQuery?的入口函数,?会在?DOM?结构加载完毕后执行

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-01 14:24:51  更:2021-08-01 14:25:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 22:33:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码