<template>
  <view class="container" style="height: 100vh; flex-direction: column;">
    <!-- 滚动容器:核心是scroll-into-view属性 -->
    <scroll-view 
      scroll-y="true" 
      :scroll-into-view="targetId"  <!-- 绑定目标元素ID -->
      scroll-with-animation="false"  <!-- 关闭动画,提高可靠性 -->
      style="
        height: 420rpx;               <!-- 固定高度(必须) -->
        width: 100%;                  <!-- 全屏宽度 -->
        background-color: rgba(0,0,0,0.3);
        padding: 20rpx;
        box-sizing: border-box;
        border: 2px solid #ff0000;    <!-- 红色边框,方便观察容器范围 -->
      "
    >
      <!-- 评论列表:每条评论都有唯一ID -->
      <view 
        class="comment-item" 
        v-for="(item, index) in commentList" 
        :key="index"
        :id="`comment-${index}`"  <!-- 唯一ID,格式:comment-0, comment-1... -->
        style="
          margin-bottom: 20rpx;
          padding: 10rpx;
          background-color: rgba(255,255,255,0.1);
        "
      >
        <text style="color: #97def7;">{{ item.username }}:</text>
        <text style="color: #ffffff;">{{ item.content }}</text>
      </view>
    </scroll-view>

    <!-- 发送区域 -->
    <view style="padding: 20rpx; background-color: #1a1a1a;">
      <input 
        v-model="newComment" 
        placeholder="输入评论..." 
        style="
          height: 60rpx;
          background-color: #333333;
          color: #ffffff;
          padding: 0 15rpx;
          border-radius: 30rpx;
        "
      />
      <button 
        @click="sendComment" 
        style="
          margin-top: 10rpx;
          height: 60rpx;
          line-height: 60rpx;
          background-color: #007aff;
          color: #ffffff;
          border-radius: 30rpx;
        "
      >
        发送
      </button>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      commentList: [],       // 评论列表
      newComment: '',        // 输入的新评论
      targetId: '',          // 目标滚动ID(最新评论的ID)
      refreshKey: 0          // 用于强制刷新的key
    };
  },
  onLoad() {
    // 初始化3条评论(确保初始内容不足一屏,方便测试新增效果)
    for (let i = 0; i < 3; i++) {
      this.commentList.push({
        username: '观众' + (i + 1),
        content: '这是第' + (i + 1) + '条初始评论,用于测试滚动效果'
      });
    }
  },
  methods: {
    sendComment() {
      if (!this.newComment.trim()) return;

      // 1. 添加新评论到列表
      this.commentList.push({
        username: '我',
        content: this.newComment
      });
      this.newComment = '';

      // 2. 强制刷新列表(关键:确保nvue识别新评论)
      this.refreshKey++;

      // 3. 定位到最新评论
      this.$nextTick(() => {
        // 计算最新评论的索引
        const lastIndex = this.commentList.length - 1;
        // 设置目标ID(与评论项的:id对应)
        this.targetId = `comment-${lastIndex}`;

        // 4. 双重保险:延迟后再次设置(解决偶发失效)
        setTimeout(() => {
          this.targetId = `comment-${lastIndex}`;
          console.log('已定位到最新评论,ID:', this.targetId);
        }, 200);
      });
    }
  }
};
</script>

实现原理

唯一 ID 绑定:每条评论通过 :id="comment-${index}" 生成唯一 ID(如 comment-0、comment-1)。
目标定位:新增评论后,计算最新评论的索引,将 targetId 设置为最新评论的 ID。
滚动触发:scroll-view 的 scroll-into-view 属性会自动滚动到 targetId 对应的元素位置。

关键优势
稳定性高:通过元素 ID 直接定位,绕过滚动高度计算,避免 scrollTop 相关的兼容性问题。
逻辑简单:无需获取滚动高度,只需管理目标元素的 ID 即可。
强制刷新:通过 refreshKey 确保 nvue 引擎重新渲染列表,识别新添加的评论。

h5和app端都能生效

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐