Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
尝试 Vue.js 最简单的方法是使用 JSFiddle 上的 Hello World 例子。你可以在浏览器新标签页中打开它,跟着例子学习一些基础用法。或者你也可以创建一个 .html 文件,然后通过如下方式引入 Vue:
开发环境版本,包含了有帮助的命令行警告<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
生产环境版本,优化了尺寸和速度<script src="https://cdn.jsdelivr.net/npm/vue"></script>
注:将以上文件引入 HTML 页面中即可,也可以下载后本地引用
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:
<div id="app">
{{ message }}
</div>
const app = new Vue({
el:'#app',
data: {
message: 'hello world!'
},
});
我们已经成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。我们要怎么确认呢?打开你的浏览器的 JavaScript 控制台 (就在这个页面打开),并修改 app.message 的值,你将看到上例相应地更新。
当一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
<!-- 创建一个Vue的根节点,Vue实例的作用域 -->
<div id="app">
<p>{{msg}}</p>
<p>30+40={{30+40}}</p>
</div>
// 创建Vue实例 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的
const vm = new Vue({
// 挂载点
el: "#app",
// 数据绑定
data: {
msg: "hello world"
},
});
console.log(vm.$data.msg); // "hello world"
// 数据已经注入到Vue实例中,可以当成vue属性直接访问
console.log(vm.msg); // "hello world"
// 响应式
vm.msg = "我已经被修改";
// 此时的数据和DOM已经关联,都是响应式的,我们可以看到页面上的也相应的更新了
v- 前缀作为一种视觉提示,用来识别模板中 Vue 特定的 attribute。指令带有前缀 v-,以表示它们是 Vue 提供的特殊特性。它们会在渲染的 DOM 上应用特殊的响应式行为。
Vuejs 在渲染元素的时候,如果我们仔细的去看,应该能看到一个闪现的过程, 这是因为 Vuejs 读取和渲染你的元素需要一定时间。所以会出现这个问题,这对于一下强迫症来说,简直要命,所以我们要怎么解决这个问题呢?
<div id="app">
<div> Hello { { name } }</div>
</div>
<script>
new Vue({
el: '#app',
data() {
return {
name: 'zhang'
}
}
})
</scirpt>
上面的例子极其简单,我们在刷新页面的时候应该可以看到 {{name}} 的闪现,但是如果我们加上 v-cloak :取消数据绑定时出现的代码闪烁
<div id="app">
<div> Hello { { name } }</div>
</div>
<style>
[v-cloak]{
display: none;
}
</style>
我们在对应的元素加上了 v-cloak 指令,并且也要添加对应的 style 样式声明。这样我们就看避免闪现的问题了。
v-once的作用是 定义它的元素或者组件只会渲染一次,包括元素或者组件的所有子节点.首次渲染后,不再随着数据的改变而重新渲染
<div id="app">
<p v-once v-text="msg"></p>
<p v-text="msg"></p>
</div>
<script>
const vm = new Vue({
el: "#app",
data() {
return {
msg: "hello"
}
},
});
</script>
v-text的作用(相当于原生js中的textContent) 用于将数据填充到标签中,作用于插值表达式类似,但是没有闪动问题
<div id="app">
<div v-text="message"></div>
</div>
<script>
const vm =new Vue({
el: '#app',
data: {
message: 'vue的初次学习'
}
})
</script>
v-html的作用可以解析html结构,既是可以解析字符串内的标签等html写法,并作为网页html结构插入标签内起作用。(相当于原生js中的innerHTML)
<div id="app">
<div v-text="message"></div>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
message: '<h1>vue的初次学习</h1>'
}
})
</script>
用来控制元素的显示/隐藏 ,主要是控制元素的display css属性的。v-show 指令的取值为true/false,分别对应着显示/隐藏
<li class="nav-item" v-show="isShow">
<a href="/ ">是否显示</a>
</li>
<script type="text/javascript">
const vm = new Vue({
el: '#app',
data: {
isShow: false
}
})
</script>
v-if、v-else-if、 v-else 指令的取值是为true或false,通过一定的条件,控制元素是否被渲染出来。
<div id="app">
<div v-if="seen>10">现在你看到我了</div>
<div v-else-if="seen>6">
<p>哈哈哈,你又看到我了!!!</p>
</div>
<div v-else>现在你看到我了</div>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
seen:5
}
})
</script>
继续在控制台输入vm.seen = 7,你会发现<p>哈哈哈,你又看到我了!!!</p>
显示出来了
单分支判断
<div id="app">
<p v-if="flag">{{msg}}</p>
<button @click="flag=!flag" v-text="tips=flag?'隐藏':'显示'"></button>
</div>
<script>
new Vue({
el: "#app",
data() {
return{
msg: '大家晚上好',
flag: false,
tips: '隐藏',
}
},
});
</script>
多分支判断
<div id="app">
<label for="">请输入积分数:</label>
<input type="number" v-model="point">
<p v-if="point>200" v-text="grade[0]"></p>
<p v-else-if="point>150" v-text="grade[1]"></p>
<p v-else-if="point>100" v-text="grade[2]"></p>
<p v-else-if="point>50" v-text="grade[3]"></p>
<p v-else v-text="grade[4]"></p>
</div>
<script>
new Vue({
el: "#app",
data() {
return {
grade: ['纸片会员', '木头会员', '铁皮会员', '金牌会员', '普通会员'],
point: 500,
}
},
});
</script>
注意:
1、v-show 其用法和 v-if 相同也可以设置元素的显示或隐藏。但是不具备条件判断功能
2、v-show相当于display:none
,只是隐藏标签,实际依然存在DOM中,v-if根据判断不进行标签渲染,实际在DOM根本不存在。
3、v-else 、v-else-if 必须要跟在 v-if 或v-else-if 模块后面
4、频繁的进行简单的显示隐藏建议用v-show,只是根据条件渲染元素用v-if
指令需要以 site in sites 形式的特殊语法, sites 是源数据数组并且 site 是数组元素迭代的别名(有时候,我们的data中的存放的数据不是个简单的数字或者字符串,而是数组Array类型,这个时候,我们要把数组的元素展示在视图上,就需要用到vue提供的 v-for 指令,来实现列表的渲染)
<div id="app">
<ul>
<li v-for="site in sites">
{{ site.id }}--- {{ site.name }}
</li>
</ul>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
sites: [
{id:1,name: 'sougou'},
{id:2,name: 'Google'},
{id:3,name: 'baidu'}
],
}
})
</script>
在控制台里,输入vm.sites.push({name: ‘360搜索’})你会发现列表最后添加了一项。
属性
<!-- 遍历userinfo对象 val 值 prop 键 index 索引 -->
<div v-for="(val, key,index) in userInfo" :key="index">
{{val}}--- {{key}} --- {{index}}
</div>
<p v-for="i in 10">这是第 {{i}} 个P标签</p>
实际使用中在渲染一组列表时key必须设置,而且必须是唯一标识,应该避免使用数组索引作为key,这可能导致一些隐蔽的bug;Vue中在使用相同标签元素过渡切换时,也会使用key属性,其目的也是为了让Vue可以区分它们,否则Vue只会替换其内部属性而不会触发过渡效果。另外,若不设置key还可能在列表更新时引发一些隐蔽的bug,下面来看一个案例:
<div id="app">
<div>
<label>ID:
<input type="text" v-model="id">
</label>
<label>Name:
<input type="text" v-model="name">
</label>
<input type="button" value="添加" @click="add">
</div>
<p v-for="item in list">
<input type="checkbox"> {{item.id}}----{{item.name}}
</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
list: [
{id: 1 ,name: "张三"},
{id: 2 ,name: "李四"},
{id: 3 ,name: "王五"},
{id: 4 ,name: "赵六"},
{id: 5 ,name: "七七"},
{id: 6 ,name: "八八"},
],
id: "",
name: "",
},
methods: {
add() { // 添加方法
this.list.unshift({
id: this.id,
name: this.name
});
this.name = this.id = "";
}
}
})
</script>
在图中可以看出,我们一开始勾选的是id为4的,但在头部添加一项之后,勾选项换成了id为3的选项。由于没有设置key,系统只知道我们选中的是列表第四项,但不知道是具体那一项。
在循环的p标签v-for 后面添加:key=”item.id”完美解决这个bug问题。
Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染, 因此使用key值可以提高渲染效率,同理,改变某一元素的key值会使该元素重新被渲染。
注意:v-for循环的时候,key属性只能使用number或string类型作为值,并且key在使用的时候,必须使用v-bind属性绑定的形式,指定key的值。
v-bind 主要用于属性绑定,比方你的class属性,style属性,value属性,href属性等等,只要是属性,就可以用v-bind指令进行绑定。v-bind:可以简写成:冒号
三种方法:
1、对象型 {red:isred}
2、三元型 isred?"red":"blue"
3、数组型 [{red:"isred"},{blue:"isblue"}]
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
<!-- 动态参数的缩写 -->
<a :[key]="url"> ... </a>
<input type="button" value="按钮" v-bind:title="mytitle + 'ai'">
<script>
const vm = new Vue({
el: '#app',
data: {
mytitle: '这是一个自定义title'
},
methods: {
show() {
alert('Hello')
}
}
})
</script>
<div id="app">
<div v-bind:class="{ active: isActive }"></div>
<div :style="redC">hello world</div>
<div :style="styleArr">hello world</div>
</div>
<style>
.active {
width: 100px;
height: 100px;
background: green;
}
</style>
<script>
new Vue({
el: '#app',
data: {
isActive: true,
redC: "color: red",
yellowB: "backgroundColor: yellow",
styleArr: [{color: 'red',backgroundColor:'yellow'}],
}
})
</script>
使用 v-on 指令绑定 DOM 事件,并在事件被触发时执行一些 JavaScript 代码.
绑定事件监听器。事件类型由参数给标签绑定函数,可以缩写为@,例如绑定一个点击函数 函数必须写在methods里面。
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>
<!-- 动态参数的缩写 -->
<a @[event]="doSomething"> ... </a>
<div id="app">
<!-- `show` 是在下面定义的方法名 -->
<button v-on:click="show">show</button>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
name: 'demo'
},
// 在 `methods` 对象中定义方法
methods: {
show: function(event) {
// `this` 在方法里指当前 Vue 实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if(event) {
console.log(event);
// 绑定者的标签名称
alert(event.target.tagName)
}
}
}
})
</script>
点击按钮翻转字符串
<div id="app">
<p>{{message}}</p>
<button v-on:click="reverseMessage">翻转消息</button>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
message: "Hello Vue.js!"
},
// 在 `methods` 对象中定义方法
methods: {
reverseMessage: function(){
this.message = this.message.split('').reverse().join(''); // !sj.euV olleH
}
}
})
</script>
注意:在reverseMessage方法中,我们更新了应用的状态,但没有触碰DOM,所以的DOM操作都是由Vue内部来处理的,你编写代码只需要关注逻辑层面即可。
vue下点击事件传参
<div id="app">
<!-- 注意:这里的第一个参数默认是`$event`原生 DOM 事件 从第二个参数开始才是要传递的 -->
<button @click.stop="calc($event,x,y)">计算</button>
<p>{{result}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
message: "Hello Vue.js!",
x: 50,
y: 100,
result: null,
},
methods: {
calc(event,x,y){
console.log(event);
this.result = `${x}+${y}=${x+y}`;
}
}
})
</script>
Vue.js 中使用内置的 v-model 指令通过绑定值和捕获 input 事件来模拟双向绑定,它能轻松实现表单输入和应用状态之间的数据双向绑定。
<input v-model="msg" >
<p>Msg: {{ msg }}</p>
<p>Msg:</p>
<p>{{ msg }}</p>
<textarea v-model="msg"></textarea>
在 input 或者 textarea 标签上使用 v-model=”msg” 相当于
<!-- 双向绑定:实时更新 -->
<input :value="msg" @input="e => msg = e.target.value">
<textarea :value="msg" @input="e => msg = e.target.value"></textarea>
<p v-text="msg"></p>
以上方式双向绑定都是实时更新的,那么添加lazy修饰符,可以实现数据延迟更新
<!-- 双向绑定:实时更新 -->
<input v-model="msg" >
<p v-text="msg"></p>
<!-- 双向绑定:延迟更新 修饰符lazy -->
<input v-model.lazy="msg" >
<!-- 相当于失去焦点时才触发更新操作 -->
<p v-text="msg"></p>
以上是vue中,常用的基本指令,不同的指令有着不同的效果,实现的方式不一样,所能展现的功能也不同,因此,通过使用指令,可以更好的提高开发效率
完整演示案例
<div id="app">
<p v-text="msgData"></p>
<p>{{ msgData }}</p>
<p v-text="msgHtml"></p>
<p v-html="msgHtml"></p>
<input v-model="msgModel" type="text"/>
<p>v-model数据:<span v-text="msgModel"></span></p>
<button v-on:click="alert">按钮</button>
<p v-for="(item, index) in list" :key="index">{{item}} -- {{index}}</p>
</div>
<template>
<div>
<p v-text="msgData"></p>
<p>{{ msgData }}</p>
<p v-text="msgHtml"></p>
<p v-html="msgHtml"></p>
<input v-model="msgModel" type="text"/>
<p>v-model数据:<span v-text="msgModel"></span></p>
<button v-on:click="alert">按钮</button>
<p v-for="(item, index) in list" :key="index">{{item}} -- {{index}}</p>
</div>
</template>
<script>
const vm = new Vue({
el: "#app",
data: {
message: 'Vue的生命周期',
msgData: '消息数据',
msgHtml: '<span style="color: red">消息HTML</span>',
msgModel: '',
list: ['apple', 'banana', 'fruit'],
},
methods: {
// alter: function(){}
// alter: ()=>{}
alert(){
alter("提示")
}
}
});
</script>
实现跑马灯效果案例
<!-- 1. 导入Vue包 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 2. 创建一个Vue控制的区域 -->
<div id="app">
<input type="button" value="浪起来" @click="lang">
<input type="button" value="低调" @click="stop">
<h4>{{msg}}</h4>
</div>
<!-- 3. 创建Vue实例 -->
<script>
// 注意:在vm实例中,如果想要获取data上的数据,或者调用methods中的方法,必须通过this.数据属性名方法名来进行访问,this就表示new出来的vm实例对象
const vm = new Vue({
el: "#app",
data: {
msg: '这是学习Vue的第一节课程,大家晚上好!",
intervalId: null,
},
methods: {
lang(){
if(this.intervalId==null){
this.this.intervalId = setInterval(()=>{
// 获取到头的第一个字符
let start = this.msg.substring(0,1);
// 获取到后面的所有字符
let end = this.msg.substring(1);
// 重新拼接得到新的字符串
this.msg = end+start;
},400)
}
},
stop: ()=>{
clearInterval(this.intervalId);
this.intervalId = null;
}
}
});
</script>
在事件处理程序中调用 event.preventDefault()或event.stopPropation()取消默认事件和阻止冒泡。尽管我们可以在方法中轻松实现,但是更好的方式是:方法只是纯粹的数据逻辑,而不去处理DOM事件细节。
为了解决这个问题,Vue为v-on指令提供了事件修饰符。
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联起来 -->
<a v-on.click.stop.prevent="doThat"></a>
<!-- 只有修饰符 阻止表单默认事件 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只在event.target是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
注意:使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用v-on.click.prevent.self会阻止所有的点击,而v-on:click.self.prevent只会阻止对元素自身的点击。
<div id="app">
<!-- 使用 .stop 阻止冒泡 -->
<div class="inner" @click="div1Handler">
<input type="button" value="戳他" @click.stop="btnHandler">
</div>
<!-- 使用 .prevent 阻止默认行为 -->
<a href="http://www.baidu.com" @click.prevent="linkClick">有问题,先去百度</a>
<!-- 使用 .capture 实现捕获触发事件的机制 -->
<div class="inner" @click.capture="div1Handler">
<input type="button" value="戳他" @click="btnHandler">
</div>
<!-- 使用 .self 实现只有点击当前元素时候,才会触发事件处理函数 -->
<div class="inner" @click="div1Handler">
<input type="button" value="戳他" @click="btnHandler">
</div>
<!-- 使用 .once 只触发一次事件处理函数 -->
<a href="http://www.baidu.com" @click.prevent.once="linkClick">有问题,先去百度</a>
<!-- 演示:.stop 和 .self 的区别 -->
<div class="outer" @click="div2Handler">
<div class="inner" @click="div1Handler">
<input type="button" value="戳他" @click.stop="btnHandler">
</div>
</div>
<!-- .self 只会阻止自己身上冒泡行为的触发,并不会真正阻止 冒泡的行为 -->
<div class="outer" @click="div2Handler">
<div class="inner" @click.self="div1Handler">
<input type="button" value="戳他" @click="btnHandler">
</div>
</div>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {},
methods: {
div1Handler() {
console.log('这是触发了 inner div 的点击事件')
},
btnHandler() {
console.log('这是触发了 btn 按钮 的点击事件')
},
linkClick() {
console.log('触发了连接的点击事件')
},
div2Handler() {
console.log('这是触发了 outer div 的点击事件')
}
}
});
</script>
在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
<input v-on:keydown.left="submit">
Vue 提供了绝大多数常用的按键码的别名:.enter .tab .delete .esc .space .up .down .left .right
你还可以通过全局 config.keyCodes 对象自定义按键修饰符别名:
可以使用 v-on:keyup.f1
Vue.config.keyCodes.f2=113;
可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器.ctrl .alt .shift .meta
<!-- Alt + C -->
<input v-on:keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div v-on:click.ctrl="doSomething">Do something</div>
请注意修饰键与常规按键不同,在和 keyup 事件一起用时,事件触发时修饰键必须处于按下状态。换句话说,只有在按住 ctrl 的情况下释放其它按键,才能触发 keyup.ctrl。而单单释放 ctrl 也不会触发事件。如果你想要这样的行为,请为 ctrl 换用 keyCode:keyup.17。
.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>
todoList案例
<div id="app">
<input type="text" @keyup.enter="submit($event)" placeholder="请输入待办项" />
<ol>
<li v-for="(item,index) in list" :key="index" v-text="item"></li>
</ol>
</div>
<script>
const vm = new Vue({
el: "#app",
data(){
return{
list:[],
}
},
methods:{
submit(ev){
console.log(ev.key);
this.list.push(ev.target.value);
ev.target.value = "";
}
}
});
</script>
计算属性可以同时设置getter()、setter()方法,是以函数形式,在vue实例的选项对象的comoputed选项中定义的。
前面做了一个字符串翻转的案例
<div id="app">
<input v-model="message">
<p>{{message.split('').reverse().join("")}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
message: "Hello Vue.js!"
},
methods: {
reverseMessage(){
}
}
})
</>
通过使用computed计算属性的语法:
<div id="app">
<input v-model="message">
<p>{{reverseMessage}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
// 属性
data: {
message: "Hello Vue.js!"
},
// 方法
methods: {
reverseMessage(){
}
},
// 计算属性
computed: {
// 声明了一个计算属性reverseMessage,给出的函数将用作属性vm.reverseMessage的getter函数。
reverseMessage: function(){
return this.message.split('').reverse().join("");
}
}
})
</script>
当msg属性的值改变时,reverseMessage的值也会自动更新,并且会自动同步更新DOM部分。在浏览器中的控制窗口修改vm.msg的值,可以发现reverseMessage的值也会随之发生变化.
计算属性默认只有getter,因此是不能直接修改计算属性的,如果需要可以提供一个setter,如下例:
<div id="app">
<input v-model="message">
<p>{{reverseMessage}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
message: "Hello Vue.js!"
},
methods: {
},
// 计算属性
computed: {
reverseMessage: {
set(newValue){
this.message = newValue;
},
// 计算属性一般是没有set方法,只读属性
get(){
return this.message.split('').reverse().join("");
}
}
}
})
</script>
在浏览器控制台中修改vm.reverseMessage=’123456’后的效果图如下,可以看到值都同时变化了,这是调用reverseMessage的setter函数来实现的。
机制:watch内的函数名 === data中的属性名
触发:data中的属性名对应的值发生改变时,就会触发watch内的函数就执行
参数:watch中的函数有两个参数,一个是new新值,一个old旧值。
<input v-model="firstName" />
<input v-model="lastName" />
<div id="demo">{{ fullName }}</div>
<script>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName(val) {
this.fullName = this.firstName + ' ' + val
}
}
})
</script>
watch:监测的是属性值, 只要属性值发生变化,其都会触发执行回调函数来执行一系列操作;
computed:监测的是依赖值,依赖值不变的情况下其会直接读取缓存进行复用,变化的情况下才会重新计算;
区别是:计算属性不能执行异步任务,计算属性必须同步执行。也就是说计算属性不能向服务器请求或者执行异步任务。如果遇到异步任务,就交给侦听属性。Watch也可以检测computed属性。
计算属性是基于它的响应式data中的数据依赖进行缓存的,只有在计算属性的相关响应式依赖发生改变时才会重新求值。而方法和监听器不存在缓存
利用插值表达式计算商品金额
<div id="app">
<p>数量:<input type="number" v-model="num" min="0"></p>
<p>单价:<input type="number" v-model="price"></p>
<p>总金额:{{num*price}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
num: 0,
price: 0,
},
})
</script>
使用计算属性来实现商品金额的计算
<div id="app">
<p>数量:<input type="number" v-model="num" min="0"></p>
<p>单价:<input type="number" v-model="price"></p>
<p>总金额:{{amount}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
num: 0,
price: 0,
},
methods: {
},
// 计算属性
computed: {
amount() {
return this.num * this.price;
}
},
})
</script>
分析:computed就是计算属性,从字面意思能计算也就是把单价乘上数量,最终生成了金额。
要注意计算属性是有缓存的,也就是只要当单价或者数量发生变化,和缓存中的值不同的时候,才会重新计算。
如果单价或者数量没有发生变化,computed不会重新计算。
使用侦听器属性来实现商品金额的计算
<div id="app">
<p>数量:<input type="number" v-model="num" min="0"></p>
<p>单价:<input type="number" v-model="price"></p>
<p>总金额:{{total}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
num: 0,
price: 0,
total: null,
},
methods: {
},
// 计算属性
computed: {
amount() {
return this.total = this.num * this.price;
}
},
// 监听器属性
watch: {
num(newNum, oldNum) {
console.log(newNum, oldNum);
this.total = newNum * this.price;
},
price(newP, oldP) {
console.log(newP, oldP);
this.total = this.num * newP;
}
}
})
</script>
注意:监听器实现,从字面意思上也是能理解,监听既是监听单价和数量的变化,如果有变化,那么total就会被重新赋值。这里呢,有一个total默认值的。
三种方法相比,计算属性最佳,代码相比监听器属性也比较少。虽然第一种最简单,但是不推荐在插值表达式中书写逻辑计算代码。