计算属性
计算属性API,计算属性教程
计算属性在template中可以像对象的属性一样使用
import Vue from "vue/dist/vue"
Vue.config.productionTip = false;
new Vue({
data: {
user: {
email: "ds@163.com",
nickName: "xyz",
phone: "187",
}
},
computed: {
// 计算属性第一种写法,计算属性的值是一个函数
userInfos() {
const user = this.user;
return user.nickName || user.email || user.phone;
},
// 计算属性的第二种写法,计算属性的值是一个对象,对象包括get和set方法
displayName: {
get() {
const user = this.user;
return user.nickName || user.email || user.phone;
},
set(value) {
this.user.nickName = value;
}
}
},
methods:{
setNickName(){
console.log("setNickName")
this.displayName = "dswxyz"; // 计算属性的赋值
}
},
template: `
<div>
{{ userInfos }}
<hr>
{{ displayName }} <button @click="setNickName">setNickName</button>
</div>
`
}).$mount('#app');
注意,如果依赖(computed中基础属性)没有变,computed会使用缓存的计算结果;
计算属性,数组计算与展示
import Vue from "vue/dist/vue"
Vue.config.productionTip = false;
let index = 0;
const createUser = (name, gender) => {
index += 1;
return {id: index, name: name, gender: gender};
}
new Vue({
data: {
users: [
createUser("王重阳", "男"),
createUser("祖冲之", "男"),
createUser("小龙女", "女"),
createUser("张曼玉", "女"),
],
gender: "all",
},
computed: {
displayUsers() {
const hash = {"all":"","male":"男","female":"女"}
return this.users.filter((u) => this.gender === "all" || u.gender === hash[this.gender]);
}
},
template: `
<div>
<div>
<button @click="gender = 'all'">全部</button>
<button @click="gender = 'male'">男</button>
<button @click="gender = 'female'">女</button>
</div>
<hr/>
<ul>
<li v-for="(u,index) in displayUsers" :key="index">{{ u.name }} {{ u.gender }}</li>
</ul>
</div>
`,
}).$mount('#app');
其中,displayUsers是对数组数据的计算
watch属性
watch API
watch能够监听到数据的变化,比如数据n发生变化时,一定会被watch监听,监听方法中,可以进行相关数据处理或者操作,如果不想操作,可以设置flag规避;
注意,watch的执行是异步的,在改变n的操作后,直接重置flag是无效的
this.inUndoMode = true;
this.n = last.from; // watch 是异步的
this.inUndoMode = false; // 在异步的watch执行完再执行
上面重置flag(inUndoMode)的操作是无效的,必须用链式操作或者nextTick:
import Vue from "vue/dist/vue";
Vue.config.productionTip = false;
new Vue({
data: {
n: 0,
inUndoMode: false,
history: []
},
watch: {
n(newValue, oldValue) {
!this.inUndoMode && this.history.push({from: oldValue, to: newValue});
}
},
template: `
<div>
{{ n }}
<hr>
<button @click="n += 1">+1</button>
<button @click="n += 2">+2</button>
<button @click="n -= 1">-1</button>
<button @click="n -= 2">-2</button>
<hr>
<button @click="undo">撤销</button>
<hr>
{{ history }}
</div>`,
methods: {
undo() {
const last = this.history.pop();
this.inUndoMode = true;
// this.n = last.from; // watch 是异步的
// this.inUndoMode = false; // 无效,因为watch是异步操作的
// 规避异步watch的方法:使用链式操作
Promise.resolve().then(() => {
this.n = last.from;
}).then(() => {
this.inUndoMode = false
});
// 规避异步watch的方法:使用nextTick,下一次能动的时候执行
this.n = last.from;
this.$nextTick(() => {
this.inUndoMode = false;
});
}
}
}).$mount('#app');
watch的immediate选项
immediate选项,表示监听数据从无到有的变化,下面是模拟computed的效果
import Vue from "vue/dist/vue"
Vue.config.productionTip = false;
new Vue({
data() {
return {
user: {
nickName: "dsw",
phone: "187",
email: "ds@163.com"
},
displayName: undefined,
};
},
watch:{
"user.nickName":{
handler(){
const {user: {nickName, email, phone}} = this;
this.displayName = nickName || email || phone;
},
immediate: true, // 表示监听从无到有的变化
},
"user.email":{
handler(){
const {user: {nickName, email, phone}} = this;
this.displayName = nickName || email || phone;
},
immediate: true,
},
"user.phone":{
handler(){
const {user: {nickName, email, phone}} = this;
this.displayName = nickName || email || phone;
},
immediate: true,
},
},
template: `
<div>
{{ displayName }}
<hr>
<button @click="user.nickName = ''">RemoveName</button>
</div>`,
}).$mount("#app");
watch的deep选项,监听对象属性的变化
正常情况下,watch只能监听基础数据类型值的变化,或者对象类型地址的变化,要监听对象属性值的变化,需要加上deep选项
import Vue from "vue/dist/vue"
Vue.config.productionTip = false;
new Vue({
data() {
return {
n: 0,
obj: { name: "dsw" },
user: {name : "dsw"},
}
},
template:`<div>
{{n}} <button @click="n += 1">n+1</button> // watch: n 变化了
<hr>
{{obj}} <button @click="obj = {name: 'dsw'}"> obj new</button> // watch: obj 变化了
<hr>
{{obj}} <button @click="obj.name = 'xyz'"> obj.name = xyz</button> // watch: obj.name 变化了
<hr>
{{user}} <button @click="user.name = 'xyz'"> user.name = xyz</button> // watch: user.name 变化了, watch: user 变化了
</div>`,
watch:{
n(){ console.log("watch: n 变化了"); },
"obj.name"(){ console.log("watch: obj.name 变化了"); },
obj(){ console.log("watch: obj 变化了"); },
"user.name"(){ console.log("watch: user.name 变化了"); },
user:{
handler(){ console.log("watch: user 变化了") },
deep: true,
}
}
}).$mount("#app");
代码中,user对象的监听加了deep选项,能监听到name的变化,但是obj对象就监听不到name的变化
watch的另一种用法
created() {
this.$watch('n',function (){
console.log("n change")
},{immediate: true})
},
watch的语法总结
watch:{
obj: function (){ },
obj(){ },
obj: ["onObjChanged", "onObjChanged2"],
obj: "onObjChanged",
obj:{
handler(){},
deep: true,
immediate: true,
},
},
其中,onObjChanged和onObjChanged2是在methods中定义的函数;