VUE3 Composition API

1. Composition API(常用部分)

文檔:

https://vue3js.cn/docs/zh/

setup

  • 新的option, 所有的組合API函數(shù)都在此使用, 只在初始化時(shí)執(zhí)行一次
  • 函數(shù)如果返回對(duì)象, 對(duì)象中的屬性或方法, 模板中可以直接使用

ref

  • 作用: 定義一個(gè)數(shù)據(jù)的響應(yīng)式
  • 語(yǔ)法: const xxx = ref(initValue):
    • 創(chuàng)建一個(gè)包含響應(yīng)式數(shù)據(jù)的引用(reference)對(duì)象
    • js中操作數(shù)據(jù): xxx.value
    • 模板中操作數(shù)據(jù): 不需要.value
  • 一般用來(lái)定義一個(gè)基本類型的響應(yīng)式數(shù)據(jù)
<template>
  <h2>{{count}}</h2>
  <hr>
  <button @click="update">更新</button>
</template>

<script>
import {
  ref
} from 'vue'
export default {

  /* 在Vue3中依然可以使用data和methods配置, 但建議使用其新語(yǔ)法實(shí)現(xiàn) */
  // data () {
  //   return {
  //     count: 0
  //   }
  // },
  // methods: {
  //   update () {
  //     this.count++
  //   }
  // }

  /* 使用vue3的composition API */
  setup () {

    // 定義響應(yīng)式數(shù)據(jù) ref對(duì)象
    const count = ref(1)
    console.log(count)

    // 更新響應(yīng)式數(shù)據(jù)的函數(shù)
    function update () {
      // alert('update')
      count.value = count.value + 1
    }

    return {
      count,
      update
    }
  }
}
</script>

3) reactive

  • 作用: 定義多個(gè)數(shù)據(jù)的響應(yīng)式
  • const proxy = reactive(obj): 接收一個(gè)普通對(duì)象然后返回該普通對(duì)象的響應(yīng)式代理器對(duì)象
  • 響應(yīng)式轉(zhuǎn)換是“深層的”:會(huì)影響對(duì)象內(nèi)部所有嵌套的屬性
  • 內(nèi)部基于 ES6 的 Proxy 實(shí)現(xiàn),通過(guò)代理對(duì)象操作源對(duì)象內(nèi)部數(shù)據(jù)都是響應(yīng)式的
<template>
  <h2>name: {{state.name}}</h2>
  <h2>age: {{state.age}}</h2>
  <h2>wife: {{state.wife}}</h2>
  <hr>
  <button @click="update">更新</button>
</template>

<script>
/* 
reactive: 
    作用: 定義多個(gè)數(shù)據(jù)的響應(yīng)式
    const proxy = reactive(obj): 接收一個(gè)普通對(duì)象然后返回該普通對(duì)象的響應(yīng)式代理器對(duì)象
    響應(yīng)式轉(zhuǎn)換是“深層的”:會(huì)影響對(duì)象內(nèi)部所有嵌套的屬性
    內(nèi)部基于 ES6 的 Proxy 實(shí)現(xiàn),通過(guò)代理對(duì)象操作源對(duì)象內(nèi)部數(shù)據(jù)都是響應(yīng)式的
*/
import {
  reactive,
} from 'vue'
export default {
  setup () {
    /* 
    定義響應(yīng)式數(shù)據(jù)對(duì)象
    */
    const state = reactive({
      name: 'tom',
      age: 25,
      wife: {
        name: 'marry',
        age: 22
      },
    })
    console.log(state, state.wife)

    const update = () => {
      state.name += '--'
      state.age += 1
      state.wife.name += '++'
      state.wife.age += 2
    }

    return {
      state,
      update,
    }
  }
}
</script>

shallowRef and shallowReactive

shallowReactive : 只處理了對(duì)象內(nèi)最外層屬性的響應(yīng)式(也就是淺響應(yīng)式)

shallowRef: 只處理了value的響應(yīng)式, 不進(jìn)行對(duì)象的reactive處理

什么時(shí)候用淺響應(yīng)式呢?

一般情況下使用ref和reactive即可
如果有一個(gè)對(duì)象數(shù)據(jù), 結(jié)構(gòu)比較深, 但變化時(shí)只是外層屬性變化 ===> shallowReactive
如果有一個(gè)對(duì)象數(shù)據(jù), 后面會(huì)產(chǎn)生新的對(duì)象來(lái)替換 ===> shallowRef

<template>
  <div>
    <div>
      <p>{{ counter.name }}</p>
      <button @click="handleCounter">add</button>
    </div>
    <div>
      <p>{{ user.name }}</p>
      <p>{{ user.age }}</p>
      <p>{{ user.hobby }}</p>
      <p>{{ user.child.value }}</p>
      <button @click="updateUser">update</button>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, shallowReactive, shallowRef } from 'vue';

export default defineComponent({
  setup() {
    // const counter = shallowRef(0);
    const counter = shallowRef({
      name: 'wanglizhi'
    });
    const user = shallowReactive({
      name: 'wanglizhi',
      age: 18,
      child: {
        id: 1,
        value: '11',
      },
      hobby: ['唱歌', '跳舞'],
    });

    function handleCounter() {
      counter.value.name = 'Leo';
      console.log(counter)
    }

    function updateUser() {
      // user.name = 'Leo';
      // user.age = 20;
      user.hobby[0] = '吃飯';
      user.child.value = '222';
      console.log(user)
    }

    return {
      counter,
      user,
      handleCounter,
      updateUser,
    };
  },
});
</script>

<style></style>

readonly and shallowReadonly

readonly:
深度只讀數(shù)據(jù)
獲取一個(gè)對(duì)象 (響應(yīng)式或純對(duì)象) 或 ref 并返回原始代理的只讀代理。
只讀代理是深層的:訪問(wèn)的任何嵌套 property 也是只讀的。
shallowReadonly
淺只讀數(shù)據(jù)
創(chuàng)建一個(gè)代理,使其自身的 property 為只讀,但不執(zhí)行嵌套對(duì)象的深度只讀轉(zhuǎn)換
應(yīng)用場(chǎng)景:
在某些特定情況下, 我們可能不希望對(duì)數(shù)據(jù)進(jìn)行更新的操作, 那就可以包裝生成一個(gè)只讀代理對(duì)象來(lái)讀取數(shù)據(jù), 而不能修改或刪除

<template>
  <div>
    <div>
      <p>{{ JSON.stringify(state) }}</p>
      <button @click="update">update</button>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, readonly, shallowReadonly } from 'vue';

export default defineComponent({
  setup() {
    const state = shallowReadonly({
      name: 'wanglizhi',
      age: 18,
      child: {
        name: 'xiaowang',
        age: 10,
        child: {
          name: 'wang',
          age: 1
        }
      }
    })

    function update() {
      state.name = 'Leo';
      state.child.name = 'Leo1';
      state.child.child.name = 'Leo2';
      console.log(state)
    }
    return {
      state,
      update,
    };
  },
});
</script>

<style></style>

toRaw and markRaw

toRaw
返回由 reactive 或 readonly 方法轉(zhuǎn)換成響應(yīng)式代理的普通對(duì)象。
這是一個(gè)還原方法,可用于臨時(shí)讀取,訪問(wèn)不會(huì)被代理/跟蹤,寫入時(shí)也不會(huì)觸發(fā)界面更新。
markRaw
標(biāo)記一個(gè)對(duì)象,使其永遠(yuǎn)不會(huì)轉(zhuǎn)換為代理。返回對(duì)象本身
應(yīng)用場(chǎng)景:
有些值不應(yīng)被設(shè)置為響應(yīng)式的,例如復(fù)雜的第三方類實(shí)例或 Vue 組件對(duì)象。
當(dāng)渲染具有不可變數(shù)據(jù)源的大列表時(shí),跳過(guò)代理轉(zhuǎn)換可以提高性能。

<template>
  <div>
    <h2>toRaw and markRow</h2>
    <div>
      <p>{{ JSON.stringify(state) }}</p>
      <button @click="update">update</button>
    </div>
    <hr>
  </div>
</template>

<script lang="ts">
import { defineComponent, toRaw, markRaw, reactive } from 'vue';

export default defineComponent({
  setup() {
    const obj = {
      name: 'wanglizhi',
      age: 18,
      child: {
        name: 'xiaowang',
        age: 10,
        child: {
          name: 'wang',
          age: 1,
        },
      },
    };
    const obj3 = markRaw(obj);
    const state = reactive(obj3);
    const obj2 = toRaw(state);

    function update() {
      state.name = 'Leo';
      state.child.name = 'Leo1';
      state.child.child.name = 'Leo2';
      console.log('obj', obj);
      console.log('state', state);
      console.log('obj2', obj2);
      console.log(obj === state)
         console.log(obj2 === obj2)
    }
    return {
      state,
      update,
    };
  },
});
</script>

<style></style>

toRef 、toRefs、 isRef and unref

toRef
為源響應(yīng)式對(duì)象上的某個(gè)屬性創(chuàng)建一個(gè) ref對(duì)象, 二者內(nèi)部操作的是同一個(gè)數(shù)據(jù)值, 更新時(shí)二者是同步的
區(qū)別ref: 拷貝了一份新的數(shù)據(jù)值單獨(dú)操作, 更新時(shí)相互不影響
應(yīng)用: 當(dāng)要將 某個(gè)prop 的 ref 傳遞給復(fù)合函數(shù)時(shí),toRef 很有用
toRefs
將響應(yīng)式對(duì)象轉(zhuǎn)換為普通對(duì)象,其中結(jié)果對(duì)象的每個(gè) property 都是指向原始對(duì)象相應(yīng) property 的ref
isRef
判斷是否為ref
unref
如果參數(shù)為 ref,則返回內(nèi)部值,否則返回參數(shù)本身。這是 val = isRef(val) ? val.value : val。

<template>
  <div>
    <h2>toRef and toRefs</h2>
    <div>
      <p>{{ JSON.stringify(state) }}</p>
      <button @click="update">update</button>
    </div>
    <hr>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, toRef, toRefs, isRef, unref } from 'vue';

export default defineComponent({
  setup() {
    const obj = {
      name: 'wanglizhi',
      age: 18,
      child: {
        name: 'xiaowang',
        age: 10,
        child: {
          name: 'wang',
          age: 1,
        },
      },
    };
    const state = reactive(obj);
    const obj2 = toRef(state, 'name');
    const obj3 = toRefs(state)

    function update() {
      // state.name = 'Leo';
      // state.child.name = 'Leo1';
      // state.child.child.name = 'Leo2';
      // obj2.value = 'haha'
      obj3.name.value = 'hehe'
      console.log('obj', obj);
      console.log('state', state);
      console.log('obj2', obj2);
      console.log('obj3', obj3);
      console.log(isRef(state))
      // console.log(isRef(obj2))
      // console.log(isRef(obj3))
      // console.log(isRef(obj3.name))
      // console.log(unref(state))
      // console.log(unref(obj2))
    }
    return {
      state,
      update,
    };
  },
});
</script>

<style></style>

customRef

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容