计算属性
使用已有的属性去进行加工计算,生成一个全新的属性(简单理解)
计算属性
1. 定义:需要的属性不存在,需要通过已有的属性计算而来。
2. 原来:底层借助了Object.defineProperty方法提供的setter和getter方法
3. get函数的执行时机:
(1). 初次读取时会执行一次
(2). 当依赖的数据发生改变时会被再次调用
4. 优势:与methods实现对比,计算属性内部有缓存机制,效率高,调试方便
5. 备注:
(1). 计算属性最终会出现在vm上,直接读取即可
(2). 如果计算属性要被修改,必须写set函数进行响应修改
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br>
名:<input type="text" v-model="lastName"> <br>
全名:<span>{{fullName}}</span>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false; // 阻止Vue在启动时生成生产提示。
new Vue ({
el: "#root",
data: {
firstName: "张",
lastName: "三"
},
computed: {
fullName: {
// 当读取计算属性值的时候,get方法被调用,且返回值。
get() {
console.log("get被调用了")
return this.firstName + " - " + this.lastName;
},
// 当修改了计算属性的时候,set方法被调用
set(val) {
this.firstName = val;
}
}
}
});
</script>
计算属性的简写方式
只需要gei方法的时候才能进行简写
<script type="text/javascript">
Vue.config.productionTip = false; // 阻止Vue在启动时生成生产提示。
new Vue ({
el: "#root",
data: {
firstName: "张",
lastName: "三"
},
computed: {
// 全写
/* fullName: {
get() {
console.log("get被调用了")
return this.firstName + " - " + this.lastName;
},
set(value) {
this.firstName = value;
}
} */
fullName() {
console.log("get被调用了")
return this.firstName + " - " + this.lastName;
}
}
});
</script>
监视属性
普通监视
- 普通属性可以监视,计算属性也可以监视
- 监视属性watch:
1. 当被监视的属性发生变化,回调函数handler自动调用
2. 监视的属性必须存在
3. 监视属性的两种写法
- new Vue时传入watch配置
- 通过vm.$watch进行监视
<body>
<div id="root">
<h2>今天天气很{{weather}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
// 创建Vue实例
new Vue({
el: '#root', // el用于定义当前Vue实例为哪个容器服务,值通常为css选择器
data: {
isHot: true
},
computed: { // 计算属性
weather() {
return this.isHot ? "炎热" : "凉爽"
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot;
}
},
watch: {
isHot:{
// immediate: true, // 初始化时让handler被调用
// 当isHot发生改变时调用,newValue修改后的值,oldValue修改前的值
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue)
}
}
}
});
</script>
深度监视
- 深度监视deep
1. watch默认不监视对象内部值的改变
2. 配置deep为true可以监视对象内部值的改变
3. 备注:
- Vue自身可以监视对象内部值的改变,但是提供的watch默认不可以
<body>
<div id="root">
<h2>今天天气很{{weather}}</h2>
<button @click="changeWeather">切换天气</button>
<hr>
<h3>numbers.a的值是{{numbers.a}}</h3>
<button @click="numbers.a++">a自增</button>
<hr />
<h3>numbers.a的值是{{numbers.b}}</h3>
<button @click="numbers.b = numbers.b+2">b+2</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
// 创建Vue实例
new Vue({
el: '#root', // el用于定义当前Vue实例为哪个容器服务,值通常为css选择器
data: {
isHot: true,
numbers: {
a: 1,
b: 1
}
},
computed: {
weather() {
return this.isHot ? "炎热" : "凉爽"
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot;
}
},
watch: {
isHot:{
// immediate: true, // 初始化时让handler被调用
// 当isHot发生改变时调用
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue)
}
},
// 监视多级结构中某个属性的变化
// "numbers.a": {
// handler() {
// console.log("a被改变了; a = " + this.numbers.a)
// }
// }
numbers: {
// 监视多级结构中属性改变
deep: true,
handler() {
console.log("a被改变了; a = " + this.numbers.a)
}
}
}
});
</script>
简写
// 正常写法
watch: {
isHot:{
// immediate: true, // 初始化时让handler被调用
// 当isHot发生改变时调用,newValue修改后的值,oldValue修改前的值
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue)
}
}
}
vm.$watch("isHot", {
// immediate: true, // 初始化时让handler被调用
// 当isHot发生改变时调用,newValue修改后的值,oldValue修改前的值
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue)
}
})
// 简写,不配置其他的项(immediate、deep等都不配置,只有handler)
watch:{
isHot(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue)
}
}
vm.$watch("isHot",function(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue)
})
watch和computed对比
computed能完成的功能,watch都能完成
watch能完成的功能,computed不一定能完成。例如:watch中可以开启异步任务,computed不能
两个原则
- 所有被Vue管理的函数最好写成普通函数,这样this指向vm或组件实例对象
- 所有不被Vue管理的函数(定时器回调函数,ajax回调函数、Promise的回调函数等),最好写成箭头(=>)函数,this的指向才是vm或组件实例对象