Vue.js - 当子组件在 <transition> 内时,无法访问 this.$parent

Posted

技术标签:

【中文标题】Vue.js - 当子组件在 <transition> 内时,无法访问 this.$parent【英文标题】:Vue.js - no access to this.$parent when child component is inside <transition> 【发布时间】:2021-05-26 18:06:01 【问题描述】:

我想要什么:我有两个组件,父组件(Wall.vue)和子组件(PostItem.vue)。每个PostItem 都有一个删除 按钮。单击时,会发送对我的 API 的请求,并从数据库中删除该项目。然后我想调用父组件的getPosts函数再次获取所有帖子(这次没有删除帖子)。

问题:在子组件内部,我无法访问this.$parent 对象(或者更具体地说,它只是空的并且不包含函数),所以我不能调用getPosts-函数。当我删除父组件中包含子组件的 &lt;transition-group&gt; 时,一切正常。

这里有什么问题?

父组件(Wall.vue)

模板部分:

<template>
  <div class="Wall view">  
      <transition-group name="wallstate">
        <template v-else-if="messages">
          <PostItem
            v-for="(message, index) in messages"
            :key="index"
            :message="message"
            :index="index"
            class="PostItem"
          />
        </template>
        <h1 v-else>
          Could not load messages. Please try later.
        </h1>
      </transition-group>
  </div>
</template>

脚本部分:

<script>
import  mapGetters  from 'vuex';
import  postsAPI  from '../services/posts.service.js';

import PostItem from '../components/PostItem.vue';

export default 
  components: 
    PostItem,
  ,

  data() 
    return 
      messages: null,
    ;
  ,

  methods: 
    getPosts() 
      ///////Do stuff
    
  
;
</script>

子组件(PostItem.vue)

模板部分

<template>
  <div class="PostItem__message frosted">
    <p class="PostItem__messageContent"> message.content </p>
    <p>
      by: <strong> message.user.username </strong>
    </p>
    <a
      @click="deletePost"
      :data-id="message._id"
      v-if="message.user._id === user.id"
    >
      Delete
    </a>
  </div>
</template>

脚本部分:

<script>
import  postsAPI  from '../services/posts.service.js';
import  mapGetters  from 'vuex';

export default 
  name: 'PostItem',

  props: 
    message: 
      type: Object,
      required: true,
    ,
    index: 
      type: Number,
      required: true,
    ,
  ,

  computed: 
    ...mapGetters(
      user: 'auth/user',
    ),
  ,

  methods: 
    deletePost(e) 
      const id = e.target.dataset.id;
      postsAPI.removeOne(id).then((res) => 
        this.$parent.getPosts();  <-------- PROBLEM HERE
      );
    ,
  ,
;
</script>

【问题讨论】:

【参考方案1】:

通常认为使用this.$parent 是一种不好的做法(它会耦合组件并降低封装/代码清晰度。)子组件在想要向祖先组件发送信息时应该发出事件。

删除直接访问和$emit一个名为“已删除”的事件:

deletePost(e) 
  const id = e.target.dataset.id;
  postsAPI.removeOne(id).then((res) => 
    this.$emit('deleted');  // Emitting the event
  );
,

父级应该监听deleted 事件并运行事件处理程序:

<PostItem
  v-for="(message, index) in messages"
  :key="index"
  :message="message"
  :index="index"
  class="PostItem"
  @deleted="getPosts"
/>

当被@deleted事件监听器触发时,父级会调用getPosts方法。

【讨论】:

【参考方案2】:

在方法部分,而不是:

methods: 
  deletePost(e) 
    const id = e.target.dataset.id;
    postsAPI.removeOne(id).then((res) => 
      this.$parent.getPosts();  
    );
  ,
,

你可以试试这个:

  methods: 
    deletePost(e) 
      const id = e.target.dataset.id;
      let self=this;
      postsAPI.removeOne(id).then((res) => 
        self.$parent.getPosts(); 
    );
  

由于作用域链,.then() 中的 'this' 与变量 'self' 指向的变量环境不同。所以也许这就是它无法工作的原因。

【讨论】:

@Beso 请突出显示您认为是复制的部分和复制的内容:)

以上是关于Vue.js - 当子组件在 <transition> 内时,无法访问 this.$parent的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Vue.js 中绑定整个组件?

如何在 vue 组件中定义变量? (Vue.JS 2)

Vue.js 组件

Vue.js 设置组件数据

Vue.js 在渲染组件之前填充数据

Vue.js 基础学习之组件