其它类型的定制营销型网站,互联网广告服务经营范围,做网站建设给人销售,安徽淮北做网站的公司文章目录1、Vue3中为什么修改变量的值后#xff0c;视图不更新#xff1f;2、使用 ref 还是 reactive#xff1f;3、reactive 为什么会有响应性连接丢失情况#xff1f;4、watch的不同使用方法5、watchEffect和 watch 的区别区别1#xff1a;数据源的区别区别2#xff1a…
文章目录1、Vue3中为什么修改变量的值后视图不更新2、使用 ref 还是 reactive3、reactive 为什么会有响应性连接丢失情况4、watch的不同使用方法5、watchEffect和 watch 的区别区别1数据源的区别区别2获取新值和旧值的区别区别3惰性执行和非惰性立即执行的区别6、watchEffect和 watch 使用注意点7、使用ref修改DOM元素1、Vue3中为什么修改变量的值后视图不更新
templatedivapp/divdiv classcontainer{{ msg1 }}{{ msg2 }}/divbutton clicksay()按钮/button
/templatescript setup
import { reactive, ref } from vuelet msg1 hi
let msg2 ref(hello)
const say () {console.log(msg1) // himsg1 hi vue3 // 这里修改 msg1的值console.log(msg1, msg1) // 这里可以获取到修改后的值hi vue3但是视图中的 msg1 没有更新原因是 msg1不是响应式的。msg2.value hello vue3 // 这里修改 msg2的值console.log(msg2, msg2) // 这里可以获取到修改后的值hello vue3视图中的 msg2 也会更新原因是 msg2是响应式的。
}
/script2、使用 ref 还是 reactive
reactive 可以转换【复杂数据类型】(例如对象、数组等) 成为响应式数据但是不支持简单数据类型例如字符串、数值、布尔值ref 可以转换【简单数据类型】或【复杂数据类型】 为响应式数据但是操作的时候需要 .value。
如果能确定数据是复杂数据类型并且定义的属性也是知道的则可以使用 reactive 转成响应式数据如果不满足以上条件则使用 ref。
代码如下 // 1. 明确login对象有两个字段需要使用 reactiveconst login reactive({username: ,password: })// 2. 后台返回的数据对象const data ref(null)const res await axios.get(/login)data.value res.data // 把不是响应式的 res 赋值给 响应式data中的valuedata仍然是响应式的。// 3. 思考为什么以下方式不可行const data reactive({ })const res await axios.get(/login)data res // 由于res 不是响应式的然后把不是响应式的 res 赋值给 响应式的data 那么data就不是响应式的了。
3、reactive 为什么会有响应性连接丢失情况
响应性连接丢失的意思是一个响应式对象原本是响应式的但随意通过 “赋值”操作把一个非响应式的数据赋值给响应式的数据对象这个响应式对象就变成了非响应式数据对象了。
reactive API有两个限制性情况 情况1reactive 仅支持复杂数据类型对象、数组等对简单数据类型字符串、数值、布尔值等原始类型不支持。 情况2因为Vue 的响应式系统是通过属性访问进行跟踪的必须始终保持对该响应式对象的相同引用。所以不可以随意地“替换赋值”一个响应式对象因为这将导致对初始引用的响应性连接丢失。 也就是说如果重新赋值或解构赋值就会丢失原来响应式对象的引用地址然后变成了一个新的引用地址因为这个新的引用地址指向的对象是没有经过 reactive 处理的所以就是一个普通对象而不是响应式对象。
❌ 响应性连接丢失 代码举例1 const data reactive({ })const res await axios.get(/login)data res // 由于res 不是响应式的然后把不是响应式的 res 赋值给 响应式的data 那么data就不是响应式的了❌ 响应性连接丢失 代码举例2
// 将响应式对象的属性直接赋值或解构赋值时或是将该属性传入一个函数时也会失去响应性连接let dataCount reactive({ count: 0 })// 响应式对象的属性直接赋值时响应式对象的属性响应性连接丢失也就是说dataCount.count 失去响应式连接但不会影响 dataCount (dataCount仍然是响应式数据对象)
let num dataCount.count // 响应式对象的属性值 直接赋值给了 num
num// 响应式对象属性解构时响应式对象属性dataCount.count响应性连接丢失,但不会影响 dataCount
let { count } dataCount // 响应式对象的属性解构赋值
count// change函数接收一个普通数字,将无法跟踪 dataCount.count 的变化, dataCount.count失去响应性连接
const change (item) {console.log(item)
}
change(dataCount.count)4、watch的不同使用方法
watch 第一个参数不同形式的数据源
可以是 ref含计算属性一个getter函数一个响应式对象或多个数据源组成的数组。
注意: watch不能侦听到响应式对象的属性值比如watch(data.count,(){ })可以提供一个getter函数进行返回响应式对象的属性值。
watch 第二个参数回调函数当数据源发生变化时执行回调函数
watch 第三个参数【可选】是一个配置项
deep 用于强制深度遍历immediate 用于立即执行第二个参数中的回调函数flush 用于调整回调函数的刷新时机onTrack / onTrigger 调试侦听器的依赖
watch 的五种不同使用方法如下
templatedivapp/divdiv{{ count }}/divbutton clickcount累加/button
/templatescript setup
import { ref, reactive, watch } from vueconst count ref(0)
const obj reactive({name: xiaozhu,age: 18,info: {height: 180,weight: 70,},
})// 使用方法1第一个参数为 ref
watch(count, (newVal, oldVal) {console.log(newVal, newVal) // 累加后 新的值console.log(oldVal, oldVal) // 累加前 旧的值
})// 使用方法2第一个参数为 getter函数
watch(() obj.age,(newVal, oldVal) {console.log(newVal, newVal) // 20console.log(oldVal, oldVal) // 18}
)
setTimeout(() {obj.age 20
}, 1000)// 使用方法3第一个参数为 一个响应式对象中的 简单数据类型
watch(() obj.name, // name为obj对象中的一个字符串类型(newVal, oldVal) {console.log(改变了)console.log(obj.name, obj.name) // 筱竹console.log(newVal, newVal) // 筱竹console.log(oldVal, oldVal) // xiaozhu}
)
setTimeout(() {obj.name 筱竹
}, 1000)// 使用方法4第一个参数为 一个响应式对象中的 复杂数据类型时需要开启深度监听设置deep选项
watch(() obj.info, // info 为obj对象中的一对象类型(newVal, oldVal) {console.log(obj.info.height, obj.info.height) // 筱竹console.log(newVal, newVal) // 筱竹console.log(oldVal, oldVal) // xiaozhu},{ deep: true } // 开启深度监听
)
setTimeout(() {obj.info.height 175
}, 1000)// 使用方法5第一个参数为 多个数据源组成的数组
watch([count, obj], () {console.log(count.value, count.value) // 点击 累加按钮后count1console.log(obj.info.weight, obj.info.weight) // 65
})
setTimeout(() {obj.info.weight 65
}, 1000)
/script5、watchEffect和 watch 的区别
区别1数据源的区别
watch 是需要侦听一个数据源ref、响应式对象等当依赖数据更新时执行回调函数watchEffect 不需要设置侦听的数据源而是自动收集依赖数据当依赖数据更新时会立即执行回调函数
templatedivapp/divdiv{{ count }}/divbutton clickcount累加/button
/templatescript setup
import { ref, reactive, watch, watchEffect } from vueconst count ref(0)// watchEffect 和 watch 区别1// watchEffect 不需要设置侦听的数据源就可以自动收集依赖以下可以自动收集 ref 数据源
watchEffect(() {console.log(count.value, count.value)
})// watch 需要设置侦听的数据源只有设置了数据源才能侦听数据源的变化
watch(count, (newVal, oldVal) {console.log(newVal, newVal) console.log(oldVal, oldVal)
})
/script区别2获取新值和旧值的区别
watch 在回调函数中获取到 新值变化后的值和 旧值变化之前的值watchEffect 在回调函数中 只可以获取到新值变化后的值不能获取到 旧值变化之前的值
// watchEffect 和 watch 区别2// watchEffect 只能拿到 新值
watchEffect(() {console.log(count.value, count.value) // 只能拿到 新值
})// watch 可以获取到 新值和 旧值
watch(count, (newVal, oldVal) {console.log(newVal, newVal) // 累加后 新的值console.log(oldVal, oldVal) // 累加前 旧的值
})区别3惰性执行和非惰性立即执行的区别
watch 的回调函数具有一定的惰性 当第一次页面展示的时候不会执行只有数据变化的时候才会执行(设置immediate 选项为true时可以变为非惰性可以立即执行页面首次加载就会执行watchEffect 的回调函数可以立即执行没有惰性页面的首次加载就会执行
// watchEffect 和 watch 区别3
const todoId ref(1)
const data ref(null)// watchEffect 中的回调函数会立即执行不需要指定 immediate: true
watchEffect(async () {const response await fetch(https://jsonplaceholder.typicode.com/todos/${todoId.value})data.value await response.json()
})// 在 watch 中想要立即执行回调函数就需要 设置 immediate: true
// watch 默认是惰性的仅当数据源变化时才会执行回调。但在某些场景中我们希望在创建侦听器时立即执行一遍回调。举例来说我们想请求一些初始数据然后在相关状态更改时重新请求数据。
watch(todoId,async () {const response await fetch(https://jsonplaceholder.typicode.com/todos/${todoId.value})data.value await response.json()},{ immediate: true }
)6、watchEffect和 watch 使用注意点
【注意点1】 侦听器必须用同步语句创建如果用异步回调创建一个侦听器那么它不会绑定到当前组件上必须手动停止侦听以防止内存泄漏。例如
// 它会自动停止 watch同理
watchEffect(() {})// 这个则不会 watch同理
setTimeout(() {watchEffect(() {})
}, 100)// 要手动停止一个侦听器请调用 watch 或 watchEffect 返回的函数
const unwatch watchEffect(() {})// 当该侦听器不再需要时
unwatch()【注意点2】 需要异步创建侦听器的情况很少请尽可能选择同步创建如果需要等待一些异步数据你可以使用条件式的侦听逻辑
// 需要异步请求得到的数据
const info ref(null)watchEffect(() {if (info.value) {// 数据加载后执行某些操作...}
})7、使用ref修改DOM元素
templatediv refref_itemapp/divinput typebutton value修改DOM元素 clickchange() /
/templatescript setup
import { ref, onMounted } from vueconst ref_item ref(null)// 注意 获取元素需要在Vue3 生命周期钩子 onMounted中获取如果在 setup 中是获取不到的因为setup中类似Vue2声明周期钩子函数中的beforeCreate和 created 此时DOM还没生成所以获取不到DOM。
onMounted(() {// 获取DOM元素console.log(ref_item.value.innerText, ref_item.value.innerText) // app
})const change () {// 修改DOM元素的值ref_item.value.innerText 你好 Vue3console.log(ref_item.value.innerText, ref_item.value.innerText) // 你好 Vue3
}
/script