vue - 组合式API
简单案例
此时num的值是不会被点击后更改的,因为当前 num 的值是一个 普通的数字, 不是响应式数据, 所以修改 num 不会让页面发生变化, 除非我们将 num 修改为 响应式数据
js
<template>
<h1>APP 组件 --- {{ num }}</h1>
<button @click="addNum">点击修改 num</button>
</template>
<script setup>
let num = 100;
function addNum() {
num++;
console.log("num 最新的值: ", num);
}
</script>
setup是一个语法糖, 能够帮助我们简洁的书写 组合式API, 在当前语法糖中, 你只需要引入一个组件, 这个组件被自动注册, 我们直接使用即可.
此时我们从 vue 引入了ref 方法
- ref 和 reactive 都属于递归监听,也就是数据的每一层都是响应式的,如果数据量比较大,非常消耗性能,非递归监听只会监听数据的第一层
- ref 的参数可以是基本数据类型,也可以是引用数据类型。
- ref 会把参数加工成一个响应式对象。如果使用的是基本类型响应式依赖 Object.defineProperty(),如果 ref 使用的是引用类型,底层 ref 会借助 reactive 的 proxy 定义响应式。
js
<template>
<h1>我是APP组件</h1>
<h3>{{ num }}</h3>
<button @click="setNum">点击修改 num</button>
</template>
<script setup>
import { ref, } from 'vue'
let num = ref(100)
function setNum() {
num.value++
console.log(num.value)
}
</script>
引入了reactive
reactive 的参数必须是一个对象,包括 json 数据和数组都可以,否则不具有响应式.
- 如果给 reactive 传递了其他对象(如时间对象),默认情况下修改对象界面不会自动更新,如果想更新,可以通过给对象重新赋值来解决。
js
<template>
<h1>我是APP组件</h1>
<ul>
<li>{{ info.id }}</li>
<li>{{ info.name }}</li>
<li>{{ info.price }}</li>
</ul>
</template>
<script setup>
import { reactive } from 'vue'
const info = reactive({
id: 1111,
name: '张三',
price: 100,
number: 1
})
</script>
shallowRef, shallowReactive 方法
- 能够帮助我们创建一个响应式数据, 但是只有第一层数据有响应式, 深层数据没有响应式
- 除此之外, 用法上和 ref/reactive 完全相同
- 总结: ref 和 reactive 定义的数据每一层都是响应式数据,使用 shallowRef 和 shallowReactive 后只有第一层数据具备响应式。语法和 ref 和 reactive 一致
js
<template>
<h1>我是APP组件</h1>
<h4>info.name{{ info.name }}</h4>
<button @click="setInfoName">改名</button>
<hr>
<h4>obj.title{{ obj.title }}</h4>
<button @click="setObjTitle">改名</button>
<hr>
<h4>obj.title{{ obj.info.id }}</h4>
<button @click="setObjId">改名</button>
</template>
<script setup>
import { shallowRef, shallowReactive } from 'vue'
const info = shallowRef({
id: 'nihao',
name: '张三',
})
function setInfoName() {
// 此时修改不了页面上的数据
info.value.name = '李四'
}
const obj = shallowReactive({
title: '苹果',
info: {
id: 1,
price:100,
}
})
function setObjTitle() {
// 可以修改页面的数据
obj.title = '香蕉'
}
function setObjId() {
// 修改不了
obj.info.id = 100
}
</script>
toRaw
- 有些时候我们不希望数据进行响应式实时更新,可以通过 toRaw 获取 ref 或 reactive 引用的原始数据,通过修改原始数据,不会造成界面的更新,只有通过修改 ref 和 reactive 包装后的数据时才会发生界面响应式变化。
markRaw
- markRaw 包装后的数据永远不会被追踪。
js
<template>
<h1>APP 组件</h1>
<ul>
<li>{{ obj.name }}</li>
</ul>
<button @click="setName">点击修改</button>
</template>
<script setup>
import { toRaw, markRaw } from 'vue'
// const info1 = {}
// const info2 = markRaw({})
const obj = toRaw({
id: 111,
name: '张三'
})
function setName() {
// 页面修改不了 但是能在控制台展现
obj.name = '神仙'
console.log(obj.name)
}
</script>
toRef
- toRef 是对定义的响应对象的某个属性进行引用
- toRef 能够帮我们拿到对象中某一属性的值, 并且将它转换为ref 对象
js
<template>
<h1>APP 组件</h1>
</template>
<script setup>
import { toRef, } from 'vue'
const obj = {
id:'1127',
name: '邵州'
}
// toRef 能够帮我们拿到对象中某一属性的值, 并且将它转换为ref 对象
const name = toRef(obj,'name')
console.log(name) //转换成ref对象 obj
console.log(name.value) // 邵州
</script>
toRefs
- 遍历对象中的所有属性,将其变为响应式数据,这是因为 toRef 只能传一个 key,toRefs 所达到的效果与 toRef 一样
- toRefs 能够将我们指定的对象内部的所有属性, 转换成 ref 对象
- 通过 toRefs 创建出来的对象, 和原本的对象之间共享一个地址
- 修改其中一个对象, 会影响另外一个对象
js
<template>
<h1>APP 组件</h1>
<h4>OBJ对象</h4>
<ul>
<li>商品ID: {{ obj.id }}</li>
<li>商品标题: {{ obj.title }}</li>
<li>商品收藏数量: {{ obj.number }}</li>
</ul>
<button @click="changeObj">点击增加number</button>
<hr>
<h4>newObj对象</h4>
<ul>
<li>商品ID: {{ newObj.id }}</li>
<li>商品标题: {{ newObj.title }}</li>
<li>商品收藏数量: {{ newObj.number }}</li>
</ul>
<button @click="changeNewObj">点击增加number</button>
</template>
<script setup>
import { toRefs, reactive } from 'vue'
const obj = reactive({
id: 1127,
number: 1,
title: '商品标题'
})
function changeObj() {
// 现在 页面会跟着自增
obj.number++
}
// toRefs 能够将我们指定的对象内部的所有属性, 转换成 ref 对象
// 通过 toRefs 创建出来的对象, 和原本的对象之间共享一个地址
// 修改其中一个对象, 会影响另外一个对象
const c = toRefs(obj)
function changeNewObj() {
// 现在页面newObj里面的number自增
// 上面的reactive obj里面的number也会跟着自增
newObj.number.value++
}
</script>
父传子 子传父 兄弟 祖孙级 在下一篇 尽情期待...