当前位置: 首页 > news >正文

WEB前端小练习——记事本

一、登陆页面

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>记事本登录注册</title><link rel="stylesheet" href="../css/login.css">
</head><body><div id="app"><!-- 登录页面 --><div v-show="isLoginPage"><h2>登录</h2><form><input v-model="loginUsername" placeholder="用户名" /><input v-model="loginPassword" placeholder="密码" /><button type="button" @click="login">登录</button><button type="button" @click="showRegisterPage">注册</button></form></div><!-- 注册页面 --><div v-show="isRegisterPage"><h2>注册</h2><form><input v-model="registerUsername" placeholder="用户名" /><input v-model="registerPassword" placeholder="密码" type="password" /><button type="button" @click="register">注册</button><button type="button" @click="showLoginPage">返回登录</button></form></div></div><script src="https://cdn.jsdelivr.net/npm/vue@2"></script><script src="../js/login.js"></script>
</body></html>
body {font-family: Arial, sans-serif;display: flex;justify-content: center;align-items: center;min-height: 100vh;margin: 0;background-color: #f4f4f4;
}div {background-color: white;padding: 20px;border-radius: 5px;box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);text-align: center;
}h2 {text-align: center;
}input {width: 80%;padding: 10px;margin-bottom: 15px;border: 1px solid #ccc;border-radius: 3px;
}button {width: 20%;padding: 10px;background-color: #4CAF50;color: white;border: none;border-radius: 3px;cursor: pointer;margin: 30px;
}button:hover {background-color: #45a049;
}    

new Vue({el: '#app',data: {isLoginPage: true,isRegisterPage: false,isLoggedIn: false,loginUsername: '',loginPassword: '',registerUsername: '',registerPassword: '',registeredUsers: [], // 存储已注册用户信息的数组usernamesSet: new Set(), // 用于确保用户名唯一性的Setnotes: [],},mounted() {const storedUsers = localStorage.getItem('registeredUsers');if (storedUsers) {this.registeredUsers = JSON.parse(storedUsers);this.registeredUsers.forEach(user => {this.usernamesSet.add(user.username);});}},methods: {login() {const inputUsername = this.loginUsername;const inputPassword = this.loginPassword;const user = this.registeredUsers.find(u => u.username === inputUsername && u.password === inputPassword);if (user) {console.log('登录成功,跳转到指定页面');window.location.href = '../html/index.html';} else {alert('用户名或密码错误,请重试!');}},register() {const usernamePattern = /^[a-zA-Z0-9]+$/;const passwordPattern = /.{6,}/;if (!this.registerUsername.match(usernamePattern)) {alert('用户名只能包含字母和数字');return;}if (!this.registerPassword.match(passwordPattern)) {alert('密码长度至少为6位');return;}if (this.usernamesSet.has(this.registerUsername)) {alert('该用户名已注册,请更换用户名');return;}const userId = Date.now(); // 使用时间戳作为唯一IDconst newUser = {id: userId,username: this.registerUsername,password: this.registerPassword};this.registeredUsers.push(newUser);this.usernamesSet.add(this.registerUsername);localStorage.setItem('registeredUsers', JSON.stringify(this.registeredUsers));alert('注册成功');console.log('已注册用户数组:', this.registeredUsers);this.isRegisterPage = false;this.isLoginPage = true;},showRegisterPage() {this.isLoginPage = false;this.isRegisterPage = true;},showLoginPage() {this.isRegisterPage = false;this.isLoginPage = true;}}
});

二、记事本页面

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>记事本</title><!-- 引入重置样式表 --><link href="../css/normalize.css" /><link href="../css/reset.css" /><link href="../css/index.css" rel="stylesheet" />
</head><body><!-- 引入 Vue --><script src="https://cdn.jsdelivr.net/npm/vue@2"></script><div id="contain"><div id="box"><div id="header"><span>记事本</span></div><div id="main"><div id="mainTop"><!-- 输入框绑定 message 数据,按下回车键或点击按钮触发 add 方法 --><input id="text" v-model="message" placeholder="just to do it!" @keyup.enter="add" /><button id="add" v-on:click="add">新增笔记</button><!-- 输入框绑定 message 数据,按下回车键或点击按钮触发 add 方法 --><br /><input id="search" v-model="searchKeyword" placeholder="搜索笔记" /><button id="check" v-on:click="select">查询笔记</button></div><div id="mainBottom"><!-- 使用 ul 和 v-for 渲染笔记列表 --><ul><li v-for="(item, index) in searchResult.length > 0? searchResult : filteredNotesList" :key="index"><!-- 笔记内容展示部分 --><!-- 根据 delMuch 状态显示复选框,并绑定 checked 属性 --><input type="checkbox" v-if="delMuch" v-model="item.checked"><span id="order">{{index + 1}}&nbsp;&nbsp;&nbsp;&nbsp;<!-- 根据 isEditing 状态显示文本或输入框 --><!--根据 item.isEditing 的状态来决定显示笔记文本还是输入框。当 isEditing 为 false 时显示笔记文本,为 true 时显示输入框,并且输入框通过 v-model 绑定 tempEditValue,用于编辑笔记内容。--><label v-if="!item.isEditing" id="content">{{item.text}}</label><input id="newMessage" v-else v-model="tempEditValue" type="text"></span><span id="right"><!-- 根据 isEditing 状态显示不同按钮 --><button v-if="!item.isEditing" id="edit" @click="edit(index)">编辑</button><!--现在根据 item.isEditing 的状态切换显示不同按钮。当处于非编辑状态时显示 “编辑” 按钮,点击后进入编辑状态;进入编辑状态后显示 “确定” 和 “取消” 按钮,分别用于确认修改和取消修改。--><button v-else id="confirm" @click="confirmEdit(index)">确定</button><button v-else id="cancel" @click="cancelEdit(index)">取消</button><button id="del" @click="del(index)">删除</button></span></span></li></ul></div></div><div id="footer" v-show="NotesList.length > 0"><!-- 显示笔记数量 --><span id="count">共有{{count}}条笔记</span><!-- 点击按钮触发批量删除和清空操作 --><button id="delMany" v-on:click="delMany" class="delS">批量删除</button><button id="clear" v-on:click="clear">清空记事本</button></div></div></div><!-- 引入优化后的 JS 文件 --><script src="../js/index.js"></script>
</body></html>
/* 全局设置,将 box-sizing 设置为 border-box,避免尺寸计算问题 */
* {box-sizing: border-box;
}body {background-image: url(../src/img/image.png);background-size: cover;background-repeat: no-repeat;
}#box {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);
}#header {background-color: rgb(177, 223, 79, .8);width: 830px;height: 80px;border: 1px solid black;font-size: 25px;text-align: center;line-height: 80px;
}#main {width: 830px;height: 360px;border-left: 1px solid black;border-right: 1px solid black;background-color: rgb(255, 255, 255, .8);overflow: hidden;
}#mainTop {height: 60px;border: 1px solid black;display: flex;align-items: center;
}#text,
#search {width: 60%;height: 60px;box-sizing: border-box;font-size: 20px;float: left;
}#add,
#check {width: 15%;height: 60px;font-size: 17px;box-sizing: border-box;float: left;
}#mainBottom {height: 300px;overflow: auto;border: 1px solid black;position: relative;
}#newMessage,
#content {display: inline-block;height: 40px;line-height: 40px;width: 620px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;font-size: 20px;position: relative;vertical-align: middle;
}#footer {width: 830px;height: 70px;border: 1px solid black;background-color: rgba(177, 223, 79, .8);text-align: center;line-height: 70px;display: flex;align-items: center;position: relative;
}#text::placeholder {font-size: 22px;color: rgba(177, 220, 100, 1);padding-left: 30px;
}#search::placeholder {padding-left: 30px;
}#count {position: absolute;left: 10px;
}ul {padding: 0;margin: 0;
}li {height: 40px;box-sizing: border-box;display: flex;align-items: center;line-height: 40px;
}li:nth-child(2n + 1) {background-color: rgba(128, 128, 150, .3);
}#delMany {background-color: white;height: 40px;position: absolute;width: 90px;right: 120px;
}#clear {background-color: white;height: 40px;position: absolute;width: 90px;right: 10px;
}#right {right: 15px;position: absolute;font-size: 18px;
}#confirm,
#edit {margin-right: 8px;width: 45px;height: 30px;
}#del {width: 45px;height: 30px;
}#order {padding-left: 20px;
}
var app = new Vue({el: "#contain",data: {NotesList: [],count: 0,message: "",delMuch: false,tempEditValue: '',selectedCategory: '',searchKeyword: '',priorities: ['高', '中', '低'],selectedPriority: '',searchResult: [],searchResultCount: 0},computed: {filteredNotesList() {let filtered = this.NotesList;if (this.selectedCategory) {filtered = filtered.filter(item => item.category === this.selectedCategory);}if (this.searchKeyword) {const keyword = this.searchKeyword.toLowerCase();filtered = filtered.filter(item => item.text.toLowerCase().includes(keyword));}if (this.selectedPriority) {filtered = filtered.filter(item => item.priority === this.selectedPriority);}return filtered;},highlightedSearchResult() {return this.searchResult.map(item => {const keyword = this.searchKeyword;if (keyword) {const regex = new RegExp(keyword, 'gi');item.highlightedText = item.text.replace(regex, '<mark>$&</mark>');} else {item.highlightedText = item.text;}return item;});}},watch: {searchKeyword: function (newKeyword) {this.select();}},methods: {clear: function () {const confirmation = confirm('你确定要清空记事本吗');if (confirmation) {this.NotesList = [];this.count = 0;this.saveNotesToLocalStorage();alert('操作已执行!');} else {alert('操作已取消。');}},add: function () {const input = this.message.trim();if (input) {this.NotesList.unshift({text: input,isEditing: false,checked: false,category: '工作',priority: '中'});this.count++;this.message = "";if (this.searchKeyword) {this.select();}this.saveNotesToLocalStorage();} else {alert("请输入有效内容");}},edit: function (index) {if (this.filteredNotesList[index]) {const realIndex = this.NotesList.indexOf(this.filteredNotesList[index]);this.NotesList[realIndex].isEditing = true;this.tempEditValue = this.NotesList[realIndex].text;}},confirmEdit: function (index) {const newText = this.tempEditValue.trim();if (newText && this.filteredNotesList[index]) {const realIndex = this.NotesList.indexOf(this.filteredNotesList[index]);this.NotesList[realIndex].text = newText;}if (this.filteredNotesList[index]) {const realIndex = this.NotesList.indexOf(this.filteredNotesList[index]);this.NotesList[realIndex].isEditing = false;}if (this.searchKeyword) {this.select();}this.saveNotesToLocalStorage();},cancelEdit: function (index) {if (this.filteredNotesList[index]) {const realIndex = this.NotesList.indexOf(this.filteredNotesList[index]);this.NotesList[realIndex].isEditing = false;this.tempEditValue = this.NotesList[realIndex].text;}},del: function (index) {if (this.filteredNotesList.length > 0 && index >= 0 && index < this.filteredNotesList.length) {const realIndex = this.NotesList.indexOf(this.filteredNotesList[index]);this.NotesList.splice(realIndex, 1);this.count--;if (this.searchKeyword) {this.select();}this.saveNotesToLocalStorage();}},delMany: function () {this.delMuch = true;const originalLength = this.NotesList.length;this.NotesList = this.NotesList.filter(item => !item.checked);const deletedCount = originalLength - this.NotesList.length;if (deletedCount > 0) {this.count = this.NotesList.length;this.delMuch = false;const isConfirmed = confirm('你确定要删除选中的笔记吗?');if (isConfirmed) {alert(`已成功删除 ${deletedCount} 条笔记`);}}if (this.searchKeyword) {this.select();}this.saveNotesToLocalStorage();},select: function () {const keyword = this.searchKeyword.trim().toLowerCase();if (keyword) {this.searchResult = this.NotesList.filter(item => item.text.toLowerCase().includes(keyword));this.searchResultCount = this.searchResult.length;if (this.searchResultCount === 0) {alert('没有查询到相关笔记');} else {alert(`查询到 ${this.searchResultCount} 条相关笔记`);}} else {this.searchResult = [];this.searchResultCount = 0;}},addOrSearch: function (event) {if (event.key === 'Enter') {if (event.ctrlKey) {this.select();} else {this.add();}}},saveNotesToLocalStorage() {localStorage.setItem('notes', JSON.stringify(this.NotesList));},loadNotesFromLocalStorage() {const notes = localStorage.getItem('notes');if (notes) {this.NotesList = JSON.parse(notes);this.count = this.NotesList.length;}}},mounted() {this.loadNotesFromLocalStorage();}
});

相关文章:

  • 多端定制系统开发:打造高效全平台覆盖的APP解决方案
  • 004 树与二叉树:从原理到实战
  • 「Mac畅玩AIGC与多模态16」开发篇12 - 多节点串联与输出合并的工作流示例
  • C++调试(叁):编译qBreakpad并使用其生成Dump文件
  • 解决Maven项目中报错“java不支持版本6即更高的版本 7”
  • 代码随想录算法训练营Day43
  • 单片机嵌入式CAN库
  • Linux第20节 --- inode和文件系统
  • 【2025软考高级架构师】——未来信息综合技术(11)
  • C++笔记-多态(包含虚函数,纯虚函数和虚函数表等)
  • 基于PyTorch的食物图像分类实战:从数据处理到模型训练
  • 61常用控件_QDateTimeEdit的使用
  • 【LeetCode Hot100】贪心篇
  • Python基本语法(函数partial)
  • 生成式 AI 的优势
  • AI 大模型常见面试题(及内容解析)
  • cpp细碎知识点
  • asp.net客户管理系统批量客户信息上传系统客户跟单系统crm
  • 给QCustomPlot添加一个QScrollBar滚动条、限制缩放范围、自动设置大小和右边栏垂直缩放
  • 基于springboot的金院银行厅预约系统的设计及实现(源码+lw+部署文档+讲解),源码可白嫖!
  • 跳水世界杯总决赛陈佳获得女子3米板冠军,陈艺文获得亚军
  • 经济日报头版评论:矢志奋斗筑梦青春中国
  • 中国海警局回应日本民用飞机侵闯我钓鱼岛领空:依法警告驱离
  • 研究完蚂蚁搬家,我好像明白了为什么我们总是堵车
  • 乘客被困停滞车厢超4小时,哈尔滨铁路局客服:列车晚点,表示歉意
  • 李在明回应韩国大法院判决:与自己所想截然不同,将顺从民意