Bootstrap

前端必知必会-Vue Props


Vue Props

Props 是 Vue 中的一个配置选项。

使用 props,我们可以通过组件标签的自定义属性将数据传递给组件。

将数据传递给组件

您还记得上一文章中所有三个组件都显示“Apple”的示例吗?使用 props,我们现在可以将数据传递给我们的组件,为它们提供不同的内容并使它们看起来不同。

让我们制作一个简单的页面来显示“Apples”、“Pizza”和“Rice”。

在主应用程序文件 App.vue 中,我们创建了自己的属性“food-name”,以便使用 <food-item/> 组件标签传递 prop:

App.vue:

<template>
<h1>Food</h1>
<food-item food-name="Apples"/>
<food-item food-name="Pizza"/>
<food-item food-name="Rice"/>
</template>

<script></script>

<style>
#app > div {
border: dashed black 1px;
display: inline-block;
width: 120px;
margin: 10px;
padding: 10px;
background-color: lightgreen;
}
</style>

在组件内接收数据

要从 App.vue 接收通过“food-item”属性发送的数据,我们使用这个新的“props”配置选项。我们列出收到的属性,以便我们的组件 *.vue 文件知道它们,现在我们可以像使用数据属性一样在任何需要的地方使用 props。

FoodItem.vue:

<script>
export default {
props: [
'foodName'
]
}
</script>

Props 属性在 <template> 标签中用破折号 - 分隔单词(kebab-case),但 kebab-case 在 JavaScript 中不合法。因此,我们需要在 JavaScript 中将属性名称写成驼峰式大小写,Vue 会自动理解这一点!

最后,我们的例子使用 <div> 元素表示“Apples”、“Pizza”和“Rice”,如下所示:

示例获取您自己的 Vue 服务器
App.vue:

<template>
<h1>Food</h1>
<food-item food-name="Apples"/>
<food-item food-name="Pizza"/>
<food-item food-name="Rice"/>
</template>

FoodItem.vue:

<template>
<div>
<h2>{{ foodName }></h2>
</div>
</template>

<script>
export default {
props: [
'foodName'
]
}
</script>

<style></style>

很快我们将看到如何将不同的数据类型作为 props 属性传递给组件,但在此之前,让我们扩展我们的代码,描述每种类型的食物,并将食物 <div> 元素放在 Flexbox 中包装器。

示例
App.vue:

<template>
  <h1>Food</h1>
  <div id="wrapper">
    <food-item
      food-name="Apples"
      food-desc="Apples are a type of fruit that grow on trees."/>
    <food-item
      food-name="Pizza"
      food-desc="Pizza has a bread base with tomato sauce, cheese, and toppings on top."/>
    <food-item
      food-name="Rice"
      food-desc="Rice is a type of grain that people like to eat."/>
  </div>
</template>

<script></script>

<style>
  #wrapper {
    display: flex;
    flex-wrap: wrap;
  }
  #wrapper > div {
    border: dashed black 1px;
    margin: 10px;
    padding: 10px;
    background-color: lightgreen;
  }
</style>

FoodItem.vue:

<template>
  <div>
    <h2>{{ foodName }}</h2>
    <p>{{ foodDesc }}</p>
  </div>
</template>

<script>
  export default {
    props: [
      'foodName',
      'foodDesc'
    ]
  }
</script>

<style></style>

布尔属性

我们可以通过传递不同数据类型的属性来实现不同的功能,并且我们能够定义从 App.vue 创建组件时如何赋予属性的规则。

让我们添加一个新的属性“isFavorite”。这应该是一个布尔属性,其值为 true 或 false,以便我们可以直接将其与 v-show 一起使用,以在食物被视为最爱时显示收藏戳 <img> 标签。

要传递数据类型不同于 String 的 props,我们必须在要传递的属性前面写上 v-bind:。

这就是我们将 App.vue 中的布尔值“isFavorite”prop 作为属性“is-favorite”传递的方式:

App.vue:

<template>
  <h1>Food</h1>
  <p>My favorite food has a diploma image attached to it.</p>
  <div id="wrapper">
    <food-item
      food-name="Apples"
      food-desc="Apples are a type of fruit that grow on trees."
      v-bind:is-favorite="true"/>
    <food-item
      food-name="Pizza"
      food-desc="Pizza has a bread base with tomato sauce, cheese, and toppings on top."
      v-bind:is-favorite="false"/>
    <food-item
      food-name="Rice"
      food-desc="Rice is a type of grain that people like to eat."
      v-bind:is-favorite="false"/>
  </div>
</template>

我们在 FoodItem.vue 中接收布尔值 ‘isFavorite’ prop,如果食物被认为是最喜欢的,则显示最喜欢的标记:

示例
FoodItem.vue:

<template>
  <div>
    <h2>
      {{ foodName }}
      <img src="/img_quality.svg" v-show="isFavorite">
    </h2>
    <p>{{ foodDesc }}</p>
  </div>
</template>

<script>
  export default {
      props: ['foodName','foodDesc','isFavorite']
  }
</script>

<style>
  img {
    height: 1.5em;
    float: right;
  }
</style>

图像:要使上述示例中的图像在您机器上的项目中本地工作,请打开上述示例,右键单击图像,选择e “将图像另存为…”并将其保存在项目中的“公共”文件夹中。

道具接口

在上面的例子中,基于 FoodItem.vue 中的代码,我们无法确定我们是否收到了“isFavorite”道具,也无法确定它是否是布尔值。为了帮助我们解决这个问题,我们可以定义我们收到的道具的数据类型,我们可以将道具设置为必需的,我们甚至可以制作验证函数来验证我们收到的道具。

如果您在团队中工作,定义我们收到的道具可以作为其他人的文档,如果我们定义的规则被破坏,它会在控制台中向我们提供警告。

道具作为对象

在 FoodItem.vue 中,我们注释掉了我们如何在数组中定义道具以将其作为引用,而是在对象中定义道具。除了 prop 名称之外,我们还可以定义每个 prop 的数据类型,如下所示:

FoodItem.vue:

<script>
  export default {
    // props: ['foodName','foodDesc','isFavorite']
    props: {
      foodName: String,
      foodDesc: String,
      isFavorite: Boolean
    }
  }
</script>

使用这种方式定义的 prop,其他人可以查看 FoodItem.vue 内部并轻松了解组件的期望。

如果从父元素(在我们的例子中是 App.vue)创建组件并给定具有错误数据类型的 prop,您会在控制台中收到警告,如下所示:

错误数据类型 prop 警告的屏幕截图

此类警告很有用,可以让我们自己和其他人知道组件没有按照预期使用,并告诉我们哪里出了问题,以便我们纠正错误。

必需的 props

要告诉 Vue 某个 prop 是必需的,我们需要将 prop 定义为对象。让我们将 prop ‘foodName’ 设为必需的,如下所示:

FoodItem.vue:

<script>
export default {
// props: ['foodName','foodDesc','isFavorite']
props: {
foodName: {
type: String,
required: true
},
foodDesc: String,
isFavorite: Boolean
}
}
</script>

如果从父元素(在我们的例子中是 App.vue)创建组件并且未定义必需的 prop,则会在控制台中收到警告,如下所示:

必需 prop 警告的屏幕截图

此类警告很有用,可以让我们和其他人知道组件未按预期使用,并告诉我们哪里出了问题,以便我们纠正错误。

默认值

我们可以为 prop 设置默认值。

让我们在 ‘FoodItem’ 组件中为 ‘foodDesc’ 属性创建一个默认值,然后为大米创建这样一个项目,而无需定义 ‘foodDesc’ 属性:

示例
App.vue:

<template>
  <h1>Food</h1>
  <p>My favorite food has a diploma image attached to it.</p>
  <div id="wrapper">
    <food-item
      food-name="Apples"
      food-desc="Apples are a type of fruit that grow on trees."
      v-bind:is-favorite="true"/>
    <food-item
      food-name="Pizza"
      food-desc="Pizza has a bread base with tomato sauce, cheese, and toppings on top."
      v-bind:is-favorite="false"/>
    <food-item
      food-name="Rice"
      food-desc="Rice is a type of grain that people like to eat." 
      v-bind:is-favorite="false"/>
  </div>
</template>

FoodItem.vue:

<script>
  export default {
    props: {
      foodName: {
        type: String,
        required: true
      },
      foodDesc: {
        type: String,
        required: false,
        default: 'This is the default description.'
      },
      isFavorite: {
        type: Boolean,
        required: false,
        default: false
      }
    }
  }
</script>

Props 验证函数

我们还可以定义一个验证函数来决定 prop 值是否有效。

这样的验证函数必须返回 true 或 false。当验证器返回 false 时,表示 prop 值无效。当我们在开发人员模式下运行页面时,无效的 prop 值会在浏览器控制台中生成警告,警告是一个有用的提示,可确保组件按预期使用。

假设我们希望食物描述具有一定的长度,介于 20 到 50 个字符之间。我们可以添加一个验证器函数来确保提供的食物描述具有有效长度。

FoodItem.vue:

<script>
  export default {
    props: {
      foodName: {
        type: String,
        required: true
      },
      foodDesc: {
        type: String,
        required: false,
        default: 'This is the default description.',
        validator: function(value) {
          if( 20<value.length && value.length<50 ) {
            return true;
          }
          else {
            return false;
          }
        }
      },
      isFavorite: {
        type: Boolean,
        required: false,
        default: false
      }
    }
  }
</script>

注意:如果你将上面的验证器代码添加到本地项目中,你将在开发模式下收到警告,因为披萨的食物描述是 65 个字符,比验证器函数允许的长度长 15 个字符。
在这里插入图片描述

修改 Props

当在括号中创建组件时元素中我们不允许更改子元素中收到的 prop 的值。因此,在 FoodItem.vue 中,我们无法更改从 App.vue 获得的 ‘isFavorite’ prop 的值。该 prop 从父级(在我们的例子中是 App.vue)是只读的。

但是,假设我们希望用户能够通过单击按钮来更改哪些食物被视为最爱。现在需要更改 ‘isFavorite’ prop,但我们无法做到这一点,因为它是只读的。

我们不允许更改 ‘isFavorite’。这将产生错误。

methods: {
  toggleFavorite() { 
    this.isFavorite = !this.isFavorite;
  }
}

为了解决这个问题,我们可以使用 prop 在 FoodItem.vue 中初始化一个新的数据值“foodIsFavorite”,如下所示:

data() {
return {
foodIsFavorite: this.isFavorite
}
}

现在我们可以添加一个方法,以便用户可以切换这个新的数据值:

methods: {
toggleFavorite() {
this.foodIsFavorite = !this.foodIsFavorite;
}
}

我们还必须为每个食物添加切换按钮,并将 <img> 标签中的 v-show 更改为依赖于新的数据属性“foodIsFavorite”。为了使我们的示例更简单,我们还将 props 声明精简为一个数组。

示例
FoodItem.vue:

<template>
<div>
<h2>
{{ foodName }}
<img src="/img_quality.svg" v-show="foodIsFavorite">
</h2>
<p>{{ foodDesc }></p>
<button v-on:click="toggleFavorite">收藏</button>
</div>
</template>

<script>
export default {
props: ['foodName','foodDesc','isFavorite'],
data() {
return {
foodIsFavorite: this.isFavorite
}
},
methods: {
toggleFavorite() {
this.foodIsFavorite = !this.foodIsFavorite;
}
}
};
</script>

<style>
img {
height: 1.5em;
float: right;
}
</style>

总结

本文介绍了Vue Props的使用,如有问题欢迎私信和评论

;