山东大学软件学院项目实训——创新实训——角色疆界(6)

前言

在前面的工作中,页面基本搭建完成。现在继续做一些小的优化,带来更好地体验。

文本内容复制

1. vuecopy方法思路:

  • 获取代码内容:使用 getElementsByTagName(“code”) 获取包含代码内容的 code元素,并提取其中的 HTML 内容。

  • 解码:使用 decodeURIComponent 对提取的代码内容进行解码,以确保内容格式正确。

  • 复制到剪贴板:调用 this.$copyText(text) 将解码后的内容复制到剪贴板。这个方法通常依赖于第三方库,如 vue-clipboard2 或者其他类似库来实现文本复制。
    视觉反馈:

  • 成功复制后,替换按钮内容为 “Copied!” 图标,并在1秒后恢复原始内容。

  • 如果复制失败,打印错误日志。

vueCopy(node) {
  var code = node.getElementsByTagName("code")[0].innerHTML;
  var text = decodeURIComponent(code);
  this.$copyText(text).then(
    res => {
      var svg = `<svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
                  <polyline points="20 6 9 17 4 12"></polyline>
                </svg>
                <span>Copied!</span>`;
      const nodeInnerHtml = node.innerHTML;
      node.innerHTML = svg;
      setTimeout(() => {
        node.innerHTML = nodeInnerHtml;
      }, 1000);
    },
    err => {
      console.log('复制失败');
    }
  );
}

2. HTML结构和事件绑定思路

  • 按钮结构:复制按钮包含一个 SVG 图标和文字 “Copy code”。
    按钮的 onclick 事件调用 copy(this) 方法。
    隐藏的代码内容:

  • 在按钮中包含一个隐藏的 code>元素,存储待复制的编码文本。这部分内容在 vueCopy 方法中被提取和使用。

  • 事件绑定:通过 οnclick=“copy(this)” 绑定按钮点击事件,调用 copy 方法。

<div class="bg-black mb-4 rounded-md">
  <div class="code_header flex items-center relative text-gray-200 bg-gray-800 px-4 py-2 text-xs font-sans">
    <span>{{infostring || ""}}</span>
    <button onclick="copy(this)" class="flex ml-auto gap-2">
      <svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
        <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path>
        <rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect>
      </svg>
      <span>Copy code</span>
      <code style="display:none">{{encodeURIComponent(code)}}</code>
    </button>
  </div>
  <div class="p-4 overflow-y-auto">
    <code class="!whitespace-pre hljs language-{{infostring}}">{{codeHtml}}</code>
  </div>
</div>

3.copy函数实现思路

  • 绑定事件在 mounted 生命周期钩子中,将 vueCopy 方法绑定到 window.copy,使其在全局范围内可用。
mounted: function () {
  var theme = localStorage.getItem("theme") || "light";
  this.changeTheme(theme);
  this.loadId();
  this.loadConversations();
  this.loadAvatar();

  let chatDivEle = this.$refs.chatContainer;
  chatDivEle.addEventListener('scroll', this.isScrollAndNotBottom, true);

  window.copy = this.vueCopy; // 全局绑定 vueCopy 方法
}

聊天滚动到最底部

实现思路:

  • 确保 DOM 更新后执行使用 Vue 的 nextTick 方法,确保在 DOM 更新后执行滚动操作。
  • 获取聊天容器使用 this.$refs.chatContainer 获取聊天容器元素的引用。
  • 滚动到最底部,使用 scrollTo 方法将聊天容器滚动到最底部,top: scrollElem.scrollHeight 表示滚动到内容的底部,behavior: ‘smooth’ 实现平滑滚动。
handleScrollBottom() {
  this.$nextTick(() => { // 使用 Vue 的 $nextTick 方法来确保 DOM 更新后执行操作
    let scrollElem = this.$refs.chatContainer; // 获取聊天容器元素的引用
    scrollElem.scrollTo({ // 设置滚动位置
      top: scrollElem.scrollHeight, // 滚动到聊天内容的最底部
      behavior: 'smooth' // 滚动行为为平滑滚动
    });
  });
}

判断是否滚动到底部实现思路:

  • 获取聊天容器使用 this.$refs.chatContainer 获取聊天容器元素的引用。
  • 检查是否需要显示滚动到底部的按钮如果聊天内容高度小于或等于聊天容器高度,则不需要显示滚动到底部的按钮,isShowGoBottom 设为 false。
  • 获取滚动位置和高度获取当前滚动位置 scrollTop,聊天容器高度 windowHeight,以及聊天内容高度 scrollHeight。
  • 判断是否滚动到底部如果滚动位置加上容器高度大于等于内容高度减去50,则表示已经接近底部,不需要显示滚动到底部的按钮;否则,isShowGoBottom 设为 true,显示滚动到底部的按钮。
isScrollAndNotBottom() {
  let chatDivEle = this.$refs.chatContainer; // 获取聊天容器元素的引用
  if (!chatDivEle) { // 如果聊天容器元素不存在,则直接返回
    return;
  }

  if (chatDivEle.scrollHeight <= chatDivEle.clientHeight) { // 如果聊天内容高度小于或等于聊天容器高度,则不显示滚动到底部的按钮
    this.isShowGoBottom = false;
    return;
  }

  const scrollTop = chatDivEle.scrollTop; // 获取滚动位置
  const windowHeight = chatDivEle.clientHeight; // 获取聊天容器高度
  const scrollHeight = chatDivEle.scrollHeight; // 获取聊天内容高度
  if (scrollTop + windowHeight >= scrollHeight - 50) { // 如果滚动位置加上聊天容器高度大于等于聊天内容高度减去 50,则不显示滚动到底部的按钮
    this.isShowGoBottom = false;
    return;
  }
  this.isShowGoBottom = true; // 显示滚动到底部的按钮
}

事件绑定和调用:
在组件挂载时,通过 mounted 生命周期钩子绑定滚动事件,以便在用户滚动时检测是否需要显示滚动到底部的按钮。

mounted: function () {
  var theme = localStorage.getItem("theme") || "light";
  this.changeTheme(theme);
  this.loadId();
  this.loadConversations();
  this.loadAvatar();

  let chatDivEle = this.$refs.chatContainer;
  chatDivEle.addEventListener('scroll', this.isScrollAndNotBottom, true); // 绑定滚动事件

  window.copy = this.vueCopy; // 全局绑定 vueCopy 方法
}

滚动到底部按钮的显示和点击事件:

  • 按钮显示控制:使用 v-show=“isShowGoBottom” 控制按钮的显示和隐藏。isShowGoBottom 在 isScrollAndNotBottom 方法中根据滚动位置动态设置。
  • 点击事件绑定:绑定 @click=“handleScrollBottom” 点击事件,调用 handleScrollBottom 方法将聊天容器滚动到底部。
<transition name="el-fade-in-linear">
  <!-- 回到底部 -->
  <button v-show="isShowGoBottom" @click="handleScrollBottom"
          class="cursor-pointer absolute right-6 bottom-[124px] md:bottom-[120px] z-10 rounded-full border border-gray-200 bg-gray-50 text-gray-600 dark:border-white/10 dark:bg-white/10 dark:text-gray-200">
    <svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round"
         stroke-linejoin="round" class="h-4 w-4 m-1" height="1em" width="1em"
         xmlns="http://www.w3.org/2000/svg">
      <line x1="12" y1="5" x2="12" y2="19"></line>
      <polyline points="19 12 12 19 5 12"></polyline>
    </svg>
  </button>
</transition>

总结

当用户点击复制按钮时,会触发 vueCopy 方法,从而将代码片段复制到剪贴板并显示视觉反馈,指示复制操作成功或失败。整个过程涉及获取代码内容、解码、复制到剪贴板以及提供用户反馈。而滚动到底部的判定和实现具体步骤包括获取 DOM 元素、计算滚动位置、设置滚动行为和动态显示/隐藏按钮。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值