目录
副作用(Side Effect)
纯粹计算背后的效果【我们做UI时非常需要】
副作用的封装(伪代码)
副作用失效(Invalidate)问题
API:WatchEffect
Coding:WatchEffect【演示代码】
/src/examples/WatchExamplese.tsx【watchEffect】
API:Watch
Coding:Watch
/src/examples/WatchExamplese.tsx【watch】
小结
function SomeComponent(a, b) {
window.location.href = '...' // 副作用
const c = ref(0) // 副作用
watchEffect(..) // 副作用
return {a+b+c.value}
}
根据数据变化,触发副作用
function HomePage {
watch(activeKey, () => {
history.repace(...)
})
return () => {
return ...
}
}
const currentIndex = ref("")
// 点击打开A
currentIndex.value = "A"
// 点击打开B
currentIndex.value = "B"
// A还没打开,就继续执行打开B,这时候就是A副作用失效
import { ref, defineComponent, watchEffect, onUnmounted } from 'vue'
export const WatchExample01 = defineComponent({
setup() {
// 常规用法
const count = ref(0)
// effect (效果)?? --副作用(side effect)
// 提供副作用,封装副作用,也在依赖副作用,会先执行一次,收集依赖
watchEffect(() => { // 副作用中用到了,才能追踪到
// watchEffect的依赖收集
console.log('im running...') // 单写打印,不会执行,因为没有依赖副作用,追踪不到
// console.log('im running...', count.value) // 会执行,因为有依赖
document.title = "count:" + count.value // 会执行,因为有依赖
// history.replaceState({}, "", "/count/" + count.value)
})
return () => {
return
{count.value}
}
}
})
export const WatchExample02 = defineComponent({
setup() {
// 执行时机
const count = ref(0)
// effect (效果)?? --副作用(side effect)
// 提供副作用,封装副作用,也在依赖副作用,会先执行一次,收集依赖
watchEffect(() => { // 副作用中用到了,才能追踪到
console.log('im running...') // 单写打印,不会执行,因为没有依赖副作用,追踪不到
// console.log('im running...', count.value) // 会执行,因为有依赖
// document.title = "count:" + count.value // 会执行,因为有依赖
// history.replaceState({}, "", "/count/" + count.value)
}, {
flush: "sync" // post 后于render执行; pre 先于render执行; sync先于render执行
})
// 执行时间线 sync【同步依赖变化第一时间执行】
// ... tick【vue闲时执行】 ... pre ... render ... post
return () => {
console.log('render...')
return
{count.value}
}
}
})
export const WatchExample03 = defineComponent({
setup() {
// 副作用失效问题
const count = ref(0)
// effect (效果)?? --副作用(side effect)
// 提供副作用,封装副作用,也在依赖副作用,会先执行一次,收集依赖
watchEffect((onInvalidate) => { // 副作用中用到了,才能追踪到
console.log(count.value)
let I = setInterval(() => {
count.value++
}, 1000)
// onInvalidate第二次执行时会清除前一次的I,关于副作用失效的问题
onInvalidate(() => {// 如果没有它的话,会越来越快
clearInterval(I)
})
// console.log('im running...') // 单写打印,不会执行,因为没有依赖副作用,追踪不到
})
// 执行时间线 sync【同步依赖变化第一时间执行】 ... tick【vue闲时执行】 ... pre ... render ... post
return () => {
return
{count.value}
}
}
})
export const WatchExample04 = defineComponent({
setup() {
// 副作用失效问题
const count = ref(0)
let I = setInterval(() => {
count.value++
}, 1000)
onUnmounted(() => { // 组件卸载时候执行的钩子
clearInterval(I)
})
// effect (效果)?? --副作用(side effect)
// 提供副作用,封装副作用,也在依赖副作用,会先执行一次,收集依赖
// const stop = watchEffect((onInvalidate) => { // 副作用中用到了,才能追踪到
// console.log(count.value)
// let I = setInterval(() => {
// count.value++
// }, 1000)
// // onInvalidate第二次执行时会清除前一次的I,关于副作用失效的问题
// onInvalidate(() => {// 如果没有它的话,会越来越快
// clearInterval(I)
// })
// // console.log('im running...') // 单写打印,不会执行,因为没有依赖副作用,追踪不到
// })
// stop() // 只执行一次
// 执行时间线 sync【同步依赖变化第一时间执行】 ... tick【vue闲时执行】 ... pre ... render ... post
return () => {
return
{count.value}
}
}
})
import { ref, defineComponent, watch } from 'vue'
export const WatchExample05 = defineComponent({
// 监听某个reactive值,封装副作用
setup() {
const count = ref(0)
// 指定响应式值的监听,不需要如watchEffect开始执行一次进行依赖收集
watch(count, () => {
console.log('count', count)
})
setTimeout(() => {
count.value++
}, 1000)
return () =>
{count.value}
}
})
export const WatchExample06 = defineComponent({
setup() {
const a = ref(0)
const b = ref(0)
// const c = ref(a.value + b.value)
watch([a, b], (x, y) => {
// c.value = a.value + b.value // 第二种写法
// x是旧值,y是新值
console.log(x, y)
})
setInterval(() => {
a.value += 0.2
}, 500)
setInterval(() => {
b.value += 0.7
}, 500)
return () =>
{a.value + b.value}
{/* {c.value} */}
}
})
export const WatchExample07 = defineComponent({
// 监听属性变化。依赖问题
setup() {
const greetings = ref("hello")
setTimeout(() => {
greetings.value = "world!"
}, 1000)
return () => {
return
}
}
})
// const Item = ({ text }: {
// text: string
// }) => {
// return {text}
// }
// 需要text变化时进行计算
const Item = defineComponent({
props: {
text: {
type: String
}
},
setup(props) {
// 子组件监听属性变化
// const textRef = ref(props.text)
// watch(textRef, ()=>{不执行,setup只执行一次})
// let x = 1
// watch(()=> x, ()=>{不触发,不是响应式值,vue不知道怎么触发})
watch(() => props.text, (to, from) => {
console.log("prop changed to", to, "old value is", from)
})
// setTimeout(() => {
// x = 2
// }, 1000)
return () => {
return {props.text}
}
}
})
export const WatchExample08 = defineComponent({
// 执行时机的问题
setup() {
const c = ref(0)
watch(c, () => { // 存在调度时间,会延迟一个周期执行
console.log("herep---------")
}, {
"immediate": true // 通常不会设置
// 设置为true,表示c变化之后,马上执行,例如c是某个事件的开关
})
return () => {
return {
c.value++
}}>
{c.value}
}
}
})