computed
现有如下场景,输入框输入字符,可以过滤如下列表,如下图,当我输入a后,得到另一个结果:
用vue3写法如下:
<template>
<div>
<input type="text" v-model="obj.mytext" />
<ul>
<li v-for="data in filterlist()" :key="data">{{ data }}</li>
</ul>
</div>
</template>
<script>
import { reactive } from "vue";
export default {
setup() {
const obj = reactive({
mytext: "",
datalist: ["aaa", "bbb", "abc", "bbb", "bcc", "add", "bcd"],
});
const filterlist = () => {
return obj.datalist.filter((item) => item.includes(obj.mytext));
};
return {
obj,
filterlist,
};
},
};
</script>
现在我们用computed在vue3里也实现这一效果,代码如下:
<template>
<div>
<input type="text" v-model="obj.mytext" />
<ul>
<li v-for="data in computedList" :key="data">{{ data }}</li>
</ul>
{{ filterlist() }} {{ filterlist() }}{{ computedList }}{{ computedList }}
</div>
</template>
<script>
import { reactive, computed } from "vue";
export default {
setup() {
const obj = reactive({
mytext: "",
datalist: ["aaa", "bbb", "abc", "bbb", "bcc", "add", "bcd"],
});
const filterlist = () => {
console.log("filterlist");
return obj.datalist.filter((item) => item.includes(obj.mytext));
};
const computedList = computed(() => {
console.log("computedList");
return obj.datalist.filter((item) => item.includes(obj.mytext));
});
return {
obj,
filterlist,
computedList,
};
},
};
</script>
页面效果如下:
我们可以看到控制台打印了两次filterlist,只打印了一次computed,
多次调用computed就能体现出它的优化性能,它会走缓存,它会把第一次执行的结果保存一份,下一次就会直接用第一次保存的结果,不会重复的执行computed里的事情。
watch
刚刚上面那个场景,输入框输入字符,可以过滤如下列表,我们还可以这样写,效果是一样的:
<template>
<div>
<input type="text" v-model="obj.mytext" @input="handleInput" />
<ul>
<li v-for="data in obj.datalist" :key="data">{{ data }}</li>
</ul>
</div>
</template>
<script>
import { reactive } from "vue";
export default {
setup() {
const obj = reactive({
mytext: "",
datalist: ["aaa", "bbb", "abc", "bbb", "bcc", "add", "bcd"],
oldlist: ["aaa", "bbb", "abc", "bbb", "bcc", "add", "bcd"],
});
const handleInput = () => {
obj.datalist = obj.oldlist.filter((item) => item.includes(obj.mytext));
};
return {
obj,
handleInput,
};
},
};
</script>
现在我们用watch监听输入框双向绑定obj.mytext的改变,然后进行过滤操作,代码如下:
<template>
<div>
<input type="text" v-model="obj.mytext" />
<ul>
<li v-for="data in obj.datalist" :key="data">{{ data }}</li>
</ul>
</div>
</template>
<script>
import { reactive, watch } from "vue";
export default {
setup() {
const obj = reactive({
mytext: "",
datalist: ["aaa", "bbb", "abc", "bbb", "bcc", "add", "bcd"],
oldlist: ["aaa", "bbb", "abc", "bbb", "bcc", "add", "bcd"],
});
watch(
() => obj.mytext,
() => {
console.log("watch");
obj.datalist = obj.oldlist.filter((item) => item.includes(obj.mytext));
}
);
return {
obj,
};
},
};
</script>
当我依次输入abc时,页面效果如下:
我们能看到打印了三次watch,说明watch监听事件执行了三次,而watch的写法值得注意的是先import引入watch,然后watch里第一个先写监听的值,第二个写回调方法的调用,即写成:
import { watch } from "vue";
export default {
setup() {
watch(
() => 监听的值,
() => {
//监听的回调方法
}
)
}
};
数据监听:watch
侦听一个或者多个数据的变化,数据变化时执行回调函数,watch的第三个参数(俩个额外参数 immediate控制立刻执行,deep开启深度侦听)
监听单个数据
1.导入watch函数
2.执行watch函数传入要侦听的响应式数据(ref对象)和回调函数
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const count = ref(0)
const setCount = ()=>{
count.value++
}
// 2. 调用watch 侦听变化
watch(count, (newValue, oldValue)=>{
console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
})
</script>
<template>
<button @click="setCount">{{ count }}</button>
</template>
侦听多个数据
侦听多个数据,第一个参数可以改写成数组的写法,得到的新旧值也是数组的形式
说明:同时侦听多个响应式数据的变化,不管哪个数据变化都需要执行回调
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const count = ref(0)
const name = ref('cp')
const setCount = ()=>{
count.value++
}
const setName = ()=>{
name.value += 'p'
}
// 2. 调用watch 侦听变化
watch([count, name], ([newCount, newName],[oldCount,oldName])=>{
console.log(`count或者name变化了`,[newCount, newName],[oldCount,oldName])
})
</script>
<template>
<button @click="setCount">{{ count }}</button>
<button @click="setName">{{ name }}</button>
</template>
immediate立即监听
第三个参数,在侦听器创建时立即触发回调,响应式数据变化之后继续执行回调
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const count = ref(0)
const setCount = ()=>{
count.value++
}
// 2. 调用watch 侦听变化
watch(count, (newValue, oldValue)=>{
console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
},{
immediate: true
})
</script>
<template>
<button @click="setCount">{{ count }}</button>
</template>
deep深度监听
第三个参数,通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const state = ref({ count: 0 })
// 2. 监听对象state
watch(state, ()=>{
console.log('数据变化了')
},{
immediate:true,
deep:true
})
const changeStateByCount = ()=>{
// 直接修改不会引发回调执行
state.value.count++
}
</script>
<template>
<button @click="changeStateByCount">{{ state.count }}</button>
</template>
1、对象更深层的值变化了,但是没有监听到
2、对象更深层的值变化了,也监听到了