vue父组件传来的值,作为子组件$refs的键名选择DOM元素,打印$refs[传来的值] 显示undefined

需求为:一个地址列表,点击右边的字母表中的字母,列表跳转到对应首字母部分。
图片描述

组件的结构是字母组件在根组件里,根组件里有个动态组件component,根据境外目的地和境内目的地按钮的切换来切换下面城市列表组件。

采用的方法是,当点击字母时,触发事件将e.target.innerHTML通过$emit('letterChange', e.target.innerHTML)传给根组件,根组件再将数据传给component动态组件,最后分别在境外目的地和境内目的地子组件中用props接收,并用watch监听数据的变化,当变化时获取this.$refs[this.letter][0],并计算其距离顶部的距离,然后设置scrolltop,已达到滚动到指定位置的目的。DOM中的列表用循环字母表事先绑定了ref。

//此为根组件
<template>
  <div class="destination">
    <letter-list @change="letterChange"></letter-list> //字母组件
    <destination-header></destination-header>
    <destination-list :letter="letter"></destination-list> //目的地列表组件,里面包含切换境内境外的动态组件
  </div>
</template>


/此为目的地列表组件
  <template>
  <section class="del-list">
    <div class="tab-contain" :class="{fixed: isfixed}">
      <ul class="tab">
          <li class="tab-item"
          v-for="item of tabs"
          :key="item.id"
          :class="{ active: currentTab===item.id}"
          @click="currentTab = item.id"
          >{{item.value}}</li>
          <span class="line" :class="{transition:currentTab==='internal-list'}"></span>
      </ul>
    </div>
    <component :is="currentTabComponent" :letter="letter"></component> //此为动态组件,将父组件传来的值,再向下传给里面的境内目的地和境外目的地组件
  </section>
</template>


//此为城市目的地境外部分的组件
<template>
  <div class="abroad-list">
      <div class="hot">
        <div class="title">热门推荐</div>
        <ul class="hot-recommend">
          <li v-for="item in hotRecommend" :key="item.id">
            <a :href="item.jumpInfo.jumpH5Url">
              <img :src="item.images[0]">
              <div><span>{{item.title}}</span><p>{{item.subTitle}}</p></div>
            </a>
          </li>
        </ul>
      </div>
      <div class="all-dest">
        <div class="title">选择目的地</div>
          <ul class="all-dest-list">
            <li class="dest"
            v-for="items of allDest"
            :key="items.title"
            :ref="items.title"> //此处通过循环数组里的每个对象,将其title的值绑定为ref,即A、B、C、D...Z
              <div class="title">{{items.title}}</div>
              <ul class="dest-items">
                <li
                v-for="item of items.list" //此处通过循环对象的list项这个数组,添加具体的城市名
                :key="item.id">
                  <a :href="item.jumpInfo.jumpH5Url">{{item.title}}</a>
                </li>
              </ul>
            </li>
          </ul>
      </div>
  </div>
</template>

问题是现在传过来的值在watch中能打印出来

console.log(this.letter) //A  B  C  D  E...点击哪个打印哪个

但用到this.$refs里却是undefined,如下:

consol.log(this.$refs[this.letter]) //undefined,

加上数组索引

consol.log(this.$refs[this.letter][0]) //Error in callback for watcher "letter": "TypeError: Cannot read property '0' of undefined"

vue直接报错"Error in callback for watcher "letter": "TypeError: Cannot read property '0' of undefined""

直接写死$refs的键名,像这样

console.log(this.$refs.A[0]) //<li>...</li>
console.log(this.$refs.B[0]) //<li>...</li>
console.log(this.$refs.G[0]) //<li>...</li>
...

都能打印出对应的元素内容。

更离奇的是

console.log(typeof this.letter) //打印出来类型是string

但我用

console.log(this.letter instanceof String) //输出的确实false

这个this.letterd 到底是个什么东西啊?!崩溃了,搞了一整天了。
之前是直接把点击获得的数据传入vuex的store里,然后在列表组件里...mapState获取并用watch监听,但仍然还是这个一模一样的问题。

求大神解答

阅读 5.4k
4 个回答

clipboard.png

同款报错
调试发现问题

clipboard.png

clipboard.png

clipboard.png

获取到的值用多余的空格,导致无法通过$refs获取到对象

clipboard.png

加trim去掉空格,问题解决

clipboard.png

这种问题无法通过console打印发现。希望对你有用!!

     // 遇到同样的问题  修改以下代码试试不报错
       <div class="all-dest">
        <div class="title">选择目的地</div>
          <ul class="all-dest-list">
            <li class="dest"
            v-for="(items, key) of allDest"
            :key="key"
            :ref="key"> //此处通过循环数组里的每个对象,将其title的值绑定为ref,即A、B、C、D...Z
              <div class="title">{{key}}</div>
新手上路,请多包涵

我今天刚好百度这个问题看到了 我把我觉的对的方法给你写下

const elm = this.$refsthis.letter
console.log(elm)

这样试下吧 用一个const定义,看看还报错不

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏