计算属性
1.定义:要用的属性不存在,要通过已有属性计算(加工)得来
2.原理:底层借助了Object.defineproperty方法提供的getter和setter。
3.get原理函数什么时候执行?
3.1初次读取该时会执行一次
3.2当依赖的数据发生改变时会被再次调用
4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
5.备注:
5.1计算属性最终会出现在vm上,直接读取使用即可;
5.2如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据
<!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>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<input type="text" v-model="firstName"><br/>
<input type="text" v-model="lastName">
<p>全名:{{name}}</p>
</div>
<script>
const vm = new Vue({
el: "#root",
data: {
firstName: "张",
lastName: "三"
},
// 计算属性,对data中的属性做进一步的加工处理再输出(输出的是一个对象),会有缓存
computed: {
/* get调用name? 1.初次读取nane时;2.所依赖的数据发生变化时 */
name: {
// get何时被调用? 1.初次读取nane时;2.所依赖的数据发生变化时
get() {
console.log("get被调用了");
return this.firstName.slice() + "-" + this.lastName;
},
// name被修改时调用set
set(value) {
// console.log(value);
console.log("set修改");
// 将字符串按指定的字符分割成数组
const arr = value.split('-');
this.firstName = arr[0];
this.lastName = arr[1]
}
},
// 简写法:将name写成一个函数形式
/* name() {
return this.firstName.slice() + "-" + this.lastName;
} */
}
})
</script>
</body>
</html>
监视属性
1.当被监视的属性变化时,回调函数自动调用,进行相关操作
2.监视的属性必须存在,才能进行监视
3.监视的两种写法:
3.1在new Vue({})里面使用watch配置
3.2通过vm.$watch监视
<!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>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<!-- <h1>今天天气{{w?"炎热":"凉爽"}}</h1> -->
<h1>今天天气{{weather}}</h1>
<!-- <button @click="fnc">切换天气</button> -->
<!-- 事件绑定的等号后面不止可以写函数名也可以写一些简单的语句 -->
<button @click="w=!w">切换天气</button>
</div>
<script>
// 如果明确了要监视那个属性,就用watch,如果开始不知道监视谁,后续有需要监视的,就用.$watch()
const vm = new Vue({
el: "#root",
data: {
w: true
},
methods: {
/* fnc() {
this.w = !this.w
} */
},
computed: {
// 完整-配置对象
/* weather: {
get() {},
set() {}
}, */
// 函数形式
weather() {
return this.w ? "炎热" : "凉爽"
}
},
// 监视1.0
/* watch: {
// 监视的对象
weather: {
// immediate:初始化时立即执行handler,默认是false
immediate: true,
// 当w发生改变时会调用handler回调函数
handler(newVal, oldVal) {
// console.log(newVal);
// console.log(oldVal);
console.log("今天天气 " + newVal + ",昨天天气 " + oldVal);
}
}
} */
});
// 监视2.0,首先是要先创建一个Vue实例对象
// $watch(x,y):第一个参数是要监视的对象,第二个参数是配置对象
vm.$watch("weather", {
immediate: true,
handler(newVal, oldVal) {
console.log("今天天气 " + newVal + ",昨天天气 " + oldVal);
}
})
</script>
</body>
</html>
深度监视
1.vue中的watch默认不监测对象内部值的改变(一层)
2.配置deep:true可以监测对象内部值改变(多层)
备注:
1.vue自身可以监测对象内部值得改变,但是vue提供的watch默认不可以
2.使用watch时,根据数据的具体结构,决定是否采用深度监视
<!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>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>今天天气{{weather}}</h1>
<button @click="w=!w">切换天气</button>
<hr>
<h3>a:{{number.a}}</h3>
<button @click="number.a++">a++</button>
<hr>
<h3>b:{{number.b}}</h3>
<button @click="number.b++">b++</button>
</div>
<script>
const vm = new Vue({
el: "#root",
data: {
w: true,
number: {
a: 1,
b: 0
}
},
methods: {},
computed: {
weather() {
return this.w ? "炎热" : "凉爽"
}
},
// vue默认是可以监测到data中多层级的数据改变的,但是vue为程序员提供的watch默认是不可以监测多层级数据的
// 想要在vue提供的watch里面监测到多层级数据的改变的,就要添加deep: true,
watch: {
// 原始写法
// "xxx":{},
weather: {
immediate: true,
handler(newVal, oldVal) {
console.log("今天天气 " + newVal + ",昨天天气 " + oldVal);
}
},
// 监视多级结构中的某个属性的变化需要用原始写法(外面加引号)
/* "number.a": {
handler() {
console.log("number里面的a数据改变了");
}
}, */
number: {
// 监视多级结构中的所有属性的变化
deep: true,
handler() {
console.log("number里面的数据改变了");
}
}
}
});
</script>
</body>
</html>
监视属性的简写
<!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>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>今天天气{{weather}}</h1>
<button @click="w=!w">切换天气</button>
</div>
<script>
const vm = new Vue({
el: "#root",
data: {
w: true,
},
methods: {},
computed: {
weather() {
return this.w ? "炎热" : "凉爽"
}
},
watch: {
// 原始写法
// "xxx":{},
// 正常写法
/* weather: {
// immediate: true,
// deep: true,
handler(newVal, oldVal) {
console.log("今天天气 " + newVal + ",昨天天气 " + oldVal);
},
} */
// 简写形式:只有handler而已,没有其他的配置项,这里的weather就相当于handler
/* weather(newVal, oldVal) {
console.log("今天天气 " + newVal + ",昨天天气 " + oldVal);
} */
}
});
// 正常写法
/* vm.$watch('weather', {
immediate: true,
deep: true,
handler(newVal, oldVal) {
console.log("今天天气 " + newVal + ",昨天天气 " + oldVal);
}
}) */
// 简写:只有回调函数,没有其他的配置项
vm.$watch('weather',
function(newVal, oldVal) {
console.log("今天天气 " + newVal + ",昨天天气 " + oldVal);
})
</script>
</body>
</html>
计算属性和监视属性的区别
计算属性是对data中的数据进行加工后形成新的数据,并且输出;data中的数据发生改变,形成的那个新数据也会发生响应的改变
监视属性是监测到data中的某个属性发生变化时,会进行特定的一些处理,不需要输出
区别:
1.computed能完成的功能,watch都可以完成
2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。小原则:
2.1所有被vue管理的函数,最好写成普通函数,这样this的指向才是vue的实例对象或组件实例对象
2.1所有不被vue所管理的函数(定时器的回调函数、ajax的回调函数、promise的回调函数等),最好写成箭头函数,这样this的指向才是vue的实例对象或者组件实例
<!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>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<input type="text" v-model="firstName"><br/>
<input type="text" v-model="lastName">
<p>全名:{{name}}</p>
</div>
<script>
new Vue({
el: "#root",
data: {
firstName: "张",
lastName: "三",
name: '张-三'
},
// 监视属性可以执行异步代码,而计算属性不可以
watch: {
// 监视姓:姓发生改变,将改变后的姓的新值与名拼接,组成新的姓名
firstName(newVal) {
// 在这里用的是箭头函数,
setTimeout(() => {
this.name = newVal + "-" + this.lastName
}, 1000)
},
// 监视名:名发生变化,将名的新值与姓拼接,组成新的姓名
lastName(newVal) {
this.name = this.firstName + "-" + newVal
setTimeout(function() {}, 1000)
}
}
})
</script>
</body>
</html>