从组件继承属性

时间:2019-11-07 15:57:04

标签: vue.js

不太确定我是否能从手册(或完全vue.js)中了解“非属性”:https://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>

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

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

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

该流应该是(并且是这样工作的)-在按下Enter键之后,写入ChildComponent中文本字段的任何内容都应一直发送到ParentComponent,因为parentValueparentMethod()应该被调用。< / p>

  1. 如果我正确理解BasicComponent是其模板根组件的一种扩展,则意味着<input>将不仅具有props类型和class set,而且还将placeholder(具有“ default”值)?

  2. 这是否也意味着分配了v-model数据的parentValue道具也将传播到<input>元素,使我的:valuev-on绑定冗余吗?

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

    < / li>
  4. 我也很难理解listeners()方法中发生的一切,因此,对破译它的任何帮助将不胜感激。 :D

预先感谢您的帮助。

欢呼

1 个答案:

答案 0 :(得分:1)

让我们一次做一个主题...

道具和非道具属性之间的区别:

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

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

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

您所遇到的事件流:

是的,您在ChildComponent 上键入的内容已被传递给ParentComponent。它们通过您的v-model@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">

您的<input>标记将继承<ChildComponent> 除外 typevalue和您的侦听器的所有属性(稍后会详细介绍)。该规则的例外是classstyle,它们始终被继承。

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

这是否意味着分配了parentValue数据的v模型道具也将传播到元素,从而使我的: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)
    }
}

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

分配在这一行中完成:

...this.$listeners,

它使用传播运算符将$listeners变量(包含所有组件事件)中的所有元素添加到要返回的对象中。

您不继承的唯一事件是input,如以下行所示:

input: event => this.$emit('input', event.target.value)

在这一行中,您告诉代码input事件的行为将是您定义的行为,而不是继承的行为。

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

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

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

您正在做两件事:

  • 您正在将parentValue的值分配给value的{​​{1}}道具
  • 您要告诉组件在调用ChildComponent事件时更新parentValue

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

要解决此问题,您有两种选择:

  • childValue重命名为childValue
  • 或者告诉您的组件使用value作为模型

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

ChildComponent

这将告诉您的组件使用该道具和该事件来使model: { prop: 'childValue', event: 'input' } 工作。

结束

最后的提示:将来,请尝试将问题缩小到单个主题。这样会更容易回答,并会帮助以后搜索这些主题的人。