computed & watch 官方文档:API — Vue.js
1.computed 计算属性
#computed:{ [key: string]: Function | { get: Function, set: Function } }
new Vue({
data: {
user: {
email: "fangyinghang@qq.com",
nickname: "方方",
phone: "13812312312"
}
},
computed:{
/* [语法一]computed:{ [key: string]: Function } */
displayNameXXX(){
const user=this.user
return user.email || user.nickname || user.phone
},
/* [语法二]computed:{ [key: string]: { get: Function, set: Function } } */
displayName:{
get(){
const user=this.user
return user.nickname || user.email || user.phone
},
set(value){
this.user.nickname = value
}
}
},
template: `
<div>
{{displayNameXXX}}
<div>
{{displayName}}
<button @click="set">set</button>
</div>
</div>
`,
methods:{
set(){
this.displayName='思思'
}
}
}).$mount("#app");
#computed例子: 选取目标性别列表
/* 创建用户 */
let id=0
const createUser=(name,gender)=>{
id += 1
return {id:id,name:name,gender:gender}
}
new Vue({
data() {
return {
users: [
createUser("方方","男"),
createUser("小思","女"),
createUser("小玮","女"),
],
selectGender:''
};
},
computed:{
displayUsers(){
/* computed缓存: 依赖属性没有变化不会重新计算 */
console.log("displayUsers 计算了一次")
/* hash表查 选取gender 值 */
const hash={
male: "男",
female: "女"
}
const {users,selectGender} = this
if(selectGender === ""){
return users
}else if(typeof selectGender === "string"){
return users.filter(u => u.gender===hash[selectGender])
}else{
throw new Error("选择了意外 gender 值 !")
}
}
},
methods:{
setGender(string){
this.selectGender=string
}
},
template: `
<div>
<div>
<button @click="setGender('')">全部</button>
<button @click="setGender('male')">男</button>
<button @click="setGender('female')">女</button>
</div>
<ul>
<li v-for="(u,index) in displayUsers" :key="index">{{u.name}} - {{u.gender}}</li>
</ul>
</div>
`
}).$mount("#app");
2.watch 监听
#watch 实现撤销功能
new Vue({
data: {
n: 0,
history: [],
/* watch 会监听所有变化,手动设置watch是否监听 */
inUndoMode: false
},
watch: {
n(newValue,oldValue){
console.log(`在不在撤销模式: ${this.inUndoMode ? "yes":"no"}`)
if(!this.inUndoMode){
this.history.push({from: oldValue,to: newValue})
console.log(`n: ${this.n}`)
}
}
},
template: `
<div>
{{n}}
<hr />
<button @click="add1">+1</button>
<button @click="add2">+2</button>
<button @click="minus1">-1</button>
<button @click="minus2">-2</button>
<hr/>
<button @click="undo">撤销</button>
<hr/>
{{history}}
</div>
`,
methods: {
add1() {
this.n += 1;
},
add2() {
this.n += 2;
},
minus1() {
this.n -= 1;
},
minus2() {
this.n -= 2;
},
undo(){
const last = this.history.pop()
const oldValue = last.from
this.inUndoMode = true
this.n = oldValue
console.log(`last n: ${this.n}`)
/* watch 的回调是异步的,同级别的异步api $nextTick() 保证 this.inUndoMode = false 在 this.n = oldValue 执行后执行*/
this.$nextTick(()=>{
this.inUndoMode = false
},0)
}
}
}).$mount("#app");
#使用 watch 模拟 computed 展示用户信息
new Vue({
data: {
user: {
email: "fangfang@qq.com",
nickname: "方方",
phone: "13812312312"
},
displayName: ""
},
watch: {
"user.email":{
/* 处理器 */
handler: "changed",
/* 第一次渲染也触发 watch */
immediate: true
},
"user.nickname":{
handler: "changed",
immediate: true
},
"user.phone":{
handler: "changed",
immediate: true
},
},
// 不如用 computed 来计算 displayName
template: `
<div>
{{displayName}}
<button @click="user.nickname=undefined">remove nickname</button>
</div>
`,
methods: {
changed(){
console.log(arguments)
const {user: {email,nickname,phone}} = this
this.displayName = nickname || email || phone
}
}
}).$mount("#app");
## computed & watch: 都是在数据出现变化时,执行一个函数
## computed 着重于依赖之间变化以及缓存
## watch 着重于数据变化时执行什么,而不是得出结果
#watch(监听器)判断数据是否变化: [ === 判断规则]
#简单类型value值变化,复杂类型(对象Object)地址变化
new Vue({
data: {
n: 0,
obj: {
a: "a",
b: "b",
}
},
template: `
<div>
<div>
{{ n }}
{{ obj }}
</div>
<button @click="n += 1">n+1</button>
<button @click="obj.a += 'hi'">obj.a + 'hi'</button>
<button @click="obj = {a:'a',b:'b'}">obj = 新对象</button>
</div>
`,
watch: {
/* [watch监听变化] 简单类型值变了就认为变化 */
n() {
console.log("n 变了");
},
/* [复杂类型] 对象地址变化才认为变化 */
obj() {
console.log("obj 变了");
console.log(this.obj)
},
/* [复杂类型] obj.a对象中的值依旧是简单类型,值变化就变化;但对象不变化(地址没有改变) */
"obj.a": function() {
console.log("obj.a 变了");
console.log(this.obj)
},
"obj.b": function() {
console.log("obj.b 变了");
}
/* deep: true 无论嵌套多深,有值 property 改变,对象监听为变化 */
/*
* obj: {
* handler(){
* console.log("obj 变了");
* },
* deep: true
* },
* */
}
}).$mount("#app");