简体   繁体   中英

In Vue, can I transfer props?

Imagine I have a <progress-bar> UI component and I want to create an <app-progress-bar> component that is the same as the <progress-bar> but with some style tweaks.

AppProgressBar.vue:

<template> <progress-bar class="app-progress-bar"></progress-bar> </template>

This will break because <progress-bar> requires a percent prop. So I can pass it in:

<progress-bar class="app-progress-bar" percent="percent"></progress-bar>

This seems fine, but is brittle when <progress-bar> has many props. Can I simply pass through all props? Theoretical syntax:

<progress-bar class="app-progress-bar" {...props}></progress-bar>

Which is similar to React/JSX.

Like already answered, extending the component would be a nice way to create your components in this scenario. Similar to class inheritance in other languages.

However, you can also pass an object as prop. If you want to keep things clean, and don't want to extend your components, you could pass a prop like this:

//object with many values that you need to pass. for ex.
myObjectWithSuff: { percent: 10%, someOtherStuff: value, ... } 

<progress-bar class="app-progress-bar" myProp="myObjectWithStuff"></progress-bar>

Inside the progress-bar component, declare the prop myProp . Then you can access any properties on that object. For example: this.myProp.percent .

This is just quick and simple, but depending on your architecture, extending components may be the way to go.

After researching this, I don't think it's possible. Instead, you can extend a component and put an extraClass key on data or computed :

import ProgressBar from './ProgressBar'

export default {
  extends: ProgressBar,
  data() {
    return { extraClass: 'app-progress-bar' }
  }
}

ProgressBar.vue:

<template>
  <div class="progress-bar" :class="extraClass">...</div>
</template>

This isn't as clean or flexible as React, but it works.

Abstract

This can be done by binding $attrs to the child. So in your case it would be:

<template>
  <progress-bar v-bind="$attrs" class="app-progress-bar"></progress-bar>
</template>

Link to Docs

vm.$attrs: Contains parent-scope attribute bindings (except for class and style)...and can be passed down to an inner component

Source: Vue $attrs documentation

Example

Let's say that a component called <inner> has a boolean prop called dark and a string prop called color .

Now let's define an outer component called <outer> which wraps <inner> in its definition.

<template>
  <inner></inner>
</template>
.
.
.
name: 'outer'

The issue here is if we use the <outer> component, we can't transfer the dark and color props through to the <inner> component which knows what to do with them. For example <inner dark color="blue"></inner> works, but <outer dark color="blue"></outer> doesn't.

If you change the definition of <outer> to include the $attrs binding, it will transfer all the props for you (this doesn't include style and class ). Here is the new definition:

<template>
  <inner v-bind="$attrs"></inner>
</template>
.
.
.
name: 'outer'

Now you can use <outer dark color="blue"></outer> .

Additional note

You can also use the inheritAttrs prop to prevent this behaviour by default. You can take a look at the official Vue docs here and I also found this JSFiddle which gives an example of inheritAttrs being used.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM