使用插槽调用子方法

Posted

技术标签:

【中文标题】使用插槽调用子方法【英文标题】:Call child method using slot 【发布时间】:2018-09-16 15:18:26 【问题描述】:

我有两个组件。一个子组件有两个 slot,由来自另一个组件的 DOM 填充。我在另一个父组件中使用这个组件。

我想要的是在我单击父组件中的元素时关闭child 组件

html

<div id="app">
  <parent></parent>
</div>

JS

// Child component.
const ChildTemplate = `
    <div class="m-dropdown">
    <button
      class="m-dropdown__button"
      aria-haspopup="true"
      aria-expanded="false"
      @click="handleClick"
      @keyup.esc="close"
      @closeDropdown="isActive = false"
    >
      <slot name="dropdownToggle"></slot>
    </button>
    <div
      class="m-dropdown__content"
      v-show="isActive"
    >
      <slot name="dropdownContent"></slot>
    </div>
  </div>
`;
const Child = 
    template: ChildTemplate,
    data() 
      return 
        isActive: false,
        dropdownCTA: null,
        dropdownCTAClassname: 'm-dropdown__button',
      ;
    ,
    methods: 
      handleClick(e) 
        this.isActive = !this.isActive;
        this.dropdownCTA = e.target.closest('button');
        this.dropdownCTA.setAttribute('aria-expanded', 'true');
      ,
      close() 
        if (this.isActive) 
          this.isActive = false;
          this.dropdownCTA.setAttribute('aria-expanded', 'false');
        
      ,
      documentClick(e) 
        const el = this.$el;
        if (this.isActive && el !== e.target && !el.contains(e.target)) 
          this.close();
        
      ,
    ,
    created() 
      document.addEventListener('click', this.documentClick);
    ,
    destroyed() 
      document.removeEventListener('click', this.documentClick);
       
;
// Parent component.
const ParentTemplate = `
    <child class="m-item-selector">
    <div
      class="m-item-selector__item"
      slot="dropdownToggle"
    >
       itemSelected 
    </div>
    <ul
      slot="dropdownContent"
      class="m-item-selector__item-list"
    >
      <li
        class="m-item-selector__item-wrapper"
        v-for="(item, index) in items"
        :key="index"
      >
        <button
            class="m-item-selector__item"
          @click="selectItem(item)"
         >
            item
         </button>
      </li>
    </ul>
  </child>
`;
const Parent = 
    template: ParentTemplate,
    data() 
      return 
        items: ['item 1', 'item 2', 'item 3'],
        itemSelected: 'item 1',
      ;
    ,
    components: 
      Child,
    ,
    methods: 
      selectItem(item) 
        console.log(item);
        // I want to close my child component in this method but
        // 'this' represents my parent component.
        // How can I access my child component so that
        // I can do something like this: this.close() ?
        this.itemSelected = item;
      ,
       
;

// Register components.
Vue.component('parent', Parent);
Vue.component('child', Child);

new Vue(
  el: "#app"
)

这是小提琴:https://jsfiddle.net/eywraw8t/19300/

【问题讨论】:

只需定义一个变量并将其作为道具传递给孩子。当您希望孩子关闭时,将其设置为 false。 请在问题本身中包含minimal reproducible example。 jsfiddle 可以作为附加帮助存在,但不能单独存在。 @EmileBergeron 更新 ;) 如果像Ohgodwhy mentions 这样的道具不适合您,您可以点击父级,然后点击parent could call the child component function using its ref How to call function on child component on parent events的可能重复 【参考方案1】:

使用默认插槽应该可以:this.$slots.default[0].context.close()

close() 应在组件的 methods 部分中定义

如果你使用命名槽,只需替换default[0]

【讨论】:

以上是关于使用插槽调用子方法的主要内容,如果未能解决你的问题,请参考以下文章

Qt - 使用信号/插槽关闭子菜单

微信小程序-slot插槽功能

微信小程序-slot插槽功能

vue插槽的使用

在 QThread::run 中间调用了一个插槽

从 JavaScript 调用 Qt 插槽