computed
:用于声明要在组件实例上暴露的计算属性。(官方文档描述)
我们已经知道,在模板中可以直接通过插值语法
显示一些data中的数据
。
但是在某些情况,我们可能需要对数据进行一些转化后再显
示,或者需要将多个数据结合起来进行显示
:
简单的运算
;模板过重
和难以维护
;而且因为多个地方都使用到,所以会有大量重复的代码,那么我们可以将逻辑抽离出去:
用法示例:
<div id="app">
<h2>{{fullName}}h2>
<h2>{{getScorelevel}}h2>
<h2>{{reverseMessage}}h2>
div>
<script>
const app = Vue.createApp({
data() {
return {
// 1.姓名
firstName: "kobe",
lastName: "byrant",
// 2.分数及不及格
score: 65,
// 3.一串文本:对文本中的单词进行反转显示
message: "my name is sevgilid"
}
},
methods: {
},
computed: {
// 计算属性对应的是一个函数(经过响应式复杂逻辑转化的都应写在computed里)
// 计算属性是有缓存的
fullName() {
return this.firstName + "" + this.lastName
},
getScorelevel() {
return this.score > 60 ? '及格' : '不及格'
},
reverseMessage() {
return this.message.split("").reverse().join("")
}
}
})
app.mount('#app')
script>
watch:
用于声明在数据更改时调用的侦听回调。(官方文档描述)
什么是侦听器呢?
插值语法等方式绑定到template
中;代码逻辑
中监听某个数据的变化,这个时候就需要用侦听器watch
来完成了;用法:{ [key: string]: string | Function [ Object | Array}
如下示例:
点击按钮后message就会修改,且控制台打印’‘message发生了改变’’
<div id="app">
<h2>{{message}}h2>
<button @click="changeMessage">修改messagebutton>
div>
<script>
const app = Vue.createApp({
data() {
return {
message: 'hello vue'
}
},
methods: {
changeMessage() {
this.message = "你好啊,李二狗"
}
},
watch: {
message() {
console.log("message发生了改变");
}
}
})
app.mount('#app')
script>
通过以上例子发现其实就是想监听谁在里面写谁,但这样使用的话只知道数据发生了改变,并不知道改变是什么。
默认是有传过来两个参
数的:分别是newvalue,oldvalue
,像下面这样修改代码后就可以看到前后数据发生的改变: watch: {
message(newValue,oldValue) {
console.log("message已发生改变", newValue, oldValue);
}
打印结果:
对象类型
,那么拿到的是代理对象
,可以通过newValue.name这样去拿值 <div id="app">
<h2>{{info}}h2>
<button @click="changeInfo">改变infobutton>
div>
<script>
const app = Vue.createApp({
data() {
return {
info:{name:"daa",age:15}
}
},
methods: {
changeInfo(){
this.info={name:"kkk",age:25}
}
},
watch: {
info(newValue,oldValue){
console.log("info数据发生了变化", newValue,oldValue);
console.log(newValue.name,oldValue.name);![在这里插入图片描述](https://img-blog.csdnimg.cn/9a9764dc762549caa4d9e4905b6336ea.png)
}
}
})
app.mount('#app')
script>
控制台打印结果:
deep:true
:为true时进行深度监听 immediate:true
:为true时第一次渲染直接执行一次监听器其实默认是不进行深度监听的,像下面的例子:
修改的是整个info是可以监听
到的info对象中的一个属性是监听不到
<script>
const app = Vue.createApp({
data() {
return {
info: {name:"kkk", age:25}
}
},
methods:{
changeInfo(){
// 1.修改原对象,可以监听
// this.info = {name:"wxx", age:52}
// 2.直接修改原对象的一个属性
this.info.name = "sevgilid"
}
},
watch:{
// 默认watch监听不会进行深度监听(所以只改变属性时未监听到)
// info(newValue,oldValue){
// console.log("info数据发生了改变", newValue,oldValue);
// }
// 进行深度监听
info:{
handler(newValue,oldValue){
console.log("info一发生改变",newValue, oldValue);
},
// 监听器选项:
//info进行深度监听:加上以下配置后即可监听到属性改变
deep:true,
// 第一次渲染直接执行一次监听器
immediate:true
}
}
})
app.mount('#app')
</script>
一个相对综合的案例,可以对前面几篇博客知识进行练习(完整代码在文末)
案例说明:
1.在界面上以表格的形式,显示一些书籍的数据;
2.在底部显示书籍的总价格;
3.点击+或者-可以增加或减少书籍数量(如果为1,那么不能继续-);
4.点击移除按钮,可以将书籍移除(当所有的书籍移除完毕时,显示:购物车为空);
5.点击行变色
案例步骤:
1.搭建界面内容:做出表格,调整基本样式
2.获取数据:可以从后台拿数据,这里选择自己在data中模拟数据
3.分析实现逻辑:
步骤代码详解:
遍历数据及加减:
注意事项:
总价响应式:
注意事项:
移出操作:
行变色:
案例完整代码:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="../Vue3.js">script>
<style>
table {
border-collapse: collapse;
color: brown;
text-align: center;
}
table,
th,
td {
border: 1px solid black;
}
.active {
background-color: aqua;
}
style>
head>
<body>
<div id="app">
<div class="shopCurt">
<table>
<thead>
<tr>
<th>序号th>
<th>商品名字th>
<th>价格th>
<th>数量th>
<th>商品描述th>
<th>操作th>
tr>
thead>
<tbody>
<template v-for="( item,index ) in infos">
<tr :class="{active:index === currentIndex}" @click="rowClick(index)">
<td>{{ index+1 }}td>
<td>{{ item.name }}td>
<td>{{ item.price }}td>
<td><button @click="decrement(index)" :disabled="item.count<=1">-1button>{{ item.count }}
<button @click="increment(index)">+1button>
td>
<td>{{ item.dec }}td>
<td><button @click="removeBook(index)">{{ item.caozuo }}button>td>
tr>
template>
tbody>
table>
div>
<h2>AllPrice:{{ allPrice }}h2>
div>
body>
<script src="./Vue3.js">script>
<script>
const app = Vue.createApp({
data() {
return {
currentIndex: -1,
infos: [
{ sort: 0, name: "华为电脑", price: 9.9, count: 1, dec: "9.9秒杀快来抢购", caozuo: "移除" },
{ sort: 0, name: "iphoneX", price: 12.8, count: 1, dec: "苹果X最新出炉", caozuo: "移除" },
{ sort: 0, name: "小米11Plus", price: 13.1, count: 1, dec: "速度来抢", caozuo: "移除" },
{ sort: 0, name: "外星人电脑", price: 56, count: 1, dec: "真的便宜", caozuo: "移除" },
{ sort: 0, name: "OPPOR11", price: 100, count: 1, dec: "好用不贵", caozuo: "移除" }
]
}
},
computed: {
allPrice() {
let price = 0;
for (const item of this.infos) {
price += item.price * item.count
}
return price
}
},
methods: {
// 监听加减按钮
increment(index) {
this.infos[index].count++
},
decrement(index) {
this.infos[index].count--
},
// 监听行点击变色
rowClick(index) {
this.currentIndex = index;
},
// 移出操作
removeBook(index) {
this.infos.splice(index, 1)
}
}
})
app.mount('#app')
script>
html>
实现效果: