使用slot调用子方法

时间:2018-04-06 14:48:30

标签: javascript vue.js

我有两个组成部分。一个子组件,其中有两个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/

1 个答案:

答案 0 :(得分:0)

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

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

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