【问题标题】:Reusable component access child method in parent slot父槽中的可重用组件访问子方法
【发布时间】:2017-12-24 19:35:33
【问题描述】:

假设我有一个组件Reusable,其方法onClick 设置了一个数据属性。我希望这个组件是可重用的,并且我想使用插槽来覆盖部分。

据我了解,我必须将 onClick 方法作为范围属性从 reusable 传递到 parent

<div class="reusable">
    <h2>Reusable</h2>
    <slot name="clicker" v-bind:onClick="onClick">
        Default stuff <button v-on:click="onClick">Close</button>
    </slot>
    <p v-if="clicked">You clicked me</p>
</div>

<div class="parent">
    <h1>Parent</h1>
    <reusable>
        <template slot="clicker" scope="reusable">
            <button click="reusable.onClick">
                Close from parent
            </button>
        </template>
    </reusable>
</div>

如果我有很多方法,这可能会变得冗长和嘈杂,我想知道:有没有更好的方法,或者这完全是 cromulent?

我已经研究过使用 refs,在父调用 this.$refs.reusable.onClick 上有方法,以及指定动态组件并将它们换出;两者似乎都违反直觉。

【问题讨论】:

  • 我想你想在 parent 组件中处理来自 child 组件的onClick 事件,对吗?
  • @ironcladgeek 我相信parent 是这里的父级,reusable 是在小时候使用parents 范围渲染的:因此我不能只绑定onClickparent 组件不需要知道任何关于reusable 的信息,它只是想覆盖它的一部分。我应该说:上面的例子有效,我只是想知道它是否是正确的方式。

标签: javascript vue.js vuejs2 vue-component


【解决方案1】:

您可以使用对象表示法绑定插槽的属性:

<slot name="clicker" v-bind="{ onClick, onInput, onCustom }">
    Default stuff <button v-on:click="onClick">Close</button>
</slot>

Here's a working fiddle.


如果过于冗长,您至少可以将对象定义移至数据属性并将其从模板中取出:

<slot name="clicker" v-bind="scopeProps">
    Default stuff <button v-on:click="onClick">Close</button>
</slot>
data() {
  return {
    scopeProps: {
      onClick: this.onClick,
      onInput: this.onInput,
      onCustom: this.onCustom
    }
  }
}

【讨论】:

  • 好的,看来这是正确的做法,这肯定会减轻痛苦。这实际上只是明确使用您的组件槽范围的一种情况。
  • scopeProps 上值得一提的一个警告是,您显然会失去data,因此在其中收集方法等并将其称为scopeMethods 或类似名称可能更有意义。
  • 不确定您所说的“失去data”是什么意思。槽的作用域只有你明确分配给它的可用。
  • 如果data{ message: 'Hello', scopeProps: { onClick: this.onClick } },那么如果不将v-bind 更改为{ message: message, scopeMethods: scopeProps } 之类的超小警告,我们就没有message
【解决方案2】:

假设我们有 2 个组件,分别名为 reusableparent

reusable.vue

<template>
  <div class="reusable">
      <h2>Reusable</h2>
      <slot name="clicker">
          Default stuff <button v-on:click="handleClick">Close</button>
      </slot>
      <p v-if="clicked">You clicked me</p>
  </div>
</template>

<script>
export default {
  params: {
    onClick: {
      type: Function,
      default() {}
    }
  }
  
  methods: {
    handleClick() {
      // default codes to execute goes here
      // then call onClick() callback
      this.onClick();
    }
  }
}
</script>

parent.vue

<template>
  <div class="parent">
      <h1>Parent</h1>
      <reusable :on-click="onClickHandler">
          <template slot="clicker">
              // other codes for injecting to slot
          </template>
      </reusable>
  </div>
</template>

<script>
import reusable from './path/to/reusable.vue';

export default {
  components: { reusable },
  
  methods: {
    onClickHandler() {
      // stuff to be run when button in 'reusable' got clicked
    }
  }
}
</script>

这是您的用例的一种可能解决方案。

【讨论】:

  • 我认为这不能解决问题:我们在父级中重新实现了onClick,我认为这是不必要的。我认为父模板需要直接在reusable上调用该方法。
猜你喜欢
  • 2020-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-11
  • 2021-04-08
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
相关资源
最近更新 更多