Vue.js入门课程7:计算属性
→ Vue.js入门课程8:组件
本课目的
本课的主要目的是创建我们的第一个组件,并探索将数据传递到组件的机制。
初始码
以下是我们将以
index.html标签<body>开头的文件代码:
<div id="app">
<div class="product">
<div class="product-image">
<img :src="image" />
</div>
<div class="product-info">
<h1>{{ title }}</h1>
<p v-if="inStock">In stock</p>
<p v-else>Out of Stock</p>
<p>Shipping: {{ shipping }}</p>
<ul>
<li v-for="detail in details">{{ detail }}</li>
</ul>
<div
class="color-box"
v-for="(variant, index) in variants"
:key="variant.variantId"
:style="{ backgroundColor: variant.variantColor }"
@mouseover="updateProduct(index)"
></div>
<button
v-on:click="addToCart"
:disabled="!inStock"
:class="{ disabledButton: !inStock }"
>
Add to cart
</button>
<div class="cart">
<p>Cart({{ cart }})</p>
</div>
</div>
</div>
</div>
这是代码
main.js:
var app = new Vue({
el: '#app',
data: {
product: 'Socks',
brand: 'Vue Mastery',
selectedVariant: 0,
details: ['80% cotton', '20% polyester', 'Gender-neutral'],
variants: [
{
variantId: 2234,
variantColor: 'green',
variantImage: './assets/vmSocks-green.jpg',
variantQuantity: 10
},
{
variantId: 2235,
variantColor: 'blue',
variantImage: './assets/vmSocks-blue.jpg',
variantQuantity: 0
}
],
cart: 0,
},
methods: {
addToCart() {
this.cart += 1;
},
updateProduct(index) {
this.selectedVariant = index;
console.log(index);
}
},
computed: {
title() {
return this.brand + ' ' + this.product;
},
image() {
return this.variants[this.selectedVariant].variantImage;
},
inStock(){
return this.variants[this.selectedVariant].variantQuantity;
}
}
})
任务
我们不需要Vue应用程序中的所有数据,方法,计算属性都位于根Vue实例中。随着时间的流逝,这将导致代码难以维护。取而代之的是,我们希望将代码分解为易于使用的模块,并使开发更加灵活。
问题的解决
让我们从获取现有代码并将其移至新组件开始。
这是
main.js组件在文件中的注册方式:
Vue.component('product', {})
第一个参数是我们选择的组件名称。第二个是一个选项对象,类似于我们在先前教程中用于实例化Vue的选项对象。
在Vue实例中,我们使用了一个属性
el来组织其与DOM元素的绑定。对于组件,使用属性template定义组件的HTML代码。
让我们用选项描述对象中的组件模板:
Vue.component('product', {
template: `
<div class="product">
… // HTML-, product
</div>
`
})
在Vue中有几种创建模板的方法。现在,我们使用模板文字,其内容包含在反引号中。
如果事实证明模板代码不会放在单个根元素(例如
<div>具有class的元素)中product,则会导致以下错误消息:
Component template should contain exactly one root element
换句话说,组件模板只能返回一个元素。
例如,以下模板格式良好,因为它仅由一个元素表示:
Vue.component('product', {
template: `<h1>I'm a single element!</h1>`
})
但是,如果模板包含多个同级,则它将不起作用。这是一个错误模式的示例:
Vue.component('product', {
template: `
<h1>I'm a single element!</h1>
<h2>Not anymore</h2>
`
})
结果,事实证明,如果模板应包含许多元素,例如,
<div>类中包含的一组元素product,则这些元素应放置在外部容器元素中。结果,模板将仅具有一个根元素。
现在,模板包含了曾经在file中的HTML代码
index.html,我们可以将数据,方法,计算出的属性添加到以前在根Vue实例中存在的组件:
Vue.component('product', {
template: `
<div class="product">
…
</div>
`,
data() {
return {
//
}
},
methods: {
//
},
computed: {
//
}
})
如您所见,该组件的结构与我们之前使用的Vue实例的结构几乎完全相同。您是否注意到
data这现在不是属性,而是带有选项的对象的方法?为什么会这样呢?
关键是,通常使用计划重用来创建组件。如果我们有很多组件
product,则需要确保每个组件都有自己的实体实例data。由于data现在它是一个返回带有数据对象的函数,因此可以保证每个组件都可以接收自己的数据集。如果实体data不是函数,则每个组件product,无论在何处使用此类组件,都将包含相同的数据。这与可重用组件的想法背道而驰。
现在,我们已经将与产品相关的代码移动到本机组件中
product,用于描述根Vue实例的代码如下所示:
var app = new Vue({
el: '#app'
})
现在我们只需要将该组件
product放置在文件代码中即可index.html。它看起来像这样:
<div id="app">
<product></product>
</div>
如果您现在重新加载应用程序页面,它将返回其先前的形式。

应用程序页面
如果现在查看Vue开发人员工具,您会注意到其中存在一个Root实体和一个Product组件。

使用Vue开发人员工具分析应用程序
现在,仅为了演示组件的可重用性,让我们在代码中添加
index.html更多的组件product。实际上,这就是组件重用的组织方式。该代码index.html将如下所示:
<div id="app">
<product></product>
<product></product>
<product></product>
</div>
并且页面将显示产品卡的三份副本。

一页上显示几个产品卡
请注意,将来我们将使用一个组件
product,因此代码index.html如下所示:
<div id="app">
<product></product>
</div>
任务
应用程序通常需要组件来接受来自父实体的数据,输入参数。在这种情况下,组件的父代
product是根Vue实例本身。
让根Vue实例具有一些数据的描述。此数据指示用户是否是高级帐户持有人。描述Vue实例的代码可能如下所示:
var app = new Vue({
el: '#app',
data: {
premium: true
}
})
让我们决定高级用户有权免费送货。
这意味着我们希望组件
product根据写入premiumVue实例实例根属性的内容输出不同的运输成本信息。
如何将存储在
premium根Vue实例属性中的数据发送到作为组件的子级product?
问题的解决
在Vue中,要将数据从父实体传输到子实体,将使用对象属性以及
props组件描述的选项。这是一个带有组件输入参数描述的对象,其值应基于从父实体接收的数据来设置。
让我们从描述组件期望接收哪种输入参数开始
product。为此,将相应的属性添加到对象,并在创建对象时使用以下选项:
Vue.component('product', {
props: {
premium: {
type: Boolean,
required: true
}
},
// , ,
})
请注意,这使用了Vue的内置功能来验证传递给组件的参数。即,通过设置为,我们指示输入参数的类型
premium是Boolean什么以及该参数需要什么。
接下来,让我们对显示传递给对象的参数的模板进行更改。通过在页面上显示属性值,我们将确保所研究的机制正常运行。requiredtrue
premium
<p>User is premium: {{ premium }}</p>
到目前为止,一切都很好。该组件
product知道它将接收其操作所需的type参数Boolean。我们已经准备好显示相关数据的地方。
但是我们还没有将参数传递给
premium组件。您可以使用类似于“行”的自定义属性来执行此操作,该属性导致可以通过其传输输入参数(尤其是)的组件premium。
让我们修改中的代码
index.html:
<div id="app">
<product :premium="premium"></product>
</div>
让我们刷新页面。

输出传递到组件的数据
现在将输入参数传递到组件。让我们谈论一下我们刚刚做了什么。
我们向组件传递一个输入参数,即称为的“自定义属性”
premium。我们使用冒号构造将此自定义属性绑定到premium存储在Vue实例数据中的属性。
现在,根Vue实例可以传递给
premium子组件product。由于属性绑定到premiumVue实例数据中的属性,因此当前值premium将始终传递到componentproduct。
上面的数字,即题词
User is premium: true,证明一切都正确完成。
现在,我们已经验证了我们正在研究的数据传输机制正在按预期工作。如果您查看Vue开发人员工具,事实证明该组件
Product现在具有一个premium存储值的输入参数true。

组件的输入参数
现在,有关用户是否有高级帐户的数据进入了组件,让我们使用此数据在页面上显示运输成本信息。不要忘记,如果将参数
premium设置为valuetrue,则用户有权免费送货。让我们创建一个新的计算属性shipping并在其中使用参数premium:
shipping() {
if (this.premium) {
return "Free";
} else {
return 2.99
}
}
如果
this.premium存储在参数中true,则计算所得的属性shipping将返回Free。否则它将返回2.99。
让我们从组件模板中删除参数值输出代码
premium。现在<p>Shipping: {{ shipping }}</p>,我们今天开始使用的代码中存在的元素将能够显示有关运输成本的信息。

由于向用户发送了将输入参数设置为值的事实,因此高级用户可以在页面上看到免费的交货
文本。 精彩!现在,我们已经了解了如何将数据从父实体转移到子实体,并能够使用组件中的数据来管理货运成本。 顺便说一句,值得注意的是,您不应在子组件中更改其输入参数。
Shipping: Freepremiumtrue
作坊
创建一个新组件
product-details,该组件应使用输入参数details并负责呈现先前使用以下代码形成的产品卡的该部分:
<ul>
<li v-for="detail in details">{{ detail }}</li>
</ul>
这是您可以用来解决此问题的模板。
这是解决问题的方法。
结果
今天是您对Vue组件的首次介绍。这是您学到的东西:
- 组件是表示为自定义元素的代码块。
- 通过将组件分解为可重用的组件,组件使您的应用程序更易于管理。它们包含对视觉组件和应用程序相应部分功能的描述。
- 组件数据由
data()带有选项的对象的方法表示。 - 输入参数(
props)用于将数据从父实体传递到子实体。 - 我们可以描述组件采用的输入参数的要求。
- .
- .
- Vue .
您正在使用Vue开发人员工具吗?
→ Vue.js初学者课程1:实例Vue
→ Vue.js初学者,课程2:绑定属性
→ Vue.js初学者课程3:条件渲染
→ Vue.js初学者课程4:列表渲染
→ Vue .js初学者课程5:事件处理
→ Vue.js初学者课程6:绑定类和样式
→ Vue.js初学者课程7:计算的属性
→ Vue.js初学者课程8:组件
