自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(2953)
  • 收藏
  • 关注

原创 javascript七基础学习系列二千二百一十二:设置游标方向

在使用"prev"或"prevunique"打开游标时,每次调用continue()或advance()都会在对象存。openCursor()方法实际上可以接收两个参数,第一个是IDBKeyRange 的实例,第二个是表示方。通常,游标都是从对象存储的第一条记录开始,每次调用continue()或advance()都。注意,openCursor()的第一个参数是null,表示默认的键范围是所有值。createIndex()的第一个参数是索引的名称,第二个参数是索引属性的名称,第三个参数是包含。

2024-08-22 15:10:25 327

原创 javascript七基础学习系列二千二百一十一:键范围

这个例子只会输出从键为"007"的记录开始到键为"ace"的记录结束的对象,比上一节的例子要少。这个方法接收四个参数:下限的键、上限的键、这个范围保证只获取键为"007"的值。// 从"007"的下一条记录开始,到"ace"的前一条记录停止。// 从"007"的下一条记录开始,到"ace"记录停止。// 从"007"记录开始,到"ace"的前一条记录停止。// 从"007"记录开始,到"ace"记录停止。// 从"007"的下一条记录开始,直到最后。// 从头开始,到"ace"的前一条记录为止。

2024-08-22 15:09:38 181

原创 javascript七基础学习系列二千二百一十:通过游标查询

记录,这个属性中保存着IDBCursor 的实例(有下一条记录时)或null(没有记录时)。记录时,onsuccess 事件处理程序最后一次被调用,此时event.target.result 等于null。这两个方法都会让游标重用相同的请求,因此也会重用onsuccess 和onerror 处理程序,直至不。update()方法使用指定的对象更新当前游标对应的值。要创建另一个请求,必须调用下列中的一个方法。如果事务没有修改对象存储的权限,update()和delete()都会抛出错误。

2024-08-22 15:08:50 290

原创 javascript七基础学习系列二千二百零九:事务

然后,可以使用add()和put()方法添加和更新对象,使用get()取得对象,使用delete()删除对象,其中,get()和delete()方法都接收对象键作为参数,这5 个方法都创。种情况下,add()会导致错误,而put()会简单地重写该对象。有了事务的引用,就可以使用objectStore()方法并传入对象存储的名称以访问特定的对象存储。拿到了对象存储的引用后,就可以使用add()或put()写入数据了。即要存储的对象,并把对象保存到对象存储。这两个方法只在对象存储中已存在同名的键时有区别。

2024-08-22 15:04:58 133

原创 javascript七基础学习系列二千二百零八:IndexedDB

使用IndexedDB 数据库的第一步是调用indexedDB.open()方法,并给它传入一个要打开的数据。不存在,open()操作会创建一个新数据库,然后触发upgradeneeded 事件。IndexedDB 的设计几乎完全是异步的。为此,大多数操作以请求的形式执行,这些请求会异步执行,开数据库期间发生错误,event.target.errorCode 中就会存储表示问题的错误码。如果给定名称的数据库已存在,则会发送一个打开它的请求;如果数据库存在,而你指定了一个升级版的版本号,则会立。

2024-08-22 13:53:20 191

原创 javascript七基础学习系列二千二百零七:localStorage 对象

要了解关于Web Storage 限制的更多信息,可以参考dev-test.nemikor 网站的“Web Storage Support。在修订的HTML5 规范里,localStorage 对象取代了globalStorage,作为在客户端持久存储。不同浏览器给localStorage 和sessionStorage 设置了不同的空间限制,但大多数会限制为每。因为localStorage 是Storage 的实例,所以可以像使用sessionStorage 一样使用。具体的限制取决于特定的浏览器。

2024-08-22 13:52:49 118

原创 javascript七基础学习系列二千二百零六:sessionStorage 对象

因为sessionStorage 对象是Storage 的实例,所以可以通过使用setItem()方法或直接给属。对于少量数据,这里的差别可以忽略不计,但对于大量数据,就可以注意到IE 中JavaScript 恢复执行的。sessionStorage 对象只存储会话数据,这意味着数据只会存储到浏览器关闭。sessionStorage 对象中的数据只能由最初存储数据的页面使用,在多页应用程序中的用处有限。老版IE 以异步方式实现了数据写入,因此给数据赋值的时间和数据写入磁盘的时间可能存在延迟。

2024-08-22 13:52:17 215

原创 javascript七基础学习系列二千二百零五:通信错误

如,在个性化的主页上,比如Gmail,可能包含多个相互独立的功能模块。随着Ajax 编程的出现,Web 应用程序在运行期间动态加载数据和功能成为常见的情形。如果在某个条件下,环聊功能不工作了,就不能算重大错误,因为这不是应用程序。一个模块的init()方法出错,数组中其后的所有模块都不会被初始化。好的代码设计意味着应用程序某个部分的错误不会影响其他部分,实际上根本不应该相关。表面上看,这段代码没什么问题,就是依次调用每个模块的init()方法。逻辑上,这样写代码是不合适的,因为每个模块相互独立,各自功能。

2024-08-22 13:51:41 53

原创 javascript七基础学习系列二千二百零四:数据类型错误

reverseSort()函数可以使用数组的sort()和reverse()方法,将数组反向排序。最后一个reverseSort()是安全的,它测试了values 参数是不是Array 的实例。法,但参数本身不是数组,那么在执行reverse()时也会报告错误。的用法,不一定要检查每个参数的数据类型,但对外的任何API 都应该做类型检查以保证正确执行。在前面的例子中,代码检查了第三个参数的数据类型,以确保它是字符串,但根本没有检查另外两。在这个重写的版本中,第一步检查了传入的值确实是字符串。

2024-08-22 13:51:09 278

原创 javascript七基础学习系列二千二百零三:识别错误

分析器会比较注解和JavaScript 代码的各个部分,对在实际运行时可能出现的潜。同样,对于1 和true 的比较也类似。不得不说的是,通过在代码构建流程中添加静态代码分析或代码检查器(linter),可以预先发现非。类型的,不会验证函数参数,所以很多错误只有在代码真正运行起来时才会出现。在这个重写的版本中,if 语句的条件会基于比较操作返回布尔值。类型转换错误的主要原因是使用了会自动改变某个值的数据类型的操作符或语言构造。假如第三个参数是数值0,if 条件判断就会失败,而数值1 则会导致满足条件。

2024-08-22 13:50:33 174

原创 javascript七基础学习系列二千二百零二:error 事件

况下,只有错误消息有用,因为URL 就是当前文档的地址,而行号可能指嵌入JavaScript 或外部文件中的。相反,会传入3 个参数:错误消息、发生错误的URL 和行号。会触发error 事件。早期支持的事件,为保持向后兼容,很多浏览器保持了其格式不变。通过返回false,这个函数实际上就变成了整个文档的try/catch 语句,可以捕获所有未处理的。然后,浏览器的默认行为就会生效,像往常一样显示这条错误消息。在任何错误发生时,无论是否是浏览器生成的,都会触发error 事件并执行这个事件处理程序。

2024-08-22 13:50:02 268

原创 javascript七基础学习系列二千二百零一:何时抛出错误

但是,如果是一个复杂的Web 应用程序,有几千行JavaScript 代码,想要找到错误的原因就会很难。在编写一个可能用于很多应用程序的JavaScript 库,或者一个会在应用程序的很多地方用到的实用函数,对于上面的一个函数来说,通过这样的错误消息调试还是很容易的。在这个重写后的函数中,如果values 参数不是数组就会抛出错误。架构的底层抛出,在这个层面上,人们对正在进行的流程知之甚少,因此无法真正地处理错误。至于抛出错误与捕获错误的区别,可以这样想:应该只在确切知道接下来该做什么的时候捕获错。

2024-08-22 13:49:31 196

原创 javascript七基础学习系列二千二百:try/catch 的用法

这个函数报告错误,就有必要通过try/catch 语句把该函数调用包装起来,对可能的错误进行处理。当try/catch 中发生错误时,浏览器会认为错误被处理了,因此就不会再使用本章前面提到的机。如果你明确知道自己的代码会发生某种错误,那么就不适合使用try/catch 语句。换句话说,浏览器会像通常一样报告这个错误,最终显示这个自定义错误。如果应用程序的用户不懂技术,那么他们即使看到错误也看不懂,这是一个理想的结果。使用throw 操作符时,代码立即停止执行,除非try/catch 语句捕获了抛出的值。

2024-08-22 13:49:00 241

原创 javascript七基础学习系列二千一百九十九:错误类型

Error 是基类型,其他错误类型继承该类型。因此,所有错误类型都共享相同的属性(所有错误对象上的方法都是这个默认类型定义的方法)。EvalError 类型的错误会在使用eval()函数发生异常时抛出。最后一种错误类型是URIError,只会在使用encodeURI()或decodeURI()但传入了格式错误的。TypeError 在JavaScript 中很常见,主要发生在变量不是预期类型,或者访问不存在的方法时。这个类型并不是代码中通常要处理的错误,如果真发生了这种错误,很可能代码哪里弄错。

2024-08-22 13:48:24 212

原创 javascript七基础学习系列二千一百九十八:try/catch 语句

ECMA-262 也指定了定义错误类型的name 属性,目前所有浏览器中都有这个属性。Chrome 和Opera 中都有的属性,尽管每个浏览器添加了其他属性。如果出错并执行catch 块中的代码,则finally 块中的代码仍执行。因为它在try 块中,不会导致错误。但是,finally 块的存在导致try 块中的return 语句被忽略。如果try 块中有代码发生错误,代码会立即退出执行,并跳到catch 块中。finally 子句,catch 块就成了可选的(它们两者中只有一个是必需的)。

2024-08-22 13:47:44 209

原创 javascript七基础学习系列二千一百九十七:错误处理与调试

作步骤,比如Chrome 的操作步骤参见Google Developers 网站的文章《Android 设备的远程调试入门》,如前所述,当网页中的JavaScript 脚本发生错误时,不同浏览器的处理方式不同。JavaScript 一直以来被认为是最难调试的编程语言之一,因为它是动态的,且多年来没有适当的开。在前面提到的所有浏览器中,访问开发者工具的路径是相似的。然后,就可以在对应的桌面浏览器中查看错误了。多数上网的人没有技术背景,甚至连什么是浏览器都不十分清楚,而且有的人不知道自己使用的是什么。

2024-08-21 16:46:53 383

原创 javascript七基础学习系列二千一百九十六:使用对称密钥加密和解密

SubtleCrypto 对象支持使用公钥和对称算法加密和解密消息。 postMessage() API 支持从不同源跨文档发送消息,同时保证安全和遵循同源策略。 Encoding API 用于实现字符串与缓冲区之间的无缝转换(越来越常见的操作)。加密消息需要传入参数对象以指定算法和必要的值、加密密钥和要加密的数据。 媒体元素和拥有自己的API,用于操作音频和视频。 File API 提供了发送、接收和读取大型二进制对象的可靠工具。 Streams API 支持以全新的方式读取、写入和处理数据。

2024-08-21 16:46:13 182

原创 javascript七基础学习系列二千一百九十一:使用SubtleCrypto 对象

SHA-256”、"SHA-384"或"SHA-512"指定。范支持其中3 种:SHA-256、SHA-384 和SHA-512。生成的消息摘要可以是256 位(SHA-256)、TextDecoder 是经常与SubtleCrypto 一起使用的类,用于实现二进制数据与字符串之间的相互转换。384 位(SHA-384)或512 位(SHA-512)。通常,在使用时,二进制的消息摘要会转换为十六进制字符串格式。这个对象包含一组方法,用于执行常见的密码学功能,如加密、散列、签名和生成密钥。

2024-08-21 16:45:42 213

原创 javascript七基础学习系列二千一百九十:Web Cryptography API

所谓“伪”指的是生成值的过程不是真的随机。被称为置换循环(permutation cycle),而这个循环的长度被称为一个周期(period)。要使用CSPRNG 重新实现Math.random(),可以通过生成一个随机的32 位数值,然后用它去除。PRNG 生成的值只是模拟了随机的特性。由于算法本身是固定的,其输入只是之前的状态,因此随机数顺序也是确定的。者知道PRNG 的内部状态,就可以预测后续生成的伪随机值。明显比常规PRNG 慢很多,但CSPRNG 生成的值就很难预测,可以用于加密了。

2024-08-21 16:45:04 342

原创 javascript七基础学习系列二千一百八十九:反射自定义元素属性

类似地,CustomElementRegistry.whenDefined()方法会返回一个期约,当相应自定义元素。如果自定义元素已经有定义,那么CustomElementRegistry.get()方法会返回相应自定义元素。自定义元素既是DOM 实体又是JavaScript 对象,因此两者之间应该同步变化。连接到DOM的元素在自定义元素有定义时会自动升级。并非始终可以先定义自定义元素,然后再在DOM 中使用相应的元素标签。// 在自定义元素有定义之前会创建HTMLUnknownElement 对象。

2024-08-21 16:44:31 286

原创 javascript七基础学习系列二千一百八十八:添加Web 组件内容

 disconnectedCallback():在每次将这个自定义元素实例从DOM中移除时调用。 connectedCallback():在每次将这个自定义元素实例添加到DOM 中时调用。这样可以在自定义元素中实现高度的HTML 和代码重用,以及DOM封装。 constructor():在创建元素实例或将已有DOM 元素升级为自定义元素时调用。因为每次将自定义元素添加到DOM 中都会调用其类构造函数,所以很容易自动给自定义元素添加。可以在自定义元素的不同生命周期执行代码。使用自定义元素生命周期方法。

2024-08-21 16:43:59 309

原创 javascript七基础学习系列二千一百八十七:事件重定向

当然,这些元素默认也不会做任何通用HTML 元素不能做的事。如果自定义元素继承了一个元素类,那么可以使用is 属性和extends 选项将标签指定为该自定义。建自定义的、复杂的和可重用的元素,而且只要使用简单的HTML 标签或属性就可以创建相应的实例。自定义元素为HTML 元素引入了面向对象编程的风格。逃出后,事件就好像是由影子宿主本身而非真正的包装元素触发的一样。注意,事件重定向只会发生在影子DOM中实际存在的元素上。元素不会发生事件重定向,因为从技术上讲,这些元素仍然存在于影子DOM 外部。

2024-08-21 16:43:25 176

原创 javascript七基础学习系列二千一百八十六:合成与影子DOM 槽位

带有slot="foo"属性的元素会被投射到带有name="foo"的上。注意,虽然在页面检查窗口中看到内容在影子DOM中,但这实际上只是DOM内容的投射(projection)。位于影子宿主中的HTML需要一种机制以渲染到影子DOM中去,但这些HTML又不必属于影子DOM树。影子DOM 一添加到元素中,浏览器就会赋予它最高优先级,优先渲染它的内容而不是原来的文本。现在,投射进去的内容就像自己存在于影子DOM 中一样。在这个例子中,由于影子DOM是空的,因此。会在1000 毫秒后变成空的。

2024-08-21 16:42:54 216

原创 javascript七基础学习系列二千一百八十五:使用影子DOM

把影子DOM添加到元素之后,可以像使用常规DOM一样使用影子DOM。来看下面的例子,这里。影子DOM 并非铁板一块。// 检查元素是否移动到了影子DOM 中。// 从父DOM 中移除元素。// 把元素添加到影子DOM。

2024-08-21 16:42:17 106

原创 javascript七基础学习系列二千一百八十四:影子DOM

概念上讲,影子DOM(shadow DOM) Web 组件相当直观,通过它可以将一个完整的DOM 树作为节点添加到父DOM 树。这样可以实现DOM 封装,意味着CSS 样式和CSS 选择符可以限制在影子DOM子树而不是整个顶级DOM树中。影子DOM 与HTML 模板很相似,因为它们都是类似document 的结构,并允许与顶级DOM 有一定程度的分离。不过,影子DOM 与HTML 模板还是有区别的,主要表现在影子DOM的内容会实际渲染到页面上,而HTML 模板的内容不会。

2024-08-21 16:41:25 212

原创 javascript七基础学习系列二千一百八十三:使用<template>标签

注意,在前面的例子中,DocumentFragment 的所有子节点都高效地转移到了foo 元素上,转移。脚本执行可以推迟到将DocumentFragment 的内容实际添加到DOM 树。下面的例子演示了这个。之后DocumentFragment 变空了。如果新添加的元素需要进行某些初始化,这种延迟执行是有用的。

2024-08-21 16:40:47 369

原创 javascript七基础学习系列二千一百八十二:Web 组件

相反,更好的方式是提前在页面中写出特殊标记,让浏览器自动将其解析为DOM子树,但跳过渲染。这正是HTML 模板的核心思想,而标签正是为这个目的而生的。比如,我们想以最快的方式给某。由于存在这些问题,因此使用Web 组件通常需要引入一个Web 组件库,比如Polymer。 并没有统一的“Web Components”规范:每个Web 组件都在一个不同的规范中定义。这里所说的Web 组件指的是一套用于增强DOM 行为的工具,包括影子DOM、自定义。在浏览器中渲染时,上面例子中的文本不会被渲染到页面上。

2024-08-21 16:40:16 252

原创 javascript七基础学习系列二千一百八十一:Navigation Timing API

Navigation Timing API 提供了高精度时间戳,用于度量当前页面加载速度。浏览器会在导航事件发生时自动记录PerformanceNavigationTiming 条目。加载资源时自动记录PerformanceResourceTiming。这个对象会捕获大量时间戳,用于描述资源加。Resource Timing API 提供了高精度时间戳,用于度量当前页面加载时请求资源的速度。通过计算并分析不同时间的差,可以更全面地审视浏览器加载页面的过程,发现可能存在的性能瓶颈。何时以及如何加载的。

2024-08-21 16:39:46 333

原创 javascript七基础学习系列二千一百八十:Performance Timeline API

Performance Timeline API 使用一套用于度量客户端延迟的工具扩展了Performance 接口。这个返回的集合代表浏览器的性能时间线(performance timeline)。浏览器会自动记录各种PerformanceEntry 对象,而使用performance.mark()也可以记录自定。除了自定义性能条目,还可以生成PerformanceMeasure(性能度量)条目,对应由名字作为标。值,而封装这个时间戳的对象是PerformanceEntry 的实例。

2024-08-21 16:39:16 254

原创 javascript七基础学习系列二千一百七十九:计时API

window.performance.now(),这个方法返回一个微秒精度的浮点值。因此,使用这个方法先后捕获的时间戳更不可能出现相等的情况。Date.now()只有毫秒级精度,如果foo()执行足够快,则两个时间戳的值会相等。打开页面或创建工作线程时,performance.now()就会从0 开始计时。始化时可能存在时间差,因此不同上下文之间如果没有共享参照点则不可能直接比较performance.now()。Date.now()方法只适用于日期时间相关操作,而且是不要求计时精度的操作。

2024-08-21 16:38:22 353

原创 javascript七基础学习系列二千一百七十八:通过管道连接流

从内部看,ReadableStream 先把自己的值传给TransformStream 内部的。WritableStream,然后执行转换,接着转换后的值又在新的ReadableStream 上出现。流可以通过管道连接成一串。注意,这里的管道连接操作隐式从ReadableStream 获得了一个读取器,并把产生的值填充到。// 每1000 毫秒生成一个递增的整数。// 每1000 毫秒生成一个递增的整数。// 从连接流的输出获得读取器。// 通过管道连接流。

2024-08-20 11:51:04 310

原创 javascript七基础学习系列二千一百七十七:转换流

转换流用于组合可读流和可写流。数据块在两个流之间的转换是通过transform()方法完成的。// 每1000 毫秒生成一个递增的整数。// 每1000 毫秒生成一个递增的整数。// 每1000 毫秒生成一个递增的整数。

2024-08-20 11:50:33 393

原创 javascript七基础学习系列二千一百七十六:可写流

可写流是底层数据槽的封装。底层数据槽处理通过流的公共接口写入的数据。

2024-08-20 11:49:58 401

原创 javascript七基础学习系列二千一百七十五:WebGL1 与WebGL2

第二种是3D 上下文,也就是WebGL。WebGL 是浏览器对OpenGL ES 2.0 的实现。requestAnimationFrame 是简单但实用的工具,可以让JavaScript 跟进浏览器渲染周期,从而更。HTML5 的元素为JavaScript 提供了动态创建图形的API。是游戏图形开发常用的一个标准。在WebGL2 中,很多扩展都变成了默认功能。 支持定型数组,限定数组中包含数值的类型;目前所有主流浏览器的较新版本都已经支持标签。// 没有扩展的代码。 创建和操作纹理。

2024-08-20 11:49:28 171

原创 javascript七基础学习系列二千一百七十四:影子DOM

概念上讲,影子DOM(shadow DOM) Web 组件相当直观,通过它可以将一个完整的DOM 树作为节点添加到父DOM 树。这样可以实现DOM 封装,意味着CSS 样式和CSS 选择符可以限制在影子DOM子树而不是整个顶级DOM树中。影子DOM 与HTML 模板很相似,因为它们都是类似document 的结构,并允许与顶级DOM 有一定程度的分离。不过,影子DOM 与HTML 模板还是有区别的,主要表现在影子DOM的内容会实际渲染到页面上,而HTML 模板的内容不会。

2024-08-20 11:48:58 340

原创 javascript七基础学习系列二千一百七十三:使用<template>标签

注意,在前面的例子中,DocumentFragment 的所有子节点都高效地转移到了foo 元素上,转移。脚本执行可以推迟到将DocumentFragment 的内容实际添加到DOM 树。下面的例子演示了这个。之后DocumentFragment 变空了。如果新添加的元素需要进行某些初始化,这种延迟执行是有用的。

2024-08-20 11:48:28 359

原创 javascript七基础学习系列二千一百七十二:Web 组件

相反,更好的方式是提前在页面中写出特殊标记,让浏览器自动将其解析为DOM子树,但跳过渲染。这正是HTML 模板的核心思想,而标签正是为这个目的而生的。比如,我们想以最快的方式给某。由于存在这些问题,因此使用Web 组件通常需要引入一个Web 组件库,比如Polymer。 并没有统一的“Web Components”规范:每个Web 组件都在一个不同的规范中定义。这里所说的Web 组件指的是一套用于增强DOM 行为的工具,包括影子DOM、自定义。在浏览器中渲染时,上面例子中的文本不会被渲染到页面上。

2024-08-20 11:47:58 378

原创 javascript七基础学习系列二千一百七十一:编写着色器

浏览器并不理解原生GLSL 代码,因此GLSL 代码的字符串必须经过编译并链接到一个着色器程序中。GLSL 是一种类似于C 的语言,专门用于编写OpenGL 着色器。这个着色器创建了一个新的包含4 项的数组(vec4),个着色器定义了一个uniform,包含颜色的4 个组件(vec4),保存在uColor 中。片段着色器必须返回一个值,保存到变量gl_FragColor 中,这个值表示绘制时使用的颜色。片段着色器与顶点着色器类似,只不过是通过uniform 传入数据。uColor 的值在着色器内不能改变。

2024-08-20 11:47:23 180

原创 javascript七基础学习系列二千一百七十:缓冲区

创建缓冲区要调用gl.createBuffer()方法,并使用gl.bindBuffer()方法将缓冲区绑定到。因此,调用gl.bufferData()虽然没有包含对buffer 的直接引用,但仍然是。如果WebGL 代码没有产出想要的输出结果,那么可以调用几次getError(),这样有可能帮你找到问题所在。法后,调用gl.getError()方法。调用gl.bindBuffer()将buffer 设置为上下文的当前缓冲区。gl.bufferData()方法的最后一个参数表示如何使用缓冲区。

2024-08-20 11:46:36 305

原创 javascript七基础学习系列二千一百六十九:常量

在WebGL 中,context 对象上的常量则不包含GL_前缀。中的glClear()方法。参数gl.COLOR_BUFFER_BIT 告诉WebGL 使用之前定义的颜色填充画布。OpenGL(同时也是WebGL)中的很多方法会包含相关的数据类型信息。以上代码把清理颜色缓冲区的值设置为黑色,然后调用clear()方法,这个方法相当于OpenGL。参数的方法,会通过方法名的后缀体现这些信息。表示参数数量的数字(1~4)在先,表示数据类型的。参数,而gl.uniform3i()表示需要3 个整数值参数。

2024-08-20 11:46:05 166

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除