单击 div 上的事件以获取 innerText 值并使用事件总线 $emit 到另一个组件不起作用

Posted

技术标签:

【中文标题】单击 div 上的事件以获取 innerText 值并使用事件总线 $emit 到另一个组件不起作用【英文标题】:Click event on div to get innerText value and $emit with event-bus to another component not working 【发布时间】:2020-01-02 16:41:42 【问题描述】:

我有一个 div 列表,其中包含我从 API 调用中获得的产品信息。在另一个组件/视图中,我想在单击 div 时显示单个产品信息。

所以我要做的是通过在单击 div 时访问事件对象来检索产品 ID,然后将该 ID 存储在变量(不是数据属性)中,然后使用事件总线 $emit 它,然后在我的其他组件中侦听它并使用该 ID 进行 API 调用以获取该单个产品的信息。我不确定这是否是做我想做的事情的最佳方式,但这是我现在想到的唯一方式。

但是到目前为止,我遇到了一些不同的错误,并且显示单个产品的组件没有呈现。

这是显示产品/div列表的组件

<template>
  <div>
    <div class="pagination">
      <button :disabled="disabled" @click.prevent="prev()">
        <i class="material-icons">arrow_back</i>
      </button>
      <span class="page-number"> currentPage </span>
      <button @click.prevent="next()">
        <i class="material-icons">arrow_forward</i>
      </button>
    </div>
    <div class="products">
      <div
        class="product"
        @click="getSingleBeer($event)"
        v-for="product in products"
        :key="product.id"
      >
        <h2 class="name"> product.name </h2>
        <div class="image">
          <img :src="product.image_url" />
        </div>
        <h3 class="tagline"> product.tagline </h3>
        <h3 class="first-brewed"> product.first_brewed </h3>
        <h3 class="abv"> product.abv %</h3>
        <p class="id"> product.id </p>
      </div>
    </div>
  </div>
</template>

<script>
import axios from "axios";
import  eventBus  from "../main";

export default 
  name: "Products",
  data() 
    return 
      products: [],
      currentPage: 1,
      searchVal: ""
    ;
  ,
  created() 
    this.getBeers();

    eventBus.$on("keyword", val => 
      this.searchVal = val;

      this.getBeersForSearch();
    );
  ,
  computed: 
    apiUrl() 
      return `https://api.punkapi.com/v2/beers?page=$this.currentPage&per_page=16`;
    ,
    apiUrlForSearch() 
      return `https://api.punkapi.com/v2/beers?page=$this.currentPage&per_page=12&beer_name=$this.searchVal`;
    ,
    disabled() 
      return this.currentPage <= 1;
    ,
    isFirstPage() 
      return this.currentPage === 1;
    
  ,
  methods: 
    async getBeers() 
      try 
        const response = await axios.get(this.apiUrl);

        this.products = response.data;

        console.log(response);
       catch (error) 
        console.log(error);
      
    ,
    async getBeersForSearch() 
      try 
        this.currentPage = 1;

        const response = await axios.get(this.apiUrlForSearch);

        this.products = response.data;

        console.log(response);
       catch (error) 
        console.log(error);
      
    ,
     getSingleBeer($event) 
      const id = parseInt($event.target.lastChild.innerText);
      eventBus.$emit("beer-id", id);
      this.$router.push( name: "Beer" );
    
  
;
</script>

这是显示单个选定产品信息的组件/视图。

<template>
  <div class="beer-container">
    <div class="description">
      <h2> beer.description </h2>
    </div>
    <div class="img-name">
      <h1> beer.name </h1>
      <img :src="beer.image_url" alt />
    </div>
    <div class="ingredients"></div>
    <div class="brewer-tips">
      <h2> beer.brewers_tips </h2>
    </div>
  </div>
</template>

<script>
import  eventBus  from "../main";
import axios from "axios";

export default 
  name: "Beer",
  data() 
    return 
      beerId: null,
      beer: []
    ;
  ,
  created() 
    eventBus.$on("beer-id", id => 
      this.beerId = id;
      this.getBeer();
      console.log(this.beer);
    );
  ,
  methods: 
    async getBeer() 
      try 
        const response = await axios.get(this.apiUrl);

        this.beer = response.data[0];

        console.log(response.data[0]);
       catch (error) 
        console.log(error + "Eroorrrrrr");
      
    
  ,
  computed: 
    apiUrl() 
      return `https://api.punkapi.com/v2/beers/$this.beerId`;
    
  
;
</script>

到目前为止我遇到的一些错误: 1-当我观察控制台日志而不是一次时,同时进行 2-3 次 api 调用。

GET https://api.punkapi.com/v2/beers/null 400
Error: Request failed with status code 400Eroorrrrrr
GET https://api.punkapi.com/v2/beers/null 400
Error: Request failed with status code 400Eroorrrrrr
GET https://api.punkapi.com/v2/beers/null 400
Error: Request failed with status code 400Eroorrrrrr

2-我第一次单击 div 时,它会指向新的路由/组件,但我没有收到任何错误,而且幕后似乎没有任何事情发生。 3- 我也遇到了这个错误:

[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'innerText' of null"
And
TypeError: Cannot read property 'innerText' of null

我的路由器.js

import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
import Beer from "./views/Beer.vue";

Vue.use(Router);

export default new Router(
  mode: "history",
  base: process.env.BASE_URL,
  routes: [
    
      path: "/",
      name: "home",
      component: Home
    ,
    
      path: "/beer",
      name: "Beer",
      component: Beer
    
  ]
);

更新:我能够将数据传递给下一个组件,但是当我第一次单击产品 div 时,什么也没发生,我只会被定向到下一个路由/组件,但数据不会被传递。当我返回并再次单击时,(不刷新页面)数据被传递,但组件上没有呈现任何内容。

【问题讨论】:

【参考方案1】:

我相信您可以通过将@click 更改为:

@click="getSingleBeer(product.id)"

应该为你传递 id,所以你可以这样做:

getSingleBeer(beerId) 
    eventBus.$emit("beer-id", beerId);
    this.$router.push( name: "Beer" );

【讨论】:

首先感谢您的建议。我不敢相信我没有想到以这种方式获取 id,而不是以我尝试的愚蠢方式来做。我尝试了你的建议,它的工作原理是我成功地接收了另一个组件中的 id。当我在控制台记录所有内容时,似乎出现了类似的模式,即在重新加载页面后的第一次尝试中,ID 被记录在另一端,但没有发生 api 调用。然后当我转到上一页(不刷新)时,api调用触发但它返回一个错误。 是的,你只传递了 id,而不是产品,你可以让它 @click="getSingleBeer(product)" 和 getSingleBeer(beer) eventBus.$emit("beer",啤酒); this.$router.push( name: "Beer" ); 哦,我亲爱的主......我可以获取 id,这意味着我也可以获取整个产品,而不是在我的其他组件中进行单独的 api 调用。我相信这就是你所说的? :) 确实如此。比玩 $event.target.lastChild.innerText 和 ajax 调用和其他东西要容易得多! ;) 我已经 3 天没睡了,哈哈,但无论如何我都不知道该怎么感谢你,马特 :) 现在一切都像黄油一样光滑,但我不知道为什么我的新组件是不渲染/安装...

以上是关于单击 div 上的事件以获取 innerText 值并使用事件总线 $emit 到另一个组件不起作用的主要内容,如果未能解决你的问题,请参考以下文章

jquery在动画div上的多次点击事件

给div添加单击事件,如何传递一个参数,比如数字?在事件函数中获取到div对象也行

有没有办法只获取顶部元素的innerText(并忽略子元素的innerText)?

InnerHTMl,innerText,outerHtml,outerText

在 Blazor 上单击 div 或元素外部以将其关闭的事件

父级上的jQuery单击事件,但找到子(单击)元素