Vue组合式API:解锁更灵活的组件逻辑

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>

父传子 子传父 兄弟 祖孙级 在下一篇 尽情期待...

相关推荐
Amd794几秒前
Nuxt.js 应用中的 webpack:compiled 事件钩子
前端·webpack·开发·编译·nuxt.js·事件·钩子
生椰拿铁You9 分钟前
09 —— Webpack搭建开发环境
前端·webpack·node.js
狸克先生20 分钟前
如何用AI写小说(二):Gradio 超简单的网页前端交互
前端·人工智能·chatgpt·交互
sinat_3842410923 分钟前
在有网络连接的机器上打包 electron 及其依赖项,在没有网络连接的机器上安装这些离线包
javascript·arcgis·electron
baiduopenmap35 分钟前
百度世界2024精选公开课:基于地图智能体的导航出行AI应用创新实践
前端·人工智能·百度地图
loooseFish42 分钟前
小程序webview我爱死你了 小程序webview和H5通讯
前端
小牛itbull1 小时前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
菜牙买菜1 小时前
让安卓也能玩出Element-Plus的表格效果
前端
请叫我欧皇i1 小时前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
533_1 小时前
[vue] 深拷贝 lodash cloneDeep
前端·javascript·vue.js