Composition API的计算属性computed
传统的计算属性不做介绍。
如下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>lesson 38</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// computed 计算属性
const app = Vue.createApp({
setup() {
const { ref } = Vue;
const count = ref(0);
const handleClick = () => {
count.value += 1;
};
return { count,handleClick };
},
template: `
<div>
<span @click="handleClick">{{count}}</span>
</div>
`
});
const vm = app.mount('#root');
</script>
</html>
最基础的计数器。
设计另一个数据,在第一个计数器的基础上加5:
<script>
// computed 计算属性
const app = Vue.createApp({
setup() {
const { ref } = Vue;
const count = ref(0);
const handleClick = () => {
count.value += 1;
};
//computed接受一个回调
//计算一个加5的方法
let countAddFive = computed(() => {
return count.value+5;
});
return { count, handleClick ,countAddFive};
},
template: `
<div>
<span @click="handleClick">{{count}}</span> -- {{countAddFive}}
</div>
`
});
const vm = app.mount('#root');
</script>
这就是计算属性在 Composition API中的使用方法。
计算属性也可写成更复杂的内容:
<script>
// computed 计算属性
const app = Vue.createApp({
setup() {
const { ref } = Vue;
const count = ref(0);
const handleClick = () => {
count.value += 1;
};
//computed接受一个回调
//计算一个加5的方法
let countAddFive = computed(() => {
get: () => {
return count.value + 5;
},
});
return { count, handleClick ,countAddFive};
},
template: `
<div>
<span @click="handleClick">{{count}}</span> -- {{countAddFive}}
</div>
`
});
const vm = app.mount('#root');
</script>
这个效果等同于上面的简写方法。
<script>
// computed 计算属性
const app = Vue.createApp({
setup() {
const { ref } = Vue;
const count = ref(0);
const handleClick = () => {
count.value += 1;
};
//computed接受一个回调
//计算一个加5的方法
let countAddFive = computed(() => {
get: () => {
return count.value + 5;
},
set: () => {
count.value = 10;
}
});
setTimeout(() => {
//之所以要.value是因为其是被ref包裹的
countAddFive.value = 100;//当去修改的时候,会走set函数
}, 3000)
return { count, handleClick ,countAddFive};
},
template: `
<div>
<span @click="handleClick">{{count}}</span> -- {{countAddFive}}
</div>
`
});
const vm = app.mount('#root');
</script>
3秒时候会修改count的值,由由于计算属性去读值会调用get方法,所以3秒之后会变为10--15
。
如果想要countAddFive
的参数真正发挥作用,可以如下修改代码:
<script>
// computed 计算属性
const app = Vue.createApp({
setup() {
const { ref } = Vue;
const count = ref(0);
const handleClick = () => {
count.value += 1;
};
//computed接受一个回调
//计算一个加5的方法
let countAddFive = computed(() => {
get: () => {
return count.value + 5;
},
set: (param) => {
count.value = param - 5;
}
});
setTimeout(() => {
//之所以要.value是因为其是被ref包裹的
countAddFive.value = 100;//当去修改的时候,会走set函数
}, 3000)
return { count, handleClick ,countAddFive};
},
template: `
<div>
<span @click="handleClick">{{count}}</span> -- {{countAddFive}}
</div>
`
});
const vm = app.mount('#root');
</script>
当然,以上可以再复杂一些:
<script>
// computed 计算属性
const app = Vue.createApp({
setup() {
const { reactive, computed } = Vue;
const countObj = reactive({ count: 0});
const handleClick = () => {
countObj.count += 1;
}
let countAddFive = computed({
get: () => {
return countObj.count + 5;
},
set: (param) => {
countObj.count = param - 5;
}
})
setTimeout(() => {
countAddFive.value = 100;
}, 3000)
return { countObj, countAddFive, handleClick }
},
template: `
<div>
<span @click="handleClick">{{countObj.count}}</span> -- {{countAddFive}}
</div>
`,
});
const vm = app.mount('#root');
</script>
监听器watch
初始代码如下:
<script>
// watch 侦听器
// watchEffect 侦听器,偏向于 effect
const app = Vue.createApp({
setup() {
const { ref } = Vue;
const name = ref('dell',);
return { name };
},
template: `
<div>
<div>
Name: <input v-model="name">
</div>
<div>
Name is {{name}}
</div>
</div>
`
});
const vm = app.mount('#root');
</script>
上面的输入框内容变化,下面的显示内容也会跟着变。
这里我们用watch实现:
<script>
// watch 侦听器
// watchEffect 侦听器,偏向于 effect
const app = Vue.createApp({
setup() {
const { ref, watch } = Vue;
const name = ref('dell');
// 具备一定的惰性 lazy
// 回调函数的参数可以拿到原始和当前值
// 可以侦听多个数据的变化,用一个侦听器承载
watch(name, (newValue,oldValue) => {});
return { name };
},
template: `
<div>
<div>
Name: <input v-model="name">
</div>
<div>
Name is {{name}}
</div>
</div>
`
});
const vm = app.mount('#root');
</script>
为了达到接下来的演示目的,现在把基础数据类型变为对象:
<script>
// watch 侦听器
// watchEffect 侦听器,偏向于 effect
const app = Vue.createApp({
setup() {
const { reactive, watch, toRefs } = Vue;
const nameObj = reactive({
name: 'dell'
});
// 具备一定的惰性 lazy
// 回调函数的参数可以拿到原始和当前值
// 可以侦听多个数据的变化,用一个侦听器承载
//监听一个对象的某一个属性,需要将参数变成一个函数
watch(()=>nameObj.name, (newValue, oldValue) => {});
const { name } = toRefs(nameObj);
return { name };
},
template: `
<div>
<div>
Name: <input v-model="name">
</div>
<div>
Name is {{name}}
</div>
</div>
`
});
const vm = app.mount('#root');
</script>
修改代码:
<script>
// watch 侦听器
// watchEffect 侦听器,偏向于 effect
const app = Vue.createApp({
setup() {
const { reactive, watch, toRefs } = Vue;
const nameObj = reactive({
name: 'dell',
englishName: 'lee'
});
// 具备一定的惰性 lazy
// 回调函数的参数可以拿到原始和当前值
// 可以侦听多个数据的变化,用一个侦听器承载
//监听一个对象的某一个属性,需要将参数变成一个函数
watch(
[
() => nameObj.name,
() => nameObj.englishName
],
([newName, newEng],
[oldName, oldEng]) => {
console.log('watch', curName, prevName, '---', curEng, preEng);
});
const { name } = toRefs(nameObj);
return { name };
},
template: `
<div>
<div>
Name: <input v-model="name">
</div>
<div>
Name is {{name}}
</div>
<div>
EnglishName: <input v-model="englishName">
</div>
<div>
EnglishName is {{englishName}}
</div>
</div>
`
});
const vm = app.mount('#root');
</script>
以上就是多参数监听。
![](http://upload-images.jianshu.io/upload_images/16102290-b6d616e9f38240b7.png)
image.png
watchEffect
watchEffect语法和watch一样。watchEffect写法没有watch那么麻烦,只需要写一个回调函数即可。
<script>
// watch 侦听器
// watchEffect 侦听器,偏向于 effect
const app = Vue.createApp({
setup() {
const { reactive, watch, toRefs ,watchEffect} = Vue;
const nameObj = reactive({
name: 'dell',
englishName: 'lee'
});
//watchEffect是立即执行的,没有惰性。immediate
//watchEffect会自动检测内部的代码
watchEffect(()=>{
console.log('aaa');
})
const { name } = toRefs(nameObj);
return { name };
},
template: `
<div>
<div>
Name: <input v-model="name">
</div>
<div>
Name is {{name}}
</div>
<div>
EnglishName: <input v-model="englishName">
</div>
<div>
EnglishName is {{englishName}}
</div>
</div>
`
});
const vm = app.mount('#root');
</script>
以上代码aaa只会执行一次,但是修改如下之后,每次修改都会执行。
......
watchEffect(()=>{
console.log('watchEffect', curName, prevName, '---', curEng, preEng);
})
......
- watchEffect是立即执行的,没有惰性。immediate
- watchEffect会自动检测内部的代码,不需要传递任何需要监听的内容
- watchEffect无法获取旧的值,只能获取最新的值
接下来写一个功能:2秒之后监听器取消,不再监听:
<script>
// watch 侦听器
// watchEffect 侦听器,偏向于 effect
const app = Vue.createApp({
setup() {
const { reactive, watch, toRefs ,watchEffect} = Vue;
const nameObj = reactive({
name: 'dell',
englishName: 'lee'
});
// 具备一定的惰性 lazy
// 回调函数的参数可以拿到原始和当前值
// 可以侦听多个数据的变化,用一个侦听器承载
//监听一个对象的某一个属性,需要将参数变成一个函数
// watch(
// [
// () => nameObj.name,
// () => nameObj.englishName
// ],
// ([newName, newEng],
// [oldName, oldEng]) => {
// console.log('watch', curName, prevName, '---', curEng, preEng);
//watchEffect是立即执行的,没有惰性。immediate
//watchEffect会自动检测内部的代码,不需要传递任何需要监听的内容
//watchEffect无法获取旧的值,只能获取最新的值
const stop = watchEffect(() => {
console.log(nameObj.name);
console.log(nameObj.englishName);
setTimeout(() => {
stop();
}, 5000)
})
const { name } = toRefs(nameObj);
return { name };
},
template: `
<div>
<div>
Name: <input v-model="name">
</div>
<div>
Name is {{name}}
</div>
<div>
EnglishName: <input v-model="englishName">
</div>
<div>
EnglishName is {{englishName}}
</div>
</div>
`
});
const vm = app.mount('#root');
</script>
watch也有这样的使用方法。
有没有办法把watch变成非惰性的?可以:
......
// 具备一定的惰性 lazy
// 回调函数的参数可以拿到原始和当前值
// 可以侦听多个数据的变化,用一个侦听器承载
//监听一个对象的某一个属性,需要将参数变成一个函数
watch(
[
() => nameObj.name,
() => nameObj.englishName
],
([newName, newEng],
[oldName, oldEng]) => {
console.log('watch', curName, prevName, '---', curEng, preEng);
},{
//这里可以传很多高级的配置
immediate: true //非惰性:立即执行
});
......