通过道具传递的ID不显示相关数据

时间:2019-11-08 02:16:53

标签: vue.js

我有一个组件,而另一个组件。基本上,如果我将鼠标悬停在名称上,则希望在下面填充其相关详细信息。到目前为止,我已经成功地传递了id,但是该id并没有太多用处,因为数据无关紧要。我不知道我在想什么

以下是我的代码

<template>
    <div>
      <ul class="pokemon-list">
        <li  v-for="(character, index) in filteredPokemon" :key="index">
         <!-- <router-link :to="'/pokemon/'+ character.url.slice(0,-1).split('/').pop()"> -->
            <a href='#' @mouseover="greet(character.url)">
              {{character.name}} 
            </a>
          <!-- </router-link> -->
        </li>
      </ul>
       <input type="text" v-model="search" placeholder="Search Pokemon">

       <SinglePokemon :name="characters.name" :pid="id"/>
     </div>

</template>

<script>
import SinglePokemon from "./singlePokemon.vue"
export default {
  name: 'pokemon',
  components: {
    SinglePokemon
  },
  data () {
    return {
      id: '',
      characters: [],
      charactersDetails : [],
      search : ""
    }
  },
  methods: {
    greet: function(id){
      this.id = id.slice(0,-1).split('/').pop();
    }
  },
  mounted(){
      let total = this.$http.get(`https://pokeapi.co/api/v2/pokemon`)
        .then((data)=>{
         this.characters = data.body.results;
        }).catch((err)=>{
          console.log(err);
        })
  },
    computed: {
       filteredPokemon: function(){
        return this.characters.filter((character)=> {
            return character.name.match(this.search)
        })
      }
    }
}
</script>

我想在传递ID时显示此组件的相关信息

<template>
    <div>
        <ul class="details">
            <li>
                Name: {{charactersDetails.name}} {{pid}}
            </li>
            <li>
                Abilities: {{charactersDetails.abilities}}
            </li>
            <li>
                Height: {{charactersDetails.height}}
            </li>
            <li>
                Weight: {{charactersDetails.weight}}
            </li>
            <li>
                Species: {{charactersDetails.species}}
            </li>
        </ul>
    </div>
</template>
<script>
export default {
    props: ['name', 'pid'],
    data(){
        return {
            id: this.pid,
            charactersDetails : {
                name : "",
                abilities : "",
                height: "",
                weight: "",
                species: ""
            }
        }
    },
    mounted(){
            let results = this.$http.get(`https://pokeapi.co/api/v2/pokemon/${this.id}`)
                .then((results)=>{
                return results.json()
                }).then(data => {
                    this.charactersDetails.abilities = data.abilities[0].ability.name; //ability
                    this.charactersDetails.name = data.name //name
                    this.charactersDetails.weight =data.weight //weight
                    this.charactersDetails.height = data.height //height
                    this.charactersDetails.species = data.species.name //species name
                })
    }
}
</script>

1 个答案:

答案 0 :(得分:0)

子组件在首次创建时将仅安装一次。此时,pid的值将是一个空字符串。您应该在开发人员工具的“网络”标签中看到相应的HTTP请求。该请求应该会成功,但是我想您会在控制台中收到错误消息,因为返回的数据没有abilities属性。

对父级id属性的后续更改将作为子级pid的属性向下传递。这应该导致模板使用新的pid值进行更新,但不会从服务器加载任何其他数据。

有几种方法可以解决此问题。

一种解决方案是在watch上引入pid

watch: {
  pid: 'loadDetails'
},

created () {
  this.loadDetails()
},

methods: {
  loadDetails () {
    // TODO: You may want alternative behaviour when pid is empty
    if (!this.pid) {
      return
    }

    // Note: this.pid, not this.id
    this.$http.get(`https://pokeapi.co/api/v2/pokemon/${this.pid}`)
      // ... the rest of your code for loading goes here
  }
}

注意:

  1. 构建网址时,我已将this.id更改为this.pid。您还应该从子组件的id中删除data属性。拥有data属性来复制道具是不必要的,并且可能导致错误。
  2. 我已将代码从您的mounted钩子移到名为loadDetails的方法中。 mounted挂钩可以删除。
  3. 我不是从mounted挂钩中加载数据,而是从created挂钩中加载数据。您使用哪个并不重要,但是created对我来说更正确。另外,您可以在immediate上设置watch标志,以便在首次创建组件时自动触发它。
  4. 在当前用例中,由于pid最初为空,因此在首次创建组件时尝试加载数据是无关紧要的。但是,最好编写该组件使其能够在一般情况下工作,而不仅仅是在您遇到的特定情况下。
  5. loadDetails内部,我选择了pid失踪时的援助。如果pid变回空白,则将保留先前的详细信息。目前这可能不是问题,但在一般情况下可能不是正确的行为。
  6. 我已删除了let results =部分。它什么也没做。

解决此问题的另一种方法是使用key

<SinglePokemon :name="characters.name" :pid="id" :key="id" />

使用key会告诉Vue销毁组件,并在id更改时创建一个新组件。新组件将运行其mounted挂钩,因此将运行您的加载代码。

这似乎是一个更简单的解决方案,但它依赖于组件的父级进行一些魔术处理才能使其正常工作。子组件本身非常脆弱。通常,较早的解决方案将是更可取的,因为它可以使子级更加健壮,并且不需要父级组件的任何特殊帮助。