当前位置:首页 > 问答 > 正文

鼠标放上去那栏数据马上从数据库里拉信息显示出来用JS怎么弄

这个效果通常被称为“鼠标悬停加载”或“悬停预览”,核心思路是当用户的鼠标移动到某个元素上时,JavaScript立刻去请求服务器,服务器从数据库查询到数据后返回给前端,前端再把这些数据动态显示出来,整个过程要快,让用户感觉信息是瞬间出现的,下面我们一步步拆解怎么做。

你得有一个可以触发事件的HTML元素,比如一个列表,列表里的每一项都是一个名字,你希望鼠标放到某个名字上时,旁边就显示出这个人的详细信息。

HTML部分可能很简单:

<ul id="nameList">
  <li data-user-id="1">张三</li>
  <li data-user-id="2">李四</li>
  <li data-user-id="3">王五</li>
</ul>
<div id="userInfo"></div>

这里的关键是 data-user-id 这个属性,我们把它像一个小纸条一样贴在每个名字上,纸条上写着这个用户对应的数据库ID,这样,当鼠标放上去时,JavaScript就能知道该去数据库拉哪个人的信息了。

接下来是重头戏,用JavaScript来实现逻辑,我们要做两件主要的事:一是监听鼠标悬停事件,二是去请求数据。

第一步,监听事件,我们不能给每个列表项都写一遍重复的代码,那样很麻烦,好的做法是只给它们的父元素(就是那个<ul id="nameList">)绑一个事件监听器,利用“事件冒泡”机制,简单说就是,不管鼠标放在哪个<li>上,这个事件都会“冒泡”到它的父元素<ul>那里被捕捉到,这种方法叫“事件委托”,效率高,尤其适合列表项很多的情况。

document.getElementById('nameList').addEventListener('mouseover', function(event) {
  // 检查触发事件的元素是不是我们关心的<li>标签
  if (event.target.tagName === 'LI') {
    // 获取贴在<li>上的数据ID
    const userId = event.target.getAttribute('data-user-id');
    // 拿到这个ID,我们就可以去拉取数据了
    fetchUserInfo(userId);
  }
});

第二步,请求数据,这里我们使用现代JavaScript中非常常用的 fetch API来向服务器发送请求,你需要提前准备好一个服务器端的接口(比如叫做 /getUserInfo),这个接口能接收一个用户ID,然后去数据库查询,最后把用户信息(比如年龄、邮箱等)以JSON格式返回。

function fetchUserInfo(userId) {
  // 向服务器发送请求,URL中包含了用户的ID
  fetch(`/getUserInfo?userId=${userId}`)
    .then(response => {
      // 检查响应是否成功
      if (!response.ok) {
        throw new Error('网络响应不正常');
      }
      // 把响应内容解析成JSON格式
      return response.json();
    })
    .then(data => {
      // 请求成功,拿到了数据(data)
      // 现在把数据显示在页面上那个id为"userInfo"的div里
      displayUserInfo(data);
    })
    .catch(error => {
      // 如果请求过程中出了任何错误(比如网络问题、服务器错误),在这里处理
      console.error('获取用户信息失败:', error);
      document.getElementById('userInfo').innerHTML = '<p>信息加载失败</p>';
    });
}

第三步,显示数据,我们写一个简单的函数,把从服务器返回的数据组装成HTML,插入到页面中。

function displayUserInfo(userData) {
  const infoDiv = document.getElementById('userInfo');
  // 使用模板字符串可以很方便地嵌入变量,生成HTML内容
  infoDiv.innerHTML = `
    <h3>${userData.name}的详细信息</h3>
    <p>年龄: ${userData.age}</p>
    <p>邮箱: ${userData.email}</p>
    <p>部门: ${userData.department}</p>
  `;
}

直接这样做可能会有一个问题:如果用户快速地在多个列表项上来回移动鼠标,就会触发很多次请求,这些请求发往服务器的顺序和它们返回的顺序可能不一致,导致最终显示的信息可能不是最后悬停的那个人的,而是某个较早请求的、但返回较慢的数据,这就产生了信息错乱。

为了解决这个问题,我们需要一个“防抖”或“取消上一次请求”的机制,一个更实用的方法是“取消上一次未完成的请求”,我们可以这样做:

// 创建一个变量来保存上一次的请求控制器
let abortController = null;
function fetchUserInfo(userId) {
  // 如果上一次请求还没完成,就取消它
  if (abortController) {
    abortController.abort();
  }
  // 创建一个新的AbortController对象,用于控制本次请求
  abortController = new AbortController();
  const signal = abortController.signal;
  fetch(`/getUserInfo?userId=${userId}`, { signal }) // 将signal信号关联到这次fetch请求
    .then(response => {
      if (!response.ok) {
        throw new Error('网络响应不正常');
      }
      return response.json();
    })
    .then(data => {
      // 显示数据
      displayUserInfo(data);
      // 请求成功完成,将abortController置空
      abortController = null;
    })
    .catch(error => {
      // 如果错误是因为请求被取消(abort)引起的,我们就不处理,也不报错
      if (error.name === 'AbortError') {
        console.log('请求被取消,因为用户又悬停了另一项');
      } else {
        // 其他错误照常处理
        console.error('获取用户信息失败:', error);
        document.getElementById('userInfo').innerHTML = '<p>信息加载失败</p>';
        abortController = null;
      }
    });
}

这样,当用户快速切换悬停目标时,JavaScript会自动取消掉那些已经发出但尚未完成的旧请求,只保留并等待最新一次请求的结果,从而确保显示的信息总是正确的。

为了更好的用户体验,你还可以在发送请求时,在显示信息的区域加一个“加载中...”的提示。

function fetchUserInfo(userId) {
  if (abortController) {
    abortController.abort();
  }
  abortController = new AbortController();
  const signal = abortController.signal;
  // 在等待数据时先显示一个加载提示
  document.getElementById('userInfo').innerHTML = '<p>加载中...</p>';
  fetch(`/getUserInfo?userId=${userId}`, { signal })
    .then(...) // 后面的代码和上面一样
}

实现这个功能的关键点在于:1. 使用HTML的data-*属性存储关键ID;2. 利用事件委托监听鼠标悬停;3. 使用fetchAPI异步请求数据;4. 使用AbortController解决请求竞态问题;5. 提供加载状态和错误处理以提升用户体验,服务器端的部分需要你另外编写,用于接收请求、查询数据库并返回JSON数据。

鼠标放上去那栏数据马上从数据库里拉信息显示出来用JS怎么弄