学习前提在学习Vue之前最好是已了解关于 HTML、CSS 和 JavaScript 的知识。如果你刚开始学习前端开发,建议先把基础知识学完后在继续学习。
Vue简介
什么是 Vue?
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的 渐进式的js框架,发布于 2014 年 2 月。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库(如: vue-router , vue-resource , vuex 等)或既有项目整合。
MVVM 模式的实现者——双向数据绑定模式
模型—视图—视图模型(Model-View-ViewModel - MVVM
),本质上是MVC(模型—视图—控制器)的改进版,其最重要的特性即是数据绑定(data binding),此外还包括依赖注入、路由配置、数据模板等一些特性。
- Model:模型层,在这里表示 JavaScript 对象
- View:视图层,在这里表示 DOM(HTML 操作的元素)
- ViewModel:连接视图和数据的中间件,Vue.js 就是 MVVM 中的 ViewModel 层的实现者
在 MVVM 架构中,是不允许 数据 和 视图 直接通信的,只能通过 ViewModel
来通信,而 ViewModel 就是定义了一个 Observer
观察者
- ViewModel 能够观察到数据的变化,并对视图对应的内容进行更新
- ViewModel 能够监听到视图的变化,并能够通知数据发生改变
至此,我们就明白了,Vue.js 就是一个 MVVM 的实现者,他的核心就是实现了 DOM 监听 与 数据绑定
:::info VM 的一个实现原理
- view model中内置了一个观察者,这个观察者观察两个维度。
- 观察视图的变化:当视图变了 ,就通知数据进行变化
- 观察数据的变化:当数据变了 ,就通知视图进行变化。
- MVVM通过VM实现了双向数据绑定。
:::
其它 MVVM 实现者
- AngularJS
- ReactJS
- 微信小程序
为什么要使用 Vue.js
- 轻量级,体积小是一个重要指标。Vue.js 压缩后有只有 20多kb (Angular 压缩后 56kb+,React 压缩后44kb+)
- 移动优先。更适合移动端,比如移动端的 Touch 事件
- 易上手,学习曲线平稳,文档齐全
- 吸取了 Angular( 模块化 )和 React( 虚拟 DOM )的长处,并拥有自己独特的功能,如: 计算属性
- 开源,社区活跃度高
Vue.js 的两大核心要素
ject.defineProperty是Es5中无
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用Object.defineProperty
把这些属性全部转为 getter/setter 。
Object.defineProperty是ES5中一个无法shim的特性,这也就是为什么Vue不支持IE8以及更低版本浏览器。
这些 getter/setter
对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。这里需要注意的问题是浏览器控制台在打印数据对象时 getter/setter 的格式化并不同,所以你可能需要安装 vuedevtools 来获取更加友好的检查接口。
每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
组件化
- 页面上每个独立的可交互的区域视为一个组件
- 每个组件对应一个工程目录,组件所需的各种资源在这个目录下就近维护
- 页面不过是组件的容器,组件可以嵌套自由组合(复用)形成完整的页面
什么是CDN
CDN的全称是Content Delivery Network,即 内容分发网络 。CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。
CDN 简单来说就是内容分发网络,这是一种加速策略,能够从离自己最近的服务器快速的获得外部的资源。
项目里引入Vue的方式
- 使用一个框架,我们第一步要做什么呢?安装下载它
- 方式一:直接CDN引入
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
- 方式二:下载和引入
// 开发环境 https://vuejs.org/js/vue.js
// 生产环境 https://vuejs.org/js/vue.min.js
- 方式三:NPM(包管理器)安装后续通过Vue-Cli4(vue官方的脚手架)方式引入,实际开发中我们使用该方式
Hello Vue案例
- 在页面引入vue的js文件即可
- 可以到这里去选择自己需要的版本CDN : https://www.bootcdn.cn/vue/
//官网上的cdn
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
- 在页面中绑定vue元素
<!--创建一个div,id是app-->
<div id="app">
<p>大家好,我是{{name}},我今年{{age}}岁了</p>
</div>
创建vue对象,设计对象的内容
<script type="text/javascript">
new Vue({
el:"#app", //Vue对象绑定在哪一个Div上
data:{
name:"张三",
age:19
} //提供数据的里面存放键值对
})
</script>
- 在页面的元素中使用插值表达式来使用vue对象中的内容
<div id="app">
{{ title }}
</div>
- 效果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<p>大家好,我是{{name}},我今年{{age}}岁了</p>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app", //Vue对象绑定在哪一个Div上
data:{
name:"张三",
age:19
} //提供数据的里面存放键值对
})
</script>
</html>
Vue基础语法
插值表达式
插值表达式的作用是在View中获得Model中的内容
- 语法:
{{vue的内容}}
- 作用:插值运算符可以对数据进行显示,也可以在插值运算符中进行表达式计算。
- 注意:差值表达式不能写在html的标签中,不能作为属性的值的部分
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<h2>Hello {{name}}</h2>
<h2>{{firstname}} {{lastname}}</h2>
<h2>{{count*2}}</h2>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
name:'Vue',
firstname:'张',
lastname:'三',
count:13
}
})
</script>
</html>
效果
除了上面的简单用法还可以使用下面的用法
<div id="app">
{{title}}
{{[1,2,3,4][2]}} <!--取值前面数组的第2个元素,小标从0开始-->
{{ {"name":"xiaoyu","age":20}.age }}
{{ sayHello()}}
</div>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
title:"hello world!"
} ,
methods:{
sayHello:function(){
return "hello vue";
}
}
})
</script>
双向数据绑定
双向数据绑定:是将标签的value值与vue实例中的data属性值进行绑定。 可以根据下面这个动图进行理解。输入框输入数据,会显示到 span 元素上
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-model="title" />
<p>{{title}}</p>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
title:"hello word"
}
})
</script>
</html>
练习:
v-model绑定select,实现默认选中项的效果。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<select v-model="mySelect">
<option value="java">Java从入门到精通</option>
<option value="python">python从入门到精通</option>
<option value="php">php从入门到精通</option>
<option value="mysql">mysql从删库到跑路</option>
</select>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
mySelect: 'java'
}
})
</script>
</html>
也可以使用JS进行实现
<body>
<div id="app">
<input type="text" id="input"/>
<span id="span"></span>
</div>
<script>
var inputObj = document.getElementById('input');
var spanObj = document.getElementById('span');
inputObj.oninput = function() {
spanObj.innerHTML = this.value;
}
</script>
</body>
事件绑定 v-on
v-on
绑定事件,如下案例:事件是input
,响应行为(方法)是changeTitle
。也就是说,当input
元素发生输入事件时,就会调用vue
里定义的changeTitle
方法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-on:input="changeTitle" />
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
title:"hello word"
},
methods:{
changeTitle:function(){
console.log("ceshi");//往日志里写
}
}
})
</script>
</html>
event.target.value
== 当前事件的对象(input元素)的value值 注意:此时的this指的是当前vue对象
所以:如果在method里要想使用当前vue 对象中的data里的内容,必须加上this.
changeTitle:function(event){
this.title = event.target.value;
}
事件绑定简化版:使用@替换v-on:
<input type="text" @input="changeTitle" />
属性绑定 v-bind
前面我们都是通过指令来将值插入到我们的标签内容中,但除了内容外,我们还需要动态绑定某些属性,比如:a标签中的href属性,img标签中的src属性;这个时候我们就可以使用v-bind指令,它的作用就是可以动态绑定属性。
html里的所有属性,都不能使用插值表达式。下面的这种做法是错误的,但可以使用绑定属性绑定来解决:
<a href="{{link}}">baidu</a>
new Vue({
el:"#app",
data:{
title:"hello world!",
link:"http://www.baidu.com"
},
...
我们知道差值表达式是不能写在html的标签的属性内的,那如果一定要用vue中的属性作为html标签的属性的内容,就可以通过v-bind进行属性绑定
<a v-bind:href="link">baidu</a>
<!--可以缩写成 冒号-->
<a :href="link">baidu</a>
v-bind绑定class
如果我们希望能动态切换class,选中字体颜色变红,初始状态字体为黑色;绑定class有两种方式:对象语法,数组语法。
- 对象语法
- 用法一:直接通过
{'',''}
绑定一个class
- 用法一:直接通过
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>.active {color: red;}</style>
</head>
<body>
<div id="app">
<h2 :class="{'active': isActive}">Hello Vue!</h2>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
isActive: true
}
})
</script>
</html>
- 用法二:同一个标签和普通的class类同时存在,并不冲突
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
.active {color: red;}
.line {text-decoration: underline;}
.title {font-size: 20px;}
</style>
</head>
<body>
<div id="app">
<h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello World</h2>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
isActive: true,
isLine: true,
}
})
</script>
</html>
- 如果过于复杂,可以放在一个methods或者computed中
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
.active {color: red;}
.line {text-decoration: underline;}
.title {font-size: 20px;}
</style>
</head>
<body>
<div id="app">
<h2 class="title" :class="classes()">Hello World</h2>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
isActive: true,
isLine: true
},
methods: {
classes() {
return {
'active': this.isActive,
'line': this.isLine
}
}
}
})
</script>
</html>
- 数组语法
- 用法一:通过[]来绑定一个类
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
.active {color: red;}
</style>
</head>
<body>
<div id="app">
<h2 :class="['active']">Hello Vue!</h2>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
}
})
</script>
</html>
- 用法二:同一个标签上和普通的类同时存在,并不冲突
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
.active {color: red;}
.line {text-decoration: underline;}
.title {font-size: 20px;}
</style>
</head>
<body>
<div id="app">
<h2 class="title" :class="['active', 'line']">Hello Vue!</h2>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
}
})
</script>
</html>
- 用法三:如果过于复杂,可以放在一个methods或者computed中
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
.active {color: red;}
.line {text-decoration: underline;}
.title {font-size: 20px;}
</style>
</head>
<body>
<div id="app">
<h2 class="title" :class="classes()">Hello Vue!</h2>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
},
methods: {
classes() {
return ['active', 'line']
}
}
})
</script>
</html>
v-bind绑定style
我们可以利用v-bind:style来绑定一个内嵌样式。
注意:
- 我们可以使用驼峰式语法:比如font-size —->
fontSize
- 短横线分隔
font-size
绑定class有两种方式:
- 对象语法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<div :style="{color: currentColor, fontSize: fontsize + 'px'}">
Hello Vue
</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
currentColor: 'blue',
fontsize: 30
}
})
</script>
</html>
- 数组语法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<div :style="[colorStyle, fontStyle]">
Hello Vue
</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
colorStyle: {color: 'blue'},
fontStyle: {'font-size': '20px'}
}
})
</script>
</html>
v-once指令
指明此元素的数据只出现一次,数据内容的修改不影响此元素
此时该标签中的差值表达式,只获取一次数据。之后数据的变化不影响此差值表达式的值。。
<p v-once>{{titile}}</p>
案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!-- <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>-->
</head>
<body>
<div id="app">
<input type="text" v-model="title" />
<p v-once>{{title}}</p>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
title:"hello word"
}
})
</script>
</html>
v-html 和 v-text
v-html:会将vue中的属性的值作为html的元素来使用,就好比是innerHTML
v-text:会将vue中的属性的值只作为纯文本来使用,纯文本输出内容
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="app">
<p v-html="myLink"></p>
<p v-text="myLink"></p>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
link:"https://www.baidu.com/",
myLink:'<a href="https://www.baidu.com/">百度</a>'
}
})
</script>
</html>
效果
分支语句:v-if、v-else-if、v-else
v-if、v-else-if、v-else。
这三个指令与JS中的条件判断if、else if、else类似。
v-if
可以根据表达式中的值渲染或者销毁元素和组件。满足条件才显示对应的元素
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<div v-if="score >= 90">优秀</div>
<div v-else-if="score >= 75">良好</div>
<div v-else-if="score >= 60">及格</div>
<div v-else>不及格</div>
<button @click="delScore">减分</button>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
score: 100
},
methods: {
delScore() {
this.score -= 10
}
}
})
</script>
</html>
v-show
v-show的用法与v-if类似,也是用于条件判断的。
二者的区别:
- v-if是完全不创建DOM元素,而v-show则是创建了DOM元素,仅仅是使用display:none隐藏了该元素。
- 当需要频繁的显示、隐藏一些内容时,使用v-show。当我们仅有一次切换,某些v-if场景根本不会显示出来的时候,用v-if。
循环语句 v-for
当我们有一组数据需要进行渲染时,我们就可以使用v-for完成。v-for类似于JS中的for循环。
格式:item in items
。后面的items代表着你需要遍历的数组,item则表示每一项的名称。
作用:遍历数组、对象
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<ul>
<!-- <li v-for="item in dataList">{{item}}</li> -->
<li v-for="(item, index) in dataList">{{index + ':' + item}}</li>
</ul>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
dataList: [
'Java从入门到精通',
'php从入门到精通',
'mysql从删库到跑路',
'Vue从单身到脱单'
]
}
})
</script>
</html>
如果我们需要在遍历的过程中,获取该元素所在数组中的索引值,应该怎么操作?
<li v-for="(item, index) in dataList">{{index + ':' + item}}</li>
改进版:for语句里,key建议加上,作为标识 index
是下标
<ul>
<!-- <li v-for="item in dataList">{{item}}</li> -->
<li v-for="(item, index) in dataList" :key = "index">{{index + ':' + item}}</li>
</ul>
表单输入绑定 v-model
表单控件在实际开发中是非常常见的,Vue中使用 v-model
指令来实现表单元素和数据的双向绑定。
你可以用
v-model
指令在表单<input>
、<textarea>
及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-model="title" />
<p>{{title}}</p>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
title:"hello word"
}
})
</script>
</html>
案例解析:
- 当我们在输入框内容时,因为input使用了v-model绑定了msg, 所以会实时将输入的内容传递给定义的属性msg,data里面的属性msg也就发生改变。
- 因为上面我们使用了Mustache语法,所以当属性msg发生改变的时候,DOM也会跟着改变。
- 所以,通过v-model实现了双向的数据绑定。
过滤器
有时候我们得到的数据并不直接符合我们的需求,这时候需要对其进行改变。如果每个数据都手动编写,将非常的麻烦,我们可以将有共同特点、共同需求的数据使用过滤器统一进行处理。
Filters属性与data
和methods
平级,用于定义过滤器。过滤器本质上是一个方法,接收一个参数。在页面中,使用插值运算符,语法:{{数据 | 过滤器名称}},不需要写参数,不需要写括号,过滤器默认会把前面的数据作为参数传递给方法。
过滤器的方法需要返回一个数据,返回的数据作为最终结果渲染到页面中。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<h2>{{count | filterEven}}</h2>
<h2>{{count2 | filterEven}}</h2>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
count: 10,
count2: 11
},
filters: {
filterEven(num) {
if (num % 2 === 0) {
return num
} else {
return '非法数字'
}
}
}
})
</script>
</html>
监听器
如果我们需要监听某个值的变化,当这个值变化是,进行一些操作,可以使用监听器。监听器的属性名称是watch,和data平级。监听器中的数据是方法,接收两个参数,分别为改变后的值和改变前的值。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-model="firstName">
<input type="text" v-model="lastName">
<h2>{{fullName}}</h2>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
firstName:'张',
lastName:'三',
fullName: ''
},
watch: {
firstName: function(newVal, oldVal) {
// 在vue中,操作data、method必须使用this
this.fullName = this.firstName + this.lastName
},
lastName(newVal, oldVal) {
this.fullName = this.firstName + this.lastName
}
}
})
</script>
</html>
计算属性:computed
1)计算属性的作用?
我们知道,在模板中可以直接通过插值语法显示一些data中的数据。但是某些情况下,我们可能需要对数据进行转化后再显示,或者需要将多个数据结合起来进行显示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
书籍总价值:{{totalPrice}}
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
books: [
{name: 'Vuejs入门', price: 99, count: 2},
{name: 'Vuejs底层', price: 96, count: 1},
{name: 'Vuejs大神', price: 20, count: 3},
]
},
computed: {
totalPrice() {
console.log("进入计算")
return this.books.reduce((prev, current) => {
prev += current.price * current.count
return prev
}, 0)
}
}
})
</script>
</html>
2)计算属性与方法的区别?
为什么会有这样的一个属性呢,用methods都可以实现我们的功能,为什么多了这样一个计算属性的东西呢?
因为计算属性会进行缓存,如果多次使用,计算属性只会调用一次。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<div>{{nameToWish}}</div>
<div>{{nameToWish}}</div>
<div>{{nameToWish}}</div>
<div>{{getnameToWish()}}</div>
<div>{{getnameToWish()}}</div>
<div>{{getnameToWish()}}</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
const vm = new Vue({
el: '#app',
data: {
name: 'lao chen',
wish: 'xiang bao fu'
},
computed: {
nameToWish() {
console.log('执行了nameToWish的计算属性')
return this.name + ' ' + this.wish
}
},
methods: {
getnameToWish() {
console.log('执行了getnameToWish的方法')
return this.name + ' ' + this.wish
}
}
})
</script>
</html>
说明
- methods :定义方法,调用方法使用 currentTime1() ,需要带括号
- computed :定义计算属性,调用属性使用 currentTime2 ,不需要带括号;
- 注意:methods和computed里不能重名
4)结论
调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这一点;计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销
小商店练习项目
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小商店</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
table {
border: 1px solid #e9e9e9;
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 8px 16px;
border: 1px solid #e9e9e9;
text-align: left;
}
th {
background-color: #f7f7f7;
}
</style>
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<th v-for="(title,index) in titles" :key="index" v-text="title"></th>
</tr>
</thead>
<tbody>
<tr v-for="(book, index) in books" :key="index">
<td v-text="index"></td>
<td v-text="book.name"></td>
<td v-text="book.date"></td>
<td>{{book.price | priceRule}}</td>
<td>
<button @click="sub(index)">-</button>
<span>{{book.num}}</span>
<button @click="add(index)">+</button>
</td>
<td>
<button @click="remove(index)">移除</button>
</td>
</tr>
</tbody>
</table>
<div>总价格:{{totalPrice | priceRule}}</div>
</div>
</body>
<script>
const vm = new Vue({
el: '#app',
data: {
titles: ['编号', '商品名称', '生产日期', '价格', '购买数量', '操作'],
books: [{
name: '风车',
date: '2020-9',
price: 12,
num: 1
},
{
name: '辣条',
date: '2020-2',
price: 2,
num: 1
},
{
name: 'AD钙',
date: '2020-10',
price: 15,
num: 1
},
{
name: '小糖果',
date: '2020-3',
price: 1,
num: 1
},
]
},
filters: {
priceRule(value) {
return '¥' + value.toFixed(2)
}
},
computed: {
totalPrice() {
return this.books.reduce((prev, current)=> {
prev +=current.num * current.price
return prev
}, 0)
}
},
methods: {
add(idx){
this.books[idx].num++
},
sub(idx){
this.books[idx].num--
if (this.books[idx].num == 0) {
this.books.splice(idx, 1)
}
},
remove(idx){
this.books.splice(idx, 1)
}
}
})
</script>
</html>