vue3 for循环节点设置属性ref和获取的方式

<template>
  <div class="page_box">
    <section class="main">
      <Scroll
        ref='scrollBox'
        :isEnd='isEnd'
        :list="contentList"
        :isLoading='true'
        :preventDefaultException='{ tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|AUDIO)$/ }'
        @pullup='loadMore'>
        <div class="search_wrapper">
          <SearchBox
            @search="handleSearch"/>
        </div>
        <div class="tab_wrapper"
          v-if="tabList[0]">
          <CustomTab1
            :tabs="tabList"
            @change="changeTab"/>
        </div>
        <van-collapse
          class="guide_list"
          v-if="contentList.length"
          v-model="activeIds"
          @change="changeCollapse">
          <van-collapse-item
            class="guide_item"
            title-class="item_title"
            v-for="(info, i) in contentList"
            :key="info.id"
            :title="`Q${i + 1}:${info.title}`"
            :name="info.id">
            <div class="content_wrapper">
              <div class="content_box"
                :ref="(el) => setRefMap(el, info)"
                :class="{
                  fold: info.isFold
                }"
                v-html="info.content"></div>
              <div class="btn_more"
                v-show="info.isFold"
                @click="info.isFold = false">
                查看更多
                <van-icon name="arrow-down"/>
              </div>
              <div class="loading_mask"
                v-show="info.isLoading">
                <van-loading type="spinner" />
              </div>
            </div>
          </van-collapse-item>
        </van-collapse>
        <!-- 数据为空 -->
        <NoData
          v-else/>
      </Scroll>
    </section>
  </div>
</template>
<script setup>
import Scroll from '@/components/Scroll.vue'
import SearchBox from '@/components/SearchBox.vue'
import CustomTab1 from '@/components/CustomTab1.vue'
import NoData from '@/components/NoData.vue'

import guideApi from '@/api/guide.js'

import { ref, nextTick, onMounted } from 'vue'
import { toast } from '@/utils/mixin'

const isEnd = ref(true)
const scrollBox = ref()

const keyword = ref('')
const tabList = ref([])
const loading = ref(false)
const moduleKey = ref({})
const currentPage = ref(1)
const activeIds = ref([])
const oldActiveIds = ref([])
const contentList = ref([])

// 动态ref相关
const refMap = ref({})
const setRefMap = (el, info) => {
  if (el) {
    refMap.value[`content${info.id}`] = el
  }
}

// 切换折叠状态(获取详情内容)
const changeCollapse = (val) => {
  if (val[0]) {
    let currId = ''
    val.forEach(item => {
      if (!oldActiveIds.value.includes(item)) {
        currId = item
      }
    })
    let info = contentList.value.find(item => {
      return item.id === currId
    })
    if (info && !info.content) {
      fetchGuideDetail(info)
    }
    oldActiveIds.value = val
  }
}

// 获取指南详情
const fetchGuideDetail = (info) => {
  info.isLoading = true
  guideApi.getGuideDetail(info.id).then(res => {
    info.isLoading = false
    if (res.code === 0 && res.data) {
      let data = res.data
      if (data) {
        info.content = data.content
        // 判断是否折叠内容
        nextTick(() => {
          let dom = refMap.value[`content${info.id}`]
          let height = dom.clientHeight
          info.isFold = height > 110
        })
      }
    } else {
      toast.alert(res.msg)
    }
  })
}

// 搜索
const handleSearch = (val) => {
  keyword.value = val
  currentPage.value = 1
  contentList.value = []
  fetchGuideList(true)
  // 重置展开项
  activeIds.value = []
  oldActiveIds.value = []
}

// 切换顶部tab
const changeTab = (tab) => {
  moduleKey.value = tab
  currentPage.value = 1
  contentList.value = []
  fetchGuideList(true)
  // 重置展开项
  activeIds.value = []
  oldActiveIds.value = []
}

// 加载更多
const loadMore = () => {
  if (!isEnd.value && !loading.value) {
    currentPage.value += 1
    fetchGuideList()
  }
}

// 滑倒底部
function refreshScroll () {
  nextTick(() => {
    if (scrollBox.value) {
      scrollBox.value.refresh()
    }
  })
}

// 获取指南列表
const fetchGuideList = (isReplace) => {
  let params = {
    search: keyword.value || null,
    category_id: moduleKey.value || null,
    page: currentPage.value,
    page_size: 10
  }
  loading.value = true
  guideApi.getGuideList(params).then(res => {
    if (res.code === 0 && res.data) {
      let results = res.data.results || []
      results.map(item => {
        item.isFold = false
        item.isLoading = false
        item.content = ''
      })
      contentList.value = isReplace ? results : contentList.value.concat(results)
      isEnd.value = contentList.value.length >= +res.data.count
    } else {
      isEnd.value = true
    }
    loading.value = false
    refreshScroll()
  })
}
// 获取分类列表
const fetchCategoryList = () => {
  guideApi.getCategoryList().then(res => {
    if (res.code === 0) {
      let data = res.data
      tabList.value = data
    } else {
      tabList.value = []
      toast.alert(res.msg)
    }
    moduleKey.value = tabList.value[0].id || ''
    fetchGuideList(true)
  })
}

onMounted(() => {
  fetchCategoryList()
})
</script>

<style lang="stylus" scoped>
.page_box
  width 100%
  height 100vh
  background: #F4F4F5;
  .main
    height: 100%
    // position relative
    .search_wrapper
      width 100%
      display: flex
      justify-content: space-between
      align-items: center
      padding 12px
      box-sizing: border-box
      >>> .search_box
        width 100%
    .tab_wrapper
      width 100%
      padding 0 12px
      box-sizing: border-box
    .guide_list
      width 100%
      padding 12px
      box-sizing: border-box
      .guide_item
        width 100%
        background: #fff
        border-radius: 8px
        overflow: hidden
        margin-bottom 12px
        >>>.item_title
          span
            font-weight: 600
            font-size 15px
            color: #0082A8
        .content_wrapper
          position relative
          .content_box
            width 100%
            line-height: 20px
            font-size 13px
            color: #63666A
            white-space: break-spaces
            &.fold
              height 100px
              overflow hidden
          .btn_more
            line-height: 20px
            text-align: center
            color #93999F
            margin-top: 10px
          .loading_mask
            width 100%
            height 100%
            display: flex
            justify-content: center
            align-items center
            position absolute
            top 0
            left 0
</style>
目标效果:富文本内容高度超过100px显示“查看更多”
image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356

推荐阅读更多精彩内容