当半夜睡不着,翻出qq的历史个性签名
当半夜睡不着,翻出qq的历史个性签名,我想起了十年前自己那些qq个性签名,如“不要迷恋哥,哥只是个传说。”、“你若安好,便是晴天”等,尬的我脚趾抠出三室一厅。

那么本次要给大家带来的就是如何实现个性签名的就地编辑 ,如哔哩哔哩的个性签名
前言
在网络社交的舞台上,个性签名如同一张精心设计的名片,不仅展现了个人的独特性格与审美情趣,还悄然透露出持有人当下的心境、生活哲学或是对世界的独特见解。它可能是几句诗词,隐含着对美好生活的向往;或许是电影台词,折射出个人的价值观念与精神追求;亦或是一段简洁有力的独白,直抒胸臆,表达着当前的情绪状态。
实战解析
存储知识
首先我们需要掌握一些存储知识:
HTML5 Local Storage(本地存储)
HTML5 Local Storage 是一种在客户端(即用户的浏览器)存储数据的技术,它允许web应用在用户的浏览器上保存数据,即使在关闭浏览器窗口或重启浏览器之后,这些数据依然存在。这对于提升用户体验非常有用,因为它可以帮助应用记住用户的偏好设置、登录状态或其他信息,而无需频繁地向服务器请求数据。
-
setItem方法:用于存储数据到本地存储中。它接受两个参数,第一个是键名(key),第二个是值(value)。例如:
localStorage.setItem('username', 'John Doe')
。 -
getItem方法:用于从本地存储中获取数据。它接受一个参数,即要获取的键名。如果该键存在于存储中,它会返回对应的值;否则,返回null。例如:
let username = localStorage.getItem('username')
。
RESTful API 和资源的概念
RESTful(Representational State Transfer)是一种网络应用程序的设计风格和开发方式,基于HTTP协议,利用URI(Uniform Resource Identifier)来定位资源,通过HTTP的GET、POST、PUT、DELETE等方法来操作资源。这里的“一切皆资源”理念意味着Web服务中的所有内容都可以被看作资源,而RESTful API则是访问和操作这些资源的一套规则。
-
db.json 和 users: 在这个上下文中,
db.json
可能是一个存放数据的文件,其中包含了比如用户信息这样的资源集合。在RESTful架构中,users
可以被视为一个资源集合。 -
访问方式示例:
http://localhost:3000/users
表示用户资源的集合,通常使用GET方法来获取所有用户的信息。http://localhost:3000/users/1
表示集合中特定用户(如ID为1的用户)的资源,你可以通过GET、PUT、PATCH或DELETE方法来读取、更新或删除这个特定资源。
两者的区别
-
存储位置与范围:HTML5 Local Storage的数据存储在用户的浏览器上,仅对该用户可见,不同用户之间不会共享这些数据。而RESTful API操作的资源存储在服务器上,可以被网络中的任何有权限的客户端访问。
-
数据持久性:Local Storage的存储空间更大,数据在用户清除浏览器数据之前会一直保留。RESTful API中的资源持久性取决于服务器的策略,如数据库备份和恢复策略等。
-
交互方式:Local Storage是客户端技术,不涉及与服务器的实时通信。RESTful API则是基于网络的,需要客户端发起HTTP请求到服务器,服务器响应处理后再返回结果给客户端。
-
应用场景:Local Storage适用于存储不敏感的用户界面状态、用户偏好设置等数据。RESTful API则用于实现客户端与服务器之间的数据交换,适用于需要在服务器端持久化数据、多用户共享数据或需要复杂业务逻辑处理的场景。
前端部分
index.html
- html部分 我们只需要在html部分放入一个挂载点作为容器去实现功能
<div id="signature"></div>
- js部分
这里我通过引入外部脚本edit_in_place.js
,把EditInPlace
类放在外部脚本,独立开发和测试EditInPlace类,可以提高开发效率。
<script src="./edit_in_place.js"></script>
<script>
const STORAGEKEY = 'signature';
fetch("http://localhost:3000/users/1")
.then(res => res.json())
.then(data => {
// console.log(data, '//////////////////////////');
const { signature } = data
const signatureDom = localStorage.getItem(STORAGEKEY) || signature;
if(signature !== signatureDom) {
localStorage.setItem(STORAGEKEY, signature);
new EditInPlace(STORAGEKEY,
document.getElementById("signature"), signature);
}
})
</script>
代码解释:
- 数据获取:
使用fetch函数从
http://localhost:3000/users/1
这个API地址获取用户信息。这是一个异步操作,数据获取后通过一系列的.then方法处理。.then(res => res.json())
将响应体转化为JSON格式。 在下一个.then中,从返回的JSON数据中解构出signature字段,这是用户当前的签名。 - 状态检查与更新:
const signatureDom = localStorage.getItem(STORAGEKEY) || signature
; 这行代码尝试从本地存储中获取签名,如果不存在,则使用刚从服务器获取的签名。- 接下来的
if(signature !== signatureDom)
判断服务器的签名是否与本地存储中的签名不同。 - 如果两者不同,说明签名有更新,于是执行:
localStorage.setItem(STORAGEKEY, signature);
更新本地存储中的签名信息。
new EditInPlace(STORAGEKEY, document.getElementById("signature"), signature);
实例化EditInPlace
类,传入存储键名、页面上的挂载点(通过ID "signature" 获取的<div>
元素)以及签名内容,开始在页面上构建并启用签名的就地编辑界面。
edit_in_place.js
我在这个文件中 模块化封装了EditInPlace
类,让代码更具可读性和复用性。
首先,封装了EditInPlace
,并且初始化要封装的函数,并且给它加上了函数签名,使它具有可读性
/**
* @func 就地编辑
* @param { ele } container 挂载点
* @author bba
* @date 2024/6/25
*/
function EditInPlace(storageKey, container, value = '这个家伙很懒,什么都没有留下') {
// console.log('-----')
this.container = container;
this.storageKey = storageKey;
this.value = value;
this.createElement();
// console.log(this.value)
this.attachEvent();
}
代码解释:
-
函数签名:
function EditInPlace(storageKey, container, value = '这个家伙很懒,什么都没有留下')
定义了构造函数,接受三个参数:storageKey
:字符串,用于在本地存储(如localStorage)中标识存储的键名。container
:DOM元素,组件将被插入的容器。value
:默认值,当没有提供初始签名内容时使用,默认签名文本为“这个家伙很懒,什么都没有留下”。
-
初始化属性:
this.container = container;
:将传入的容器元素引用赋值给实例的container
属性。this.storageKey = storageKey;
:将存储键名赋值给实例的storageKey
属性。this.value = value;
:设置初始签名值,如果没有传入,则使用默认值。
-
创建DOM元素:
this.createElement();
调用实例方法createElement
,这个方法虽然没有在代码片段中展示,但根据注释推测,它的作用是动态创建文本展示(span
)、编辑框(input
)以及可能的控制按钮(如保存和取消按钮),并将这些元素添加到指定的容器中。
-
事件绑定:
this.attachEvent();
调用实例方法attachEvent
,用于为新创建的DOM元素绑定必要的事件监听器,如监听点击事件以切换编辑状态、保存更改等。同样,此方法的具体实现未在代码片段中给出。
我们继续代码的实现
- createElement():
createElement: function () {
// DOM树
// 创建一个div
this.editElement = document.createElement('div');
// 添加一个子元素
this.container.appendChild(this.editElement);
// signature 文本值
this.staticElement = document.createElement('span');
this.staticElement.innerHTML = this.value;
this.editElement.appendChild(this.staticElement);
// input
this.fieldElement = document.createElement('input');
this.fieldElement.type = 'text';
this.fieldElement.value = this.value;
this.fieldElement.className = 'edit-mode'
this.editElement.appendChild(this.fieldElement);
// 确定按钮
this.saveButton = document.createElement('input');
this.saveButton.className = 'btn'
this.saveButton.type = 'button';
this.saveButton.value = '保存';
this.editElement.appendChild(this.saveButton);
// 取消按钮
this.cancelButton = document.createElement('input');
this.cancelButton.className = 'btn'
this.cancelButton.type = 'button';
this.cancelButton.value = '取消';
this.editElement.appendChild(this.cancelButton);
// 初始文本状态
this.converToText();
// 监听事件
this.attachEvent();
},
代码解释:
-
创建主容器Div: 首先,通过 document.createElement('div') 创建一个新的
<div>
元素,并将其引用存储在this.editElement
中。这个<div>
将作为编辑组件的根容器。 -
将主容器添加到页面: 通过 this.container.appendChild(this.editElement) 将刚创建的
<div>
添加到类初始化时传入的容器元素 (this.container
) 内。 -
创建静态文本Span: 接着,创建一个
<span>
元素 (this.staticElement) 用于显示签名的初始文本值,并通过innerHTML
属性设置其内容为 this.value,最后将这个<span>
添加到主容器 (this.editElement) 中。 -
创建输入框Input: 创建一个类型为 'text' 的
<input>
元素 (this.fieldElement),用于用户编辑签名,其初始值同样设为 this.value,然后将其添加到主容器中。 创建按钮:分别创建“保存”和“取消”两个按钮,类型均为 'button',并通过 value 属性设置按钮上的文字,随后也将这两个按钮添加到主容器中。 -
初始化文本状态: 调用
this.converToText()
方法,确保组件初次渲染时处于文本展示状态,而非编辑状态。 -
事件监听: 最后,调用
this.attachEvent()
方法来为创建的各个元素(特别是按钮)添加必要的事件监听器,以实现编辑、保存和取消等功能。
1.1 converToText()
converToText: function () {
this.staticElement.style.display = 'inline'
this.fieldElement.style.display = 'none'
this.saveButton.style.display = 'none'
this.cancelButton.style.display = 'none'
},
1.2 converToEdit()
converToEdit: function () {
this.staticElement.style.display = 'none'
this.fieldElement.style.display = 'inline'
this.saveButton.style.display = 'inline'
this.cancelButton.style.display = 'inline'
},
- attachEvent()
这段事件监听是为了实例在页面上创建的几个DOM元素绑定相应的事件处理函数,以便实现就地编辑功能的交互逻辑。
attachEvent: function () {
// let that = this;
// this.staticElement.addEventListener('click',() => {
// this 指向元素
// this丢失了
// that.converToEdit();
// });
this.staticElement.addEventListener('click', () => this.converToEdit());
this.saveButton.addEventListener('click', () => {
this.save()
});
this.cancelButton.addEventListener('click', () => {
this.converToText();
});
},
- 保存按钮save():
save: function () {
this.value = this.fieldElement.value;
// html5 localStorage
// 将数据存储到本地,下次打开页面的时候,从本地获取数据
localStorage.setItem(this.storageKey, this.value);
this.staticElement.innerHTML = this.value;
this.converToText();
this.saveData();
},
- saveData():
这个方法功能是使用Fetch API向服务器发送一个HTTP PATCH请求,以便更新指定资源的数据。
saveData: function () {
let value = this.value
// resfull = url 定义的方式 + METHOD
// get 是读 Post 创建 PUT 修改 PATCH 局部更新 DELETE 删除
// 看到这个url 就知道啥资源?
// 修改db.json里的数据 GET
fetch('http://localhost:3000/users/1', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
}, // 请求头信息,告诉服务器,发送的参数是json格式
body: JSON.stringify({
signature: value
}) // 请求体
})
.then(res => res.json())
.then(data => {
console.log(data, "保存成功")
})
}
代码解释:
-
数据准备: 方法首先将当前对象的
value
属性赋值给局部变量value
,这个值通常是在编辑模式下用户输入的内容。 -
发起PATCH请求: 使用
fetch
函数向http://localhost:3000/users/1
这个URL发起一个PATCH类型的HTTP请求。这个请求的目标是更新ID为1的用户资源中的数据。PATCH请求常用于局部更新已有资源,而不是替换整个资源。 -
配置请求选项:
- Method: 设置为
PATCH
,表明这是一个局部更新请求。 - Headers: 设置请求头,特别是
Content-Type
为application/json
,告知服务器发送的数据格式是JSON。 - Body: 包含一个JSON字符串,该字符串由用户的输入(
value
)经过JSON.stringify
处理后得到,结构为{signature: value}
。这里假设我们要更新的是用户签名(signature)字段。
- Method: 设置为
-
处理响应:
- 第一个
.then
处理函数会等待fetch的响应,并将其转化为JSON格式。 - 第二个
.then
处理函数接收转化后的JSON数据,并打印到控制台,附带消息"保存成功",表明更新操作完成且服务器返回了响应。
- 第一个
那么大致的效果就完成了
改了value然后点击保存之后
总结
通过本次实战解析,我们不仅回顾了十年前那些充满个性色彩的QQ签名,还深入学习并实践了如何在现代Web开发中实现一个实用的个性签名就地编辑功能。我们从理论到实践,逐步构建了一个结合前端技术和后端交互的完整解决方案,涵盖了HTML5 Local Storage的使用、RESTful API的基本理解和应用,以及如何通过JavaScript ES6的Class和模块化编程提升代码的组织与可维护性。 那么这次的分享到这里就结束了
转载自:https://juejin.cn/post/7384999241041985555