Prop 从组件继承

fla*_*rrr 2 vue.js

不太确定我是否理解手册(或 vue.js)中的“非 prop 属性”: https: //v2.vuejs.org/v2/guide/components-props.html

假设我有 ChildComponent.vue 文件:

<template>
  <input type="text" class="input" :value="childValue" v-on="listeners">
</template>

<script>
  export default {
    props: {
      childValue: {
        type: String,
        default: 'blah',
      }
    },
    computed: {
      listeners() {
        return {
          // Pass all component listeners directly to input
          ...this.$listeners,
          // Override input listener to work with v-model
          input: event => this.$emit('input', event.target.value)
        }
      }
    }
  }
</script>
Run Code Online (Sandbox Code Playgroud)

然后我将它添加到 ParentComponent 中,如下所示:

<template>
  <ChildComponent v-model="parentValue" placeholder="default" @keydown.enter="parentMethod"/>
</template>

<script>
  export default {
    data () {
      return {
        parentValue: "",
      };
    },
    methods: {
      parentMethod () {
        ...
      }
    },
  }
</script>
Run Code Online (Sandbox Code Playgroud)

流程应该是(并且像这样工作) - 按 Enter 键后写入 ChildComponent 中的文本字段的任何内容都应该一直发送到 ParentComponent,并且parentValue应该parentMethod()被调用。

  1. 如果我理解正确的话 BasicComponent 是对其模板根组件的扩展,这意味着<input>不仅具有 props 类型和类集,而且placeholder(具有“默认”值)?

  2. 另外,这是否意味着分配数据v-model的 propparentValue也将传播到<input>element,从而使 my:valuev-onbind 冗余?

  3. v-on="listeners"另一个问题 -在不指定事件的情况下到底是如何工作的,这是否意味着我正在监听每个事件?在父组件中有一个简写@keydown.enter,这意味着它正在监听 keydown.enter 事件,但在listeners()方法中我正在发出一个input事件......

  4. 我也很难理解listeners()方法中到底发生了什么,所以任何破译这一点的帮助将不胜感激。:D

预先感谢您的帮助。

干杯

Ayr*_*ton 6

让我们一次讨论一个主题......

prop 属性和非 prop 属性的区别:

Props 是您在对象中定义的参数props。使用 props,您可以告诉用户应该为给定的 prop 使用什么类型、是否需要、默认值、分配验证函数等。

此外,道具是反应性的,因此如果您的模板依赖于道具并且道具更新,那么您的模板也会更新。

您分配给组件但不对应于任何 props 的属性将传递给变量$attrs。您可以使用它来访问这些值,例如$attrs.id获取 id 或$attrs.name获取名称等。

您的案例中的事件流程:

是的,您在 上键入的内容ChildComponent 将被传递到ParentComponent. v-model它们通过 your和 via传递@keydown.enter="parentMethod"

您可能知道事件是如何工作的,但如果您不知道,那么要点如下:当您需要将数据从子组件传递到父组件时,您可以在子组件中发出一个事件,并在父组件中侦听该事件。

例如,如果您想发出一个名为 foo 的事件,您可以$emit使用$emit('foo'). 然后,您可以通过添加到子级来在父级中监听它@foo="yourHandler",其中yourHandler编写了一个用于处理事件的函数。这就是你所做的@keydown.enter="parentMethod"

<input>不仅有道具类型和类集,还有占位符(具有“默认”值)?:

答:这要看情况。模板中的标记将接收的内容<input>取决于根元素 ( ) 是否<input>继承组件属性。inheritsAttrs该行为由组件的属性定义,默认为 true。

这意味着,在您的情况下,由于您没有指定inheritsAttrs它将默认为 true ,并且是的,您传递给的每个属性都<ChildComponent>将传递给您的<input>标签,除了您手动定义的内容。

由于您<input>像这样声明了标签:

<input type="text" class="input" :value="childValue" v-on="listeners">
Run Code Online (Sandbox Code Playgroud)

您的<input>标签将继承<ChildComponent> except typevalue您的侦听器的所有属性(稍后会详细介绍)。该规则的例外是classstyle,无论如何,它们总是被继承。

PS:请注意,typeclassplaceholder是属性,而不是道具。

这是否意味着为parentValue 数据分配的 v-model 属性也将传播到元素,从而使我的 :value 和 v-on 绑定冗余?

答:不可以,但是也行不通。原因如下:

当您使用这段代码声明侦听器时:

listeners() {
    return {
        // Pass all component listeners directly to input
        ...this.$listeners,
        // Override input listener to work with v-model
        input: event => this.$emit('input', event.target.value)
    }
}
Run Code Online (Sandbox Code Playgroud)

listeners您将标记上放置的每个事件侦听器ChildComponent(包括您的事件)分配给您的计算属性keydown,这就是它起作用的原因。

分配是在这一行完成的:

...this.$listeners,
Run Code Online (Sandbox Code Playgroud)

$listeners它使用展开运算符将变量(保存所有组件事件)中的所有元素添加到您要返回的对象中。

您没有继承的唯一事件是input,如以下行中所定义:

input: event => this.$emit('input', event.target.value)
Run Code Online (Sandbox Code Playgroud)

通过这一行,您可以告诉代码,input事件的行为将是您定义的,而不是继承的。

然后,当您分配v-on="listeners"给输入时,您就是在告诉它监听listeners变量上列出的每个事件。也就是说:您将所有继承的事件和自定义input事件附加到输入事件中。

最后,要解释为什么它不是多余的但为什么它不起作用,您必须了解它是如何v-model工作的。它(通常)通过监听input组件的事件并使用它来更新value同一组件的 prop 来工作。所以在这一行中:

<ChildComponent v-model="parentValue" placeholder="default" @keydown.enter="parentMethod"/>
Run Code Online (Sandbox Code Playgroud)

你正在做两件事:

  • 您将 的值分配parentValuevalue的 propChildComponent
  • 您告诉组件在调用事件parentValue时进行更新。input

这意味着为您的标签分配值和侦听器input并不是多余的,因为您需要它才能v-model正常工作,但它最终不会工作,因为您的组件没有道具value。它有一个childValue道具。

要修复它,您有两种选择:

  • 重命名childValuevalue
  • 或者告诉你的组件用作childValue模型

要执行第二种方法,只需将这段代码附加到您的ChildComponent

model: {
    prop: 'childValue',
    event: 'input'
}
Run Code Online (Sandbox Code Playgroud)

这将告诉您的组件使用该道具和该事件来工作v-model

结束

最后一点:将来,尝试将您的问题缩小到一个主题。回答起来会更容易,并且会帮助以后搜索这些主题的人。