1.基本使用
本篇的主要内容有:
- vue 的安装
- 生命周期钩子
- 模板语法
- 常用指令
- 数据侦听器
- Class、Style 绑定
- 条件渲染
- 列表渲染
- 表单输入绑定
- 组件
vue 的安装
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
官方文档:链接地址
最简单的安装方式是创建一个 .html 文件,然后通过如下方式引入 Vue:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
当然也可以使用 Node.js 的构建工具安装 vue-cli。这种方式主要针对专业前端开发,这里便不再赘述。
为了使 idea 有更好的代码提示效果,建议安装 vue.js 插件。
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统,以操作数据的方式操作 DOM 节点,Vue 不建议使用者直接操作节点内容,目前大部分开发平台都倡导以修改数据的方式操作节点,操作节点被认为是一种落后的技术。
<div id="app">
{{ message }}
</div>
渲染代码:
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
如此便成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。
通过浏览器控制台输入 app.message="测试" 可以修改vue的数据,会发现一旦数据变化了,vue 管理的页面也发生变化。
为了让用户和你的应用进行交互,我们可以用 v-on 指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法:
<div id="app-5">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">反转消息</button>
</div>
渲染代码:
var app5 = new Vue({
el: '#app-5',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
注意在 reverseMessage 方法中,更新了应用的状态,但没有触碰 DOM。所有的 DOM 操作都由 Vue 来处理,编写的代码只需要关注逻辑层面即可。
练习:
1.在页面中编写一个点击次数统计的功能,点击一次值增加一。
参考代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>练习</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app" style="text-align: center">
<h1>{{count}}</h1>
<input type="button" value="增加" v-on:click="add()">
</div>
<script>
new Vue({
el: "#app",
data: {
count: 0
},
methods: {
add() {
this.count++;
}
}
})
</script>
</body>
</html>
生命周期钩子
每个 Vue 实例在被创建时都要经过一系列的初始化过程。例如:需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
比如 created 钩子可以用来在一个实例被创建之后执行代码:
new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})
// => "a is: 1"
也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mounted、updated 和 destroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。
下图展示了实例的生命周期。销毁的事件需要在 vue 脚手架中才能使用。
练习:
1.在上一个练习中使用 created 生命周期函数完成数据从缓存中读取。
参考代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>练习</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app" style="text-align: center">
<h1>{{count}}</h1>
<input type="button" value="增加" v-on:click="add()">
</div>
<script>
new Vue({
el: "#app",
data: {
count: 0
},
methods: {
add() {
this.count++;
sessionStorage.count = this.count;
}
},
created() {
if (sessionStorage.count) {
this.count = sessionStorage.count
}
}
})
</script>
</body>
</html>
模板语法
1.插值
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:
<span>Message: {{ msg }}</span>
Mustache 标签将会被替代为对应数据对象上 msg 属性的值。无论何时,绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新。
通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:
<span v-once>这个将不会改变: {{ msg }}</span>
2.原始 HTML
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令:
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
这个 span 的内容将会被替换成为属性值 rawHtml,直接作为 HTML——会忽略解析属性值中的数据绑定。
3.Attribute
Mustache 语法不能作用在 HTML attribute 上,遇到这种情况应该使用 v-bind 指令:
<div v-bind:id="dynamicId"></div>
对于布尔 attribute (它们只要存在就意味着值为 true),v-bind 工作起来略有不同,在这个例子中:
<button v-bind:disabled="isButtonDisabled">Button</button>
如果 isButtonDisabled 的值是 null、undefined 或 false,则 disabled attribute 甚至不会被包含在渲染出来的 <button> 元素中。
4.使用 JavaScript 表达式
迄今为止,在我们的模板中,我们一直都只绑定简单的属性键值。但实际上,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
练习:
1.制作一个点击一次在页面增加一张照片的按钮。每次点击都将插入一张相同的照片到页面。
参考代码:
<div id="app" style="text-align: center">
<p v-html="content"></p>
<input type="button" value="增加" v-on:click="add()">
</div>
<script>
new Vue({
el: "#app",
data: {
content: ""
},
methods: {
add() {
this.content += "<img src=http://58.42.239.163:8888/static/img/noteBook/PAZrEvLF.jpg width='100'>";
}
}
})
</script>
常用指令
指令(Directives)是带有 v- 前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式 (v-for 是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。回顾前面看到的例子:
<p v-if="seen">现在你看到我了</p>
这里,v-if 指令将根据表达式 seen 的值的真假来插入/移除 <p> 元素。
一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind 指令可以用于响应式地更新 HTML attribute:
<a v-bind:href="url">...</a>
在这里 href 是参数,告知 v-bind 指令将该元素的 href 与 attribute 与表达式 url 的值绑定。
另一个例子是 v-on 指令,它用于监听 DOM 事件:
<a v-on:click="doSomething">...</a>
在这里参数是监听的事件名。我们也会更详细地讨论事件处理。
从 2.6.0 开始,可以用方括号括起来的 JavaScript 表达式作为一个指令的参数,但是变量名会被 vue 转为小写,所以建议使用下划线命名。
<a v-bind:[attribute_name]="url"> ... </a>
这里的 attribute_name 会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,Vue 实例有一个 data 属性 attribute_name,其值为 "href",那么这个绑定将等价于 v-bind:href。
同样地,你可以使用动态参数为一个动态的事件名绑定处理函数:
<a v-on:[event_name]="doSomething"> ... </a>
在这个示例中,当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus。
指令缩写
1.v-bind 缩写
<!-- 完整语法 -->
<a v-bind:href="url">...</a><!-- 缩写 -->
<a :href="url">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>
2.v-on 缩写
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a><!-- 缩写 -->
<a @click="doSomething">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>
它们看起来可能与普通的 HTML 略有不同,但 : 与 @ 对于 attribute 名来说都是合法字符,在所有支持 Vue 的浏览器都能被正确地解析。而且,它们不会出现在最终渲染的标记中。缩写语法是完全可选的。
练习:
1.在页面上有一张照片和一个按钮,按钮用于控制照片的显示和隐藏,点击后按钮的文字也变成相应的文字“隐藏”或“显示”。
参考代码:
<div id="app" style="text-align: center">
<p><img v-show="show" src=http://58.42.239.163:8888/static/img/noteBook/PAZrEvLF.jpg width='100'></p>
<button v-on:click="add()">{{show?'隐藏':'显示'}}</button>
</div>
<script>
new Vue({
el: "#app",
data: {
show: true
},
methods: {
add() {
this.show = !this.show;
}
}
})
</script>
数据侦听器
当需要监听数据变化时就需要侦听器。Vue 通过 watch 选项提供了一套更通用的方法,来响应数据的变化。
<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
渲染代码:
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 question
发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
}
})
练习:
1.做一个输入框文本长度校验,当长度大于 5 后文字变成红色,同时 alert 弹窗警告。
参考代码:
<div id="app" style="text-align: center">
<p><input v-model="input" v-bind:style="inputStyle"></p>
</div>
<script>
new Vue({
el: "#app",
data: {
input: "",
inputStyle: {
color: "black"
}
},
watch: {
input(newStr, oldStr) {
if (newStr.length > 5) {
alert("超出范围");
this.inputStyle.color = "red"
}
}
}
})
</script>
Class、Style 绑定
我们可以传给 v-bind:class 一个对象,以动态地切换 class:
<div v-bind:class="{ active: isActive }"></div>
上面的语法表示 active 这个 class 存在与否将取决于数据 property isActive 的 truthiness。
你可以在对象中传入更多字段来动态切换多个 class。此外,v-bind:class 指令也可以与普通的 class attribute 共存。当有如下模板:
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
和如下 data:
data: {
isActive: true,
hasError: false
}
结果渲染为:
<div class="static active"></div>
当 isActive 或者 hasError 变化时,class 列表将相应地更新。例如,如果 hasError 的值为 true,class 列表将变为 "static active text-danger"。
绑定的数据对象不必内联定义在模板里:
<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}
v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
渲染模板数据:
data: {
activeColor: 'red',
fontSize: 30
}
直接绑定到一个样式对象通常更好,这会让模板更清晰:
<div v-bind:style="styleObject"></div>
渲染模板数据:
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:
<div v-bind:style="[baseStyles, overridingStyles]"></div>
练习:
1.按照如下设计图完成练习,点击对应的按钮完成如下的星级评分模块。
参考代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>练习</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
* {
margin: 0;
padding: 0
}.stars { margin: 10px; padding: 10px; border: 1px saddlebrown solid; } .stars span { float: left; height: 30px; line-height: 30px; } .stars i { width: 30px; height: 30px; line-height: 30px; float: left; margin-right: 30px; background: #ccc; color: #fff; text-align: center; cursor: default; font-style: normal; } .stars .on { color: #a71417; } </style>
</head>
<body>
<div id="app">
<div class="stars">
<span>商品评价:</span>
<i v-bind:class="stars1>=1?'on':''" v-on:click="stars1=1">★</i>
<i v-bind:class="stars1>=2?'on':''" v-on:click="stars1=2">★</i>
<i v-bind:class="stars1>=3?'on':''" v-on:click="stars1=3">★</i>
<i v-bind:class="stars1>=4?'on':''" v-on:click="stars1=4">★</i>
<i v-bind:class="stars1>=5?'on':''" v-on:click="stars1=5">★</i>
<input type="text" v-model="stars1"/>
</div>
</div><script>
new Vue({
el: "#app",
data: {
stars1: 0,}, methods: {} })
</script>
</body>
</html>
条件渲染
1.v-if 用于条件限制某节点的渲染与否。
<h1 v-if="awesome">Vue is awesome!</h1>
也可以用 v-else 添加一个“else 块”:
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no </h1>
vue 2.1.0 新增 v-else-if,顾名思义,充当 v-if 的“else-if 块”,可以连续使用:
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
2.v-show 用于根据条件展示元素的指令。用法与 v-if 大致一样。
<h1 v-show="ok">Hello!</h1>
不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display。
练习:
1.分别使用 v-show 与 v-if 完成如下操作,点击对应的盒子使其隐藏。
参考代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>练习</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
#app {
width: 80%;
}
.box {
width: 100px;
height: 100px;
background: yellow;
margin: 10px;
float: left;
text-align: center;
line-height: 100px;
font-size: 30px;
}
</style>
</head>
<body>
<div id="app">
<div v-show="box1" v-on:click="box1=false">1</div>
<div v-show="box2" v-on:click="box2=false">2</div>
<div v-show="box3" v-on:click="box3=false">3</div>
<div v-show="box4" v-on:click="box4=false">4</div>
</div>
<script>
new Vue({
el: "#app",
data: {
box1: true,
box2: true,
box3: true,
box4: true
},
})
</script>
</body>
</html>
参考2:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
#app {
width: 80%;
}
.box {
width: 100px;
height: 100px;
background: yellow;
margin: 10px;
float: left;
text-align: center;
line-height: 100px;
font-size: 30px;
}
</style>
</head>
<body>
<div id="app">
<h1 class="box" v-for="d in 4" @click="show(d)" v-if="!redIndex.includes(d)">{{d}}</h1>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
redIndex:[],
},
methods: {
show(data) {
this.redIndex.push(data);
}
}
});
</script>
</body>
</html>
列表渲染
我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
渲染代码:
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
在 v-for 还支持一个可选的第二个参数,即当前项的索引。
<ul id="example-2">
<li v-for="(item, index) in items">
- {{ index }} - {{ item.message }}
</li>
</ul>
你也可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:
<div v-for="item of items"></div>
在 v-for 里使用对象,也可以用 v-for 来遍历一个对象的属性。
<ul id="v-for-object">
<li v-for="value in object">
{{ value }}
</li>
</ul>
渲染代码:
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
你也可以提供第二个的参数为 property 名称 (也就是键名):
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
还可以用第三个参数作为索引:
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>
表单输入绑定
你可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text 和 textarea 元素使用 value 属性和 input 事件
- checkbox 和 radio 使用 checked 属性和 change 事件
- select 字段将 value 作为 prop 并将 change 作为事件
1.单行文本
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
2.多行文本
<p>Message is: {{ message }}</p>
<textarea v-model="message" placeholder="add multiple lines"></textarea>
3.复选框
单个复选框,绑定到布尔值:
<input type="checkbox" v-model="checked">
<p>选中:{{ checked }}</p>
多个复选框,绑定到同一个数组:
<div id='example-3'>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
4.单选按钮绑定到普通字符串
<div id="example-4">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
</div>
5.选择框
单选时:
<div id="example-5">
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
多选时 (绑定到一个数组):
<div id="example-6">
<select v-model="selected" multiple>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>Selected: {{ selected }}</span>
</div>
用 v-for 渲染的动态选项:
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
渲染数据:
new Vue({
el: '...',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
组件
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
Vue.component(tagName, options)
tagName 为组件名,options 为配置选项。
注册后,我们可以使用以下方式来调用组件:
<tagName></tagName>
组件虽然在单独使用 vue.js 时使用不多,但在 vue 单页面应用即 vue 脚手架中使用颇多。
<div id="app">
<runoob></runoob>
</div>
<script>
// 注册
Vue.component('runoob', {
template: '<h1>自定义组件!</h1>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
Prop
prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
<div id="app">
<child message="hello!"></child>
</div>
<script>
// 注册
Vue.component('child', {
// 声明 props
props: ['message'],
// 同样也可以在 vm 实例中像 "this.message" 这样使用
template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件。
<div id="app">
<div>
<input v-model="parentMsg">
<br>
<child v-bind:message="parentMsg"></child>
</div>
</div>
<script>
Vue.component('child', {
props: {'message': {type: String, default: ""}},
template: '<span>{{ message }}</span>'
})
new Vue({
el: '#app',
data: {
parentMsg: '父组件内容'
}
})
</script>
注意:
1.prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
2.props 里面的键必须是中划线命名,不能使用驼峰命名。
当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。 type 可以是下面原生构造器: String Number Boolean Array Object Date Function Symbol type 也可以是一个自定义构造器,使用 instanceof 检测。
子组件向父组件传值,子组件向父组件传值是通过 emit 方法的方式。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h1>{{formSon}}</h1>
<com2 @func="show"></com2>
<com2 @func="show"></com2>
</div><template id="tmpl">
<div>
<p>这是子组件</p>
<input type="button" :value="son.age" @click="sonClick()">
</div>
</template><script>
Vue.component('com2', { template: '#tmpl', data() { return { son: { name: '小头儿子', age: 6 } } }, methods: { sonClick() { this.son.age++; this.$emit('func', this.son) } } }); let vm = new Vue({ el: '#app', data: { formSon: {} }, methods: { show(data) { this.formSon = data } } });
</script>
</body>
</html>
练习:
1.如下商品列表,灰色部分为子组件内容,在子组件中点击按钮可以增加购买数量,每次子组件点击都修改父组件的总价。
参考代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h1>商品列表</h1>
<h3>总价:{{allPrice}}</h3>
<p v-for="item in goods">
<span>{{item.name}}</span>
<button-counter :price="item.price" @increment="increment"></button-counter>
</p>
</div><script>
Vue.component('button-counter', { template: ` <div style="background-color: #eee"> <p>价格:{{price}},花费:{{price * count}} <button v-on:click="incrementHandler">数量:{{ count }}</button> </p> </div>`, data: function () { return { count: 0 } }, methods: { incrementHandler: function () { this.count += 1 this.$emit('increment', this.price) } }, props: { price: { type: Number, default: 1 } } }) let app = new Vue({ el: '#app', data: { allPrice: 0, goods: [ {name: "商品1", price: 1}, {name: "商品2", price: 2}, {name: "商品3", price: 3}, ] }, methods: { increment(data) { this.allPrice += data; } } })
</script>
</body>
</html>