【ruby java】登陆功能/邮件发送模版240903
Rails 风格登录系统添加全面而详细的注释,解释每个部分的功能和用途。
详细注释,解释了每个文件和代码块的功能。以下是一些关键点的总结:
1. 控制器(Controllers):
- `ApplicationController`: 定义了 `current_user` 方法,用于在整个应用中获取当前登录用户。
- `SessionsController`: 处理用户登录和注销功能。
- `UsersController`: 处理用户注册功能,包括创建新用户和处理注册表单。
2. 模型(Model):
- `User`: 使用 `has_secure_password` 进行密码加密和验证,并添加了用户名验证。
3. 视图(Views):
- 使用 ERB(Embedded Ruby)语法在 HTML 中嵌入 Ruby 代码。
- `<% %>`: 执行 Ruby 代码但不输出结果。
- `<%= %>`: 执行 Ruby 代码并输出结果。
- 使用 Rails 的表单构建器和链接辅助方法(如 `form_with` 和 `link_to`)。
4. 布局(Layout):
- 主布局文件包含导航栏和闪现消息显示。
- 使用 `yield` 插入各个页面的具体内容。
5. 表单和验证:
- 注册表单包含错误消息显示逻辑。
- 使用强参数(Strong Parameters)来增强安全性。
6. 会话管理:
- 使用 Rails 的 session 机制来管理用户登录状态。
这个示例展示了一个基本的 Rails 登录系统的结构和实现方式。在实际应用中,你可能还需要添加更多功能,如密码重置、记住我功能、OAuth 集成等。
同时,请注意这只是应用的一部分。在完整的 Rails 应用中,你还需要:
- 配置数据库(`config/database.yml`)
- 设置路由(`config/routes.rb`)
- 运行数据库迁移来创建用户表
- 添加适当的样式(CSS)和可能的 JavaScript 交互
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
# 将 current_user 方法设为 helper 方法,使其在视图中可用
helper_method :current_user
private
# 获取当前登录用户
def current_user
# 如果 @current_user 已设置,直接返回,否则尝试从数据库中查找用户
# ||= 操作符是一种常见的 Ruby 缓存模式
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
# app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
# 显示登录表单
def new
# 不需要额外的逻辑,直接渲染 new.html.erb
end
# 处理登录请求
def create
# 根据提交的用户名查找用户
user = User.find_by(username: params[:username])
# 验证用户存在且密码正确
if user && user.authenticate(params[:password])
# 登录成功,将用户 ID 存入 session
session[:user_id] = user.id
# 重定向到首页,显示成功消息
redirect_to root_path, notice: '登录成功!'
else
# 登录失败,设置错误消息
flash.now[:alert] = '无效的用户名或密码'
# 重新渲染登录表单
render :new
end
end
# 处理注销请求
def destroy
# 清除 session 中的用户 ID
session[:user_id] = nil
# 重定向到首页,显示注销成功消息
redirect_to root_path, notice: '已成功注销'
end
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController
# 显示用户注册表单
def new
# 初始化一个新的 User 对象,用于表单构建
@user = User.new
end
# 处理用户注册请求
def create
# 使用强参数创建新用户
@user = User.new(user_params)
if @user.save
# 注册成功,自动登录用户
session[:user_id] = @user.id
# 重定向到首页,显示成功消息
redirect_to root_path, notice: '注册成功!'
else
# 注册失败,重新渲染注册表单
render :new
end
end
private
# 强参数方法,定义允许传递的参数
def user_params
params.require(:user).permit(:username, :password, :password_confirmation)
end
end
# app/models/user.rb
class User < ApplicationRecord
# 启用安全密码功能,要求 bcrypt gem
has_secure_password
# 验证用户名存在且唯一
validates :username, presence: true, uniqueness: true
end
# app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>登录系统</title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all' %>
</head>
<body>
<nav>
<%# 使用 link_to 辅助方法创建链接 %>
<%= link_to '首页', root_path %>
<%# 根据用户登录状态显示不同的链接 %>
<% if current_user %>
<%= link_to '注销', logout_path, method: :delete %>
<% else %>
<%= link_to '登录', login_path %>
<%= link_to '注册', signup_path %>
<% end %>
</nav>
<%# 显示闪现消息 %>
<% flash.each do |type, message| %>
<div class="flash <%= type %>"><%= message %></div>
<% end %>
<%# 插入各个页面的具体内容 %>
<%= yield %>
</body>
</html>
# app/views/sessions/new.html.erb
<h1>登录</h1>
<%# 创建指向 login_path 的表单 %>
<%= form_with(url: login_path, local: true) do |f| %>
<div>
<%= f.label :username, '用户名' %>
<%= f.text_field :username %>
</div>
<div>
<%= f.label :password, '密码' %>
<%= f.password_field :password %>
</div>
<div>
<%= f.submit '登录' %>
</div>
<% end %>
# app/views/users/new.html.erb
<h1>注册</h1>
<%# 创建新用户表单 %>
<%= form_with(model: @user, local: true) do |f| %>
<%# 显示验证错误信息 %>
<% if @user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% @user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= f.label :username, '用户名' %>
<%= f.text_field :username %>
</div>
<div>
<%= f.label :password, '密码' %>
<%= f.password_field :password %>
</div>
<div>
<%= f.label :password_confirmation, '确认密码' %>
<%= f.password_field :password_confirmation %>
</div>
<div>
<%= f.submit '注册' %>
</div>
<% end %>
# app/views/home/index.html.erb
<h1>欢迎来到登录系统</h1>
<%# 根据用户登录状态显示不同内容 %>
<% if current_user %>
<p>你好,<%= current_user.username %>!</p>
<% else %>
<p>请登录或注册</p>
<% end %>
require 'bcrypt'
require 'securerandom'
class User
attr_reader :username, :password_hash
attr_accessor :is_member # 新增: 允许外部读取和修改会员状态
def initialize(username, password, is_member = false)
@username = username
@password_hash = BCrypt::Password.create(password)
@is_member = is_member # 新增: 初始化会员状态,默认为非会员
end
def authenticate(password)
BCrypt::Password.new(@password_hash) == password
end
end
class UserDatabase
def initialize
@users = {} # 使用哈希存储用户,键为用户名,值为User对象
end
def add_user(username, password, is_member = false)
@users[username] = User.new(username, password, is_member)
end
def find_user(username)
@users[username]
end
# 新增: 更新用户的会员状态
def update_membership(username, is_member)
user = find_user(username)
user.is_member = is_member if user # 如果用户存在,更新其会员状态
end
end
class SessionManager
def initialize
@sessions = {} # 存储会话信息,键为会话令牌,值为用户名
end
def create_session(username)
token = SecureRandom.hex(16) # 生成随机的会话令牌
@sessions[token] = username
token
end
def get_user(token)
@sessions[token] # 根据令牌返回用户名
end
def delete_session(token)
@sessions.delete(token) # 删除指定的会话
end
end
class LoginSystem
def initialize
@user_db = UserDatabase.new
@session_manager = SessionManager.new
end
# 修改: 增加is_member参数,允许在注册时设置会员状态
def register(username, password, is_member = false)
if @user_db.find_user(username)
puts "用户名已存在"
else
@user_db.add_user(username, password, is_member)
puts "注册成功#{is_member ? ',并已设置为会员' : ''}"
end
end
# 修改: 登录成功后显示会员状态
def login(username, password)
user = @user_db.find_user(username)
if user && user.authenticate(password)
token = @session_manager.create_session(username)
puts "登录成功,会话令牌: #{token}"
puts user.is_member ? "欢迎回来,尊贵的会员!" : "欢迎回来,普通用户。"
token
else
puts "用户名或密码错误"
nil
end
end
def logout(token)
if @session_manager.get_user(token)
@session_manager.delete_session(token)
puts "注销成功"
else
puts "无效的会话"
end
end
# 修改: 检查会话时同时显示会员状态
def check_session(token)
username = @session_manager.get_user(token)
if username
user = @user_db.find_user(username)
puts "当前登录用户: #{username}"
puts user.is_member ? "会员状态: 是" : "会员状态: 否"
else
puts "未登录或会话已过期"
end
end
# 新增: 更新指定用户的会员状态
def update_membership(username, is_member)
if @user_db.find_user(username)
@user_db.update_membership(username, is_member)
puts "已更新 #{username} 的会员状态为: #{is_member ? '会员' : '非会员'}"
else
puts "用户不存在"
end
end
# 新增: 检查指定用户的会员状态
def check_membership(username)
user = @user_db.find_user(username)
if user
puts "用户 #{username} 的会员状态: #{user.is_member ? '是会员' : '不是会员'}"
else
puts "用户不存在"
end
end
end
# 使用示例
login_system = LoginSystem.new
# 注册新用户(普通用户和会员)
login_system.register("alice", "password123") # 注册普通用户
login_system.register("bob", "securepass", true) # 注册会员用户
# 登录并检查会员状态
token_alice = login_system.login("alice", "password123")
login_system.check_session(token_alice)
# 更新会员状态
login_system.update_membership("alice", true)
# 再次检查会员状态
login_system.check_membership("alice")
特殊符合作用:
1. `||` (双竖线):
`||` 是逻辑或运算符,也用于提供默认值。在Ruby中,它有两个主要用途:
a) 逻辑或运算:
```ruby
result = condition1 || condition2
```
如果 `condition1` 为真,`result` 将等于 `condition1`;否则,它将等于 `condition2`。
b) 默认值赋值:
```ruby
name = user_input || "Guest"
```
如果 `user_input` 为 `nil` 或 `false`,`name` 将被赋值为 "Guest"。
2. `||=` (双竖线等于):
`||=` 是一种常见的Ruby惯用法,用于条件赋值。它的作用是:如果变量还没有被赋值(是 `nil` 或 `false`),则赋予它一个新值。
例如,在我们之前的代码中:
```ruby
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
```
这行代码的意思是:如果 `@current_user` 还没有被赋值,就去数据库中查找用户并赋值;如果已经赋值过了,就直接返回,避免重复查询数据库。
3. `:` (冒号):
冒号 `:` 在Ruby中有几种不同的用途:
a) 定义符号(Symbol):
```ruby
:username
:password
```
符号类似于轻量级的字符串,常用作哈希的键或方法参数。
b) 哈希的键值对:
```ruby
user = { username: "alice", role: "admin" }
```
这是Ruby 1.9+的新语法,等同于 `{ :username => "alice", :role => "admin" }`。
c) 命名参数:
```ruby
def login(username:, password:)
# 方法体
end
login(username: "alice", password: "secret")
```
这里的 `:` 用于定义和使用命名参数。
在Rails中,冒号还常用于:
d) 指定路由:
```ruby
get '/login', to: 'sessions#new'
```
e) 指定关联:
```ruby
belongs_to :user
has_many :posts
```
总结:
- `||` 用于逻辑或运算和提供默认值
- `||=` 用于条件赋值,常用于缓存和初始化
- `:` 用于定义符号、哈希键、命名参数,以及在Rails中指定路由和关联
这些符号在Ruby和Rails开发中非常常见,理解它们的用法对于阅读和编写代码都很重要。
# 邮件模版发送功能Ruby实现
class EmailTemplate
def initialize(template)
@template = template # 存储模板字符串
end
def render(placeholders)
result = @template # 创建模板的副本
placeholders.each do |key, value|
# 使用gsub方法替换所有匹配的占位符
result = result.gsub("{{#{key}}}", value)
end
result # 返回渲染后的结果
end
end
# Ruby使用示例
template = "Dear {{name}},\n\nThank you for your purchase of {{product}}.\n\nBest regards,\n{{company}}"
email = EmailTemplate.new(template) # 创建模板实例
rendered = email.render({
name: "John",
product: "Ruby Programming Book",
company: "RubyBooks Inc."
}) # 使用哈希传递占位符值
puts rendered # 输出渲染结果
# Java实现
public class EmailTemplate {
private String template; // 存储模板字符串
public EmailTemplate(String template) {
this.template = template; // 构造函数初始化模板
}
public String render(Map<String, String> placeholders) {
String result = template; // 创建模板的副本
for (Map.Entry<String, String> entry : placeholders.entrySet()) {
// 使用replace方法替换所有匹配的占位符
result = result.replace("{{" + entry.getKey() + "}}", entry.getValue());
}
return result; // 返回渲染后的结果
}
}
// Java使用示例
String template = "Dear {{name}},\n\nThank you for your purchase of {{product}}.\n\nBest regards,\n{{company}}";
EmailTemplate emailTemplate = new EmailTemplate(template); // 创建模板实例
Map<String, String> placeholders = new HashMap<>(); // 创建占位符Map
placeholders.put("name", "John");
placeholders.put("product", "Java Programming Book");
placeholders.put("company", "JavaBooks Inc.");
String rendered = emailTemplate.render(placeholders); // 渲染模板
System.out.println(rendered); // 输出渲染结果
当然,我可以为您对比Ruby和Java在实现邮件模板置换时的差异。让我们先看一下Ruby的典型实现,然后与Java版本进行比较。
现在让我们对比这两种实现:
1. 语法和结构:
- Ruby:更简洁,使用动态类型。
- Java:更冗长,需要明确的类型声明。
2. 初始化:
- Ruby:使用`initialize`方法。
- Java:使用构造函数。
3. 占位符替换:
- Ruby:使用`gsub`方法进行字符串替换。
- Java:使用`replace`方法。
4. 参数传递:
- Ruby:直接传递一个哈希作为参数。
- Java:使用`Map<String, String>`作为参数。
5. 迭代:
- Ruby:使用`each`方法进行迭代。
- Java:使用`for`循环或增强型for循环。
6. 字符串插值:
- Ruby:可以直接在字符串中使用`#{}`进行插值。
- Java:需要使用字符串连接。
7. 使用示例:
- Ruby:可以直接传递哈希字面量。
- Java:需要创建`Map`对象并逐个添加键值对。
8. 动态性:
- Ruby:更动态,可以在运行时轻松添加或修改方法。
- Java:更静态,类的结构在编译时确定。
总的来说,Ruby版本通常更简洁、更灵活,而Java版本更明确、类型安全。Ruby的动态特性使得代码更简短,但Java的静态类型提供了更好的编译时错误检查。选择哪种实现取决于项目需求、团队偏好和性能考虑。
如果您需要更详细的解释或有任何其他问题,请随时告诉我。
相关文章:
【ruby java】登陆功能/邮件发送模版240903
Rails 风格登录系统添加全面而详细的注释,解释每个部分的功能和用途。 详细注释,解释了每个文件和代码块的功能。以下是一些关键点的总结: 1. 控制器(Controllers): - ApplicationController: …...
告别格式不兼容烦恼!ape转换mp3,分享3个简单方法
各位读者们,你们是否有过这种体验:满怀期待地在网上下载一首好听的歌曲,结果怎么点击手机都播放不了,定睛一看,弹窗显示“无法播放该音频文件”。这是为什么呢?原来那首歌的音频格式是ape,不被手…...
Java核心知识体系-并发与多线程:线程基础
1 先导 Java线程基础主要包含如下知识点,相信我们再面试的过程中,经常会遇到类似的提问。 1、线程有哪几种状态? 线程之间如何转变? 2、线程有哪几种实现方式? 各优缺点? 3、线程的基本操作(线程管理机制ÿ…...
KRaft模式下的Kafka启动指南:摆脱Zookeeper依赖
一、背景介绍 多年来,人们一直在同时使用Apache ZooKeeper和Apache Kafka。但是自Apache Kafka 3.3发布以来,它就可以在没有ZooKeeper的情况下运行。同时它包含了新的命令kafka-metadata-quorum和kafka-metadata-shell?该如何安装新版kafka,…...
【数据库】MySQL-基础篇-函数
专栏文章索引:数据库 有问题可私聊:QQ:3375119339 目录 一、简介 二、字符串函数 三、数值函数 四、日期函数 五、流程函数 一、简介 函数 是指一段可以直接被另一段程序调用的程序或代码。 也就意味着,这一段程序或代码在 M…...
dp练习【4】
最长数对链 646. 最长数对链 给你一个由 n 个数对组成的数对数组 pairs ,其中 pairs[i] [lefti, righti] 且 lefti < righti 。 现在,我们定义一种 跟随 关系,当且仅当 b < c 时,数对 p2 [c, d] 才可以跟在 p1 [a, b…...
php 实现推荐算法
在PHP中实现推荐算法的应用场景通常包括电商、社交媒体、内容平台等。推荐算法可以帮助用户找到与其兴趣相关的内容,提高用户体验和平台黏性。以下是几种常见的推荐算法及其PHP实现方式: 1. 基于协同过滤的推荐算法 协同过滤(Collaborative…...
相机光学(三十六)——光圈
0.参考链接 (1)Hall光圈和Piris光圈的区别 (2)自动光圈及P-IRIS原理 1.光圈分类 Hall光圈和Piris光圈是两种不同的光圈技术。它们之间的区别如下: Hall光圈:Hall光圈是一种传统的光电子元件,通…...
数据结构——树和二叉树
目录 一、树的概念 二、树结点之间的关系 三、二叉树 1、满二叉树 2、完全二叉树 四、二叉树的存储 1、顺序存储 2、链式存储 一、树的概念 如果数据和数据之间满足一对多的关系,将其逻辑结构称之为树 如下图:树的根与树的分支存在一对多的关系 将上…...
142. Go操作Kafka(confluent-kafka-go库)
文章目录 Apache kafka简介开始使用Apache Kafka构建生产者构建消费者 总结 之前已经有两篇文章介绍过 Go如何操作 kafka 28.windows安装kafka,Go操作kafka示例(sarama库) 51.Go操作kafka示例(kafka-go库) Apache ka…...
spring boot(学习笔记第十九课)
spring boot(学习笔记第十九课) Spring boot的batch框架,以及Swagger3(OpenAPI)整合 学习内容: Spring boot的batch框架Spring boot的Swagger3(OpenAPI)整合 1. Spring boot batch框架 Spring Batch是什么 Spring Batch 是一个…...
docker安装 redis 并且加密开启SSL/TLS通道
拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/qiluo-images/redis:latest docker tag registry.cn-hangzhou.aliyuncs.com/qiluo-images/redis:latest redis:latest要在 Docker 容器中启动 Redis 并开启 SSL/TLS 加密,需按照以下步骤修改启动命令和配置…...
什么是ARM架构?什么是X86架构?两者的区别是什么?
一、什么是ARM架构 (一)起源于发展 ARM 架构由英国剑桥的 Acorn 计算机公司开发。因市场无合适产品,Acorn 自行设计出第一款微处理器,命名为 ARM。此后 ARM 架构不断发展,1990 年为与苹果合作成立 ARM 公司࿰…...
【vscode】vscode paste image插件设置
本文首发于 ❄️慕雪的寒舍 vscode编辑md文件的时候,如果想插入图片,自带的粘贴只会粘贴到当前目录下,也没有文件重命名,很不友好。 在扩展商店里面有mushan的Paste Image插件,相比自带的,更加友好一点。但…...
自定义string类
#include <iostream> #include <string> int main() { std::string str "Hello, World!"; // 使用 c_str() 将 std::string 转换为 C 风格字符串,并传递给 printf printf("The string is: %s\n", str.c_str()); // 尝试修改…...
Python | Leetcode Python题解之第387题字符串中的第一个唯一字符
题目: 题解: class Solution:def firstUniqChar(self, s: str) -> int:position dict()q collections.deque()n len(s)for i, ch in enumerate(s):if ch not in position:position[ch] iq.append((s[i], i))else:position[ch] -1while q and po…...
RocketMQ 消费时序列化报错问题分析及解决
问题背景 在2024年3月7日,系统消费 RocketMQ 消息时出现了序列化报错,错误信息显示为: java.io.InvalidClassException: com.xxx.xxx.bean.mg.GoodsChangeLogMessage; local class incompatible: stream classdesc serialVersionUID... 这是…...
全能与专精:探索未来AI模型的发展趋势与市场潜力
文章目录 每日一句正能量前言AI模型的全面评估和比较AI模型的专精化和可扩展性AI模型的合理使用和道德规范后记 每日一句正能量 一个人,如果没有经受过投资失败的痛楚,又怎么会看到绝望之后的海阔天空。很多时候,经历了人生中最艰难的事&…...
Python深度学习:【开源数据集系列】ImageNet数据集
ImageNet 是一个大规模的视觉数据集,是计算机视觉领域最重要的基准数据集之一。该数据集由普林斯顿大学和斯坦福大学的研究人员发起,于 2009 年推出。ImageNet 是用于物体分类、目标检测、图像分割、姿势估计等多种任务的通用数据集,尤其在深度学习和计算机视觉的突破性研究…...
微信小程序手写签名
微信小程序手写签名组件 该组件基于signature_pad封装,signature_pad本身是web端的插件,此处将插件代码修改为小程序端可用。 signature_pad.js /*!* Signature Pad v5.0.3 | https://github.com/szimek/signature_pad* (c) 2024 Szymon Nowak | Releas…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
