→ 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:组件
→ Vue。初学者第9课js:自定义事件
本课目的
我们希望组件
product能够通知父实体Vue根实例已发生事件。在这种情况下,它product必须与事件发生的通知一起发送一些数据。
初始码
现在,示例
index.html项目文件包含以下代码:
<div id="app">
<product :premium="premium"></product>
</div>
这是文件的内容
main.js:
Vue.component('product', {
props: {
premium: {
type: Boolean,
required: true
}
},
template: `
<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>
`,
data() {
return {
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;
},
shipping() {
if (this.premium) {
return "Free";
} else {
return 2.99
}
}
}
})
var app = new Vue({
el: '#app',
data: {
premium: true
}
})
任务
现在,它
product作为一个独立的组件提供,与购物车相关的代码已包含在product其中就没有意义了。如果每个产品都有自己的篮子来监视状态,那么我们的应用程序将变得一团糟。相反,我们希望购物车存在于Vue实例的根目录下。我们还需要该组件来product通知根Vue实例有关将项目添加到购物车,即有关单击按钮的信息Add to cart。
决断
让我们将与购物车相关的数据移回Vue根实例:
var app = new Vue({
el: '#app',
data: {
premium: true,
cart: 0
}
})
接下来,让我们将购物车模板移回
index.html,将其代码转换为以下形式:
<div id="app">
<div class="cart">
<p>Cart({{ cart }})</p>
</div>
<product :premium="premium"></product>
</div>
现在,如果您在浏览器中打开应用程序页面并单击按钮
Add to cart,则不会发生任何预期的事情。

单击“添加到购物车”按钮尚无任何结果,
单击此按钮应该怎么办?我们需要单击它时,根Vue实例将收到一条通知,该通知将调用使购物车保持最新状态的方法,即更新存储在中的值
cart。
为了实现这一点,我们首先重写
addToCart组件方法代码product。
现在看起来像这样:
addToCart() {
this.cart += 1;
},
让我们把它变成这种形式:
addToCart() {
this.$emit('add-to-cart');
},
这是什么意思呢?
就是这样。调用该方法时
addToCart,将生成一个自定义的命名事件add-to-cart。换句话说,当Add to cart单击按钮时,将调用一个方法,该方法生成一个指示按钮刚刚被按下的事件(即,由按钮单击触发的事件刚刚发生)。
但是现在,应用程序中没有任何东西正在等待此事件,而不是在监听它。让我们将事件监听器添加到
index.html:
<product :premium="premium" @add-to-cart="updateCart"></product>
在这里,我们以与使用构造
@add-to-card相同的方式使用视图构造:premium。但是,如果这:premium是可以通过其将数据从父级传输到子级组件的“管道”,则@add-to-cart可以将其与父级组件的“无线电接收器”进行比较,后者从子级组件接收已按下按钮的信息Add to cart。由于“ radio”位于<product>嵌套的标记中<div id="app">,因此,这意味着有关单击的信息到达时,Add to cart将调用updateCart位于Vue根实例中的方法。
代码
@add-to-cart=«updateCart»转换为普通语言,如下所示:“当您听到发生了事件时add-to-cart,请调用方法updateCart。”
该方法现在将在实例化Vue时在使用的options对象中声明,您可能已经在以下地方看到过:
methods: {
updateCart() {
this.cart += 1;
}
}
实际上,这与早先在中使用的方法完全相同
product。但是现在它在Vue根实例中,并在单击按钮时调用Add to cart。

按钮再次起作用
当您单击组件中的按钮时,
product将调用addToCart一个生成事件的方法。收听广播的根Vue实例获悉该事件已发生,并调用一种方法updateCart来递增存储在中的数字cart。
我们已经实现了我们的目标,但是在实际应用中,知道已经发生了某个事件,已经将某种产品添加到购物车并不会带来太大的收益。实际上,您至少需要知道已将哪种产品添加到购物车。这意味着,如果是由于按下按钮而产生的,则还需要传输一些数据。
事件中传递的数据可以描述为组件
$emit方法代码中传递的第二个参数addToCartproduct:
this.$emit('add-to-cart', this.variants[this.selectedVariant].variantId);
现在,事件传递了
variantId用户想要添加到购物车的产品的标识符()。这意味着我们不仅可以增加购物车中的物品数量,还可以走得更远,并在购物车中存储有关添加到购物车中的物品的更多详细信息。为此,我们首先通过将一个空数组写入来将篮子转换为数组cart:
cart: []
接下来,让我们重写方法
updateCart。首先-它现在将接受id-事件中现在传递的相同产品标识符,其次-现在将其接收到的内容放入数组中:
methods: {
updateCart(id) {
this.cart.push(id);
}
}
单击按钮后,产品标识符将添加到阵列中。阵列显示在页面上。

具有产品ID的阵列显示在页面上。
我们不需要在页面上显示整个阵列。我们将对添加到购物车(即数组)的产品数量的输出感到满意
cart。因此,我们可以重写标记代码<p>,显示有关添加到购物车的产品数量的信息,如下所示:
<p>Cart({{ cart.length }})</p>

该页面显示有关添加到购物车中的商品数量的信息,
现在我们只需在页面上显示数组的长度,换句话说就是购物车中的商品数量。从外部看,购物车外观与以前相同,但现在,我们不再只是增加数字属性的值
cart,而是在数组中存储cart有关将哪些商品添加到购物车的信息。
作坊
在项目中添加一个按钮,以从阵列中删除
cart之前添加的产品。通过单击此按钮,应生成一个事件,其中包含有关要从购物车中删除的物品的标识符的信息。
结果
这是您今天学到的:
- 组件可以使用构造通知父实体发生了某些事情
$emit。 - 父组件可以使用使用伪指令
v-on(或其速记版本@)定义的事件处理程序来组织对子组件生成的事件的响应。如果发生事件,则可以在父组件中调用事件处理程序。 - , , .
如果您正在学习本课程并上了本课,请告诉我们您的目的,通过掌握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:组件
→ Vue。初学者第9课js:自定义事件
