溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Vue3中怎么使用CompositionAPI解決問題

發(fā)布時間:2022-08-31 09:33:30 來源:億速云 閱讀:155 作者:iii 欄目:編程語言

這篇文章主要介紹“Vue3中怎么使用CompositionAPI解決問題”,在日常操作中,相信很多人在Vue3中怎么使用CompositionAPI解決問題問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Vue3中怎么使用CompositionAPI解決問題”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

一、為什么選擇CompositionAPI

Vue2的局限性

  • 組件邏輯膨脹導(dǎo)致的可讀性變差

  • 無法跨組件重用代碼

  • Vue2對TS的支持有限

在傳統(tǒng)的OptionsAPI中我們需要將邏輯分散到以下六個部分。

OptionsAPI

  • components

  • props

  • data

  • computed

  • methods

  • lifecycle methods

如何使用CompositionAPI解決問題

最佳的解決方法是將邏輯聚合就可以很好的代碼可讀性。

這就是我們的CompositionAPI語法能夠?qū)崿F(xiàn)的功能。CompositionAPI是一個完全可選的語法與原來的OptionAPI并沒有沖突之處。他可以讓我們將相同功能的代碼組織在一起,而不需要散落到optionsAPI的各個角落

代碼重用方法PK

Vue2中的跨組件重用代碼,我們大概會有四個選擇

1、Mixin - 混入

Vue3中怎么使用CompositionAPI解決問題

  • 代碼混入其實(shí)就是設(shè)計(jì)模式中的混合模式,缺點(diǎn)也非常明顯。

  • 可以理解為多重繼承,簡單的說就是一個人如何有兩個父親

缺點(diǎn)

  • 無法避免屬性名沖突

  • 繼承關(guān)系不清晰

2、Mixin Factory - 混入工廠

返回一個

Vue3中怎么使用CompositionAPI解決問題

?代碼重用方便

?繼承關(guān)系清洗

3、ScopeSlots - 作用域插槽

?可讀性不高

?配置復(fù)雜 - 需要再模板中進(jìn)行配置

?性能低 - 每個插槽相當(dāng)于一個實(shí)例

4、CompositionApi - 復(fù)合API

Vue3中怎么使用CompositionAPI解決問題

?代碼量少

?沒有引入新的語法,只是單純函數(shù)

?異常靈活

?工具語法提示友好 - 因?yàn)槭菃渭兒瘮?shù)所以 很容易實(shí)現(xiàn)語法提示、自動補(bǔ)償

二、setup & ref

使用CompositionAPI理由

?更好的Typescript支持

?在復(fù)雜功能組件中可以實(shí)現(xiàn)根據(jù)特性組織代碼 - 代碼內(nèi)聚性, 比如:
排序和搜索邏輯內(nèi)聚

?組件間代碼復(fù)用

setup是什么

  • 在以下方法前執(zhí)行:

    • Components

    • Props

    • Data

    • Methods

    • Computed Properties

    • Lifecycle methods

  • 可以不在使用難于理解的this

  • 有兩個可選參數(shù)

    • props - 屬性 (響應(yīng)式對象 且 可以監(jiān)聽(watch))

import {watch} from "vue"
export defalut {
	props: {
		name: String
	},
	setup(props) {
		watch(() => {
			console.log(props.name)
		})
	}
}
  • context 上下文對象 - 用于代替以前的this方法可以訪問的屬性

setup (props,context) {
	const {attrs,slots,parent,root,emit} = context
}

ref是什么

對基本數(shù)據(jù)類型數(shù)據(jù)進(jìn)行裝箱操作使得成為一個響應(yīng)式對象,可以跟蹤數(shù)據(jù)變化。

總結(jié)

Vue3中怎么使用CompositionAPI解決問題

可維護(hù)性明顯提高

  • 可以控制哪些變量暴露

  • 可以跟中哪些屬性被定義 (屬性繼承與引用透明)

三、Methods

基礎(chǔ)用法

Vue3中怎么使用CompositionAPI解決問題

自動拆裝箱總結(jié)

Vue3中怎么使用CompositionAPI解決問題

  • JS :需要通過.value訪問包裝對象

  • 模板: 自動拆箱

四、 Computed - 計(jì)算屬性

這個地方實(shí)在沒什么好講的,和Vue2沒變化

<template>
  <div>
    <div>Capacity: {{ capacity }}</div>
    <p>Spases Left: {{ sapcesLeft }} out of {{ capacity }}</p>
    <button @click="increaseCapacity()">Increase Capacity</button>
  </div>
</template>

<script>

import { ref, computed, watch } from "vue";
export default {
  setup(props, context) {
    const capacity = ref(3);
    const attending = ref(["Tim", "Bob", "Joe"]);
    function increaseCapacity() {
      capacity.value++;
    }
    const sapcesLeft = computed(() => {
      return capacity.value - attending.value.length;
    });
    return { capacity, increaseCapacity, attending, sapcesLeft };
  },
};
</script>

五、Reactive - 響應(yīng)式語法

之前reactive 的 Ref 去聲明所有的響應(yīng)式屬性

import { ref,computed } from 'vue'
export default {
  setup(){
    const capacity = ref(4);
    const attending = ref(["Tim","Bob","Joe"]);
    const spacesLeft = computed(()=>{
      return capacity.value - attending.value.length
    })
    function increaseCapacity(){ capacity.value ++;}
    return { capacity,increaseCapacity,attending,spacesLeft}
  }
}

但是有另一個等效的方法用它去代替 reactive 的Ref

import { reactive,computed } from 'vue'
export default {
  setup(){
    const event = reactive({
      capacity:4,
      attending:["Tim","Bob","Joe"],
      spacesLeft:computed(()=>{
        return event.capacity - event.attending.length;
      })
    })
  }
}

過去我們用vue2.0的data來聲明響應(yīng)式對象,但是現(xiàn)在在這里每一個屬性都是響應(yīng)式的包括computed 計(jì)算屬性

這2種方式相比于第一種沒有使用.

接下來 我們再聲明method 這2種語法都o(jì)k,取決于你選擇哪一種

setup(){
  const event = reactive(){
    capacity:4,
    attending:["Tim","Bob","Joe"],
    spacesLeft:computed(()=>{
      return event.capacity - event.attending.length;
    })
    function increaseCapacity(){event.capacity++}
    //return整個對象
    return {event,increaseCapacity}
  }
}
<p>Spaces Left:{{event.spacesLeft}} out of {{event.capacity}}</p>
<h3>Attending</h3>
<ul>>
	<li v-for="(name,index) in event.attending" :key="index">
     {{name}}
  </li>
</ul>
<button @click="increaseCapacity()"> Increase Capacity</button>

在這里我們使用對象都是.屬性的方式,但是如果 這個結(jié)構(gòu)變化了,event分開了編程了一個個片段,這個時候就不能用.屬性的方式了

//在這里可以使用toRefs
import {reactive,computed,toRefs} from 'vue'
export default{
  setup(){
    const event = reactive({
      capacity:4,
      attending:["Tim","Bob","Joe"],
      spacesLeft:computed(()=>{
        return event.capacity -event.attending.length;
        
      })
    })
    function increaseCapacity(){ event.capacity ++ }
    return {...toRefs(event),increaseCapacity}
  }
}

如果沒有 increaseCapacity() 這個方法 直接可以簡化為

return toRefs(event)

完整代碼

<div>
   <p>Space Left : {{event.spacesLeft}} out of {{event.capacity}} </p>
   <h3>Attending</h3>
   <ul>
      <li v-for="(name,index)" in event.attending :key="index">{{name}}
      </li>


     
   </ul>
   <button @click="increaseCapacity">Increase Capacity</button>
   </div>
</template>

<script>
//第一種
import {ref,computed } from 'vue'
export default {
  setup(){
    const capacity = ref(4)
    const attending = ref(["Tim","Bob","Joe"])
    const spaceLeft = computed(()=>{
      return capacity.value - attending.value.length;
    });
    function increaseCapacity(){ capacity.value++; }
    return {capacity,increaseCapacity,attending,spaceLeft}   


  }
} 

//返回一個響應(yīng)式函數(shù) 第二種
import { reactive,computed } from 'vue'
export default {
  setup(){
    const event = reactive({
      capacity:4,
      attending:["Tim","Bob","Joe"],
      spaceLeft:computed(()=>{
        return event.capacity - event.attending.length;
      })
    })
    //我們不再使用.value
    function increaseCapacity() { event.capacity++; }
    //把這個event放入到template中
    return { event,increaseCapacity}
  }
}


</script>

六、 Modularizing

使用CompositionAPI的兩個理由

1、可以按照功能組織代碼

Vue3中怎么使用CompositionAPI解決問題

2、組件間功能代碼復(fù)用

Vue3中怎么使用CompositionAPI解決問題

Vue3中怎么使用CompositionAPI解決問題

七、 LifecycleHooks - 生命周期鉤子

Vue2Vue3
beforeCreate?setup(替代)
created?setup(替代)
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestroyonBeforeUnmount
destroyedonUnmounted
errorCapturedonErrorCaptured
-?onRenderTracked
-?onRenderTriggered

setup中調(diào)用生命周期鉤子

import { onBeforeMount,onMounted } from "vue";
export default {
  setup() {
    onBeforeMount(() => {
        console.log('Before Mount!')
    }) 
    onMounted(() => {
        console.log('Before Mount!')
    }) 
  },
};

八、Watch - 監(jiān)聽器

// 所有依賴響應(yīng)式對象監(jiān)聽
watchEffect(() => {
   results.value = getEventCount(searchInput.value);
 });

// 特定響應(yīng)式對象監(jiān)聽
watch(
  searchInput,
  () => {
    console.log("watch searchInput:");
  }
);

// 特定響應(yīng)式對象監(jiān)聽 可以獲取新舊值
watch(
  searchInput,
 (newVal, oldVal) => {
    console.log("watch searchInput:", newVal, oldVal);
  },
);

// 多響應(yīng)式對象監(jiān)聽
watch(
  [firstName,lastName],
 ([newFirst,newLast], [oldFirst,oldlast]) => {
   // .....
  },
  
);

// 非懶加載方式監(jiān)聽 可以設(shè)置初始值
watch(
  searchInput,
  (newVal, oldVal) => {
    console.log("watch searchInput:", newVal, oldVal);
  },
  {
    immediate: true, 
  }
);

九、Sharing State - 共享狀態(tài)

Vue3中怎么使用CompositionAPI解決問題

編寫一個公共函數(shù)usePromise函數(shù)需求如下:

  • results : 返回Promise執(zhí)行結(jié)果

  • loading: 返回Promise運(yùn)行狀態(tài)

    • PENDING :true

    • REJECTED : false

    • RESOLVED: false

  • error : 返回執(zhí)行錯誤

Vue3中怎么使用CompositionAPI解決問題

import { ref } from "vue";

export default function usePromise(fn) {
  const results = ref(null);
  // is PENDING
  const loading = ref(false);
  const error = ref(null);

  const createPromise = async (...args) => {
    loading.value = true;
    error.value = null;
    results.value = null;
    try {
      results.value = await fn(...args);
    } catch (err) {
      error.value = err;
    } finally {
      loading.value = false;
    }
  };
  return { results, loading, error, createPromise };
}

應(yīng)用

import { ref, watch } from "vue";
import usePromise from "./usePromise";
export default {
  setup() {
    const searchInput = ref("");
    function getEventCount() {
      return new Promise((resolve) => {
        setTimeout(() => resolve(3), 1000);
      });
    }

    const getEvents = usePromise((searchInput) => getEventCount());

    watch(searchInput, () => {
      if (searchInput.value !== "") {
        getEvents.createPromise(searchInput);
      } else {
        getEvents.results.value = null;
      }
    });

    return { searchInput, ...getEvents };
  },
};

十、Suspense - 懸念

復(fù)雜的Loading實(shí)現(xiàn)

我們考慮一下當(dāng)你加載一個遠(yuǎn)程數(shù)據(jù)時,如何顯示loading狀態(tài)

通常我們可以在模板中使用v-if

Vue3中怎么使用CompositionAPI解決問題

但是在一個組件樹中,其中幾個子組件需要遠(yuǎn)程加載數(shù)據(jù),當(dāng)加載完成前父組件希望處于Loading狀態(tài)時我們就必須借助全局狀態(tài)管理來管理這個Loading狀態(tài)

Vue3中怎么使用CompositionAPI解決問題

Suspense基礎(chǔ)語法

這個問題在Vue3中有一個全新的解決方法。

這就是Suspense Component,懸念組件。

Vue3中怎么使用CompositionAPI解決問題

<template>
  <div>
    <div v-if="error">Uh oh .. {{ error }}</div>
    <Suspense>
      <template #default>
        <div>
          <Event />
          <AsyncEvent />
        </div>
      </template>
      <template #fallback> Loading.... </template>
    </Suspense>
  </div>
</template>

<script>
import { ref, onErrorCaptured, defineAsyncComponent } from "vue";

import Event from "./Event.vue";

const AsyncEvent = defineAsyncComponent(() => import("./Event.vue"));
export default {
  components: {
    Event,
    AsyncEvent,
  },

  setup() {
    const error = ref(null);
    onErrorCaptured((e) => {
      error.value = e;
      // 阻止錯誤繼續(xù)冒泡
      return true;
    });
    return { error };
  },
};
</script>

骨架屏實(shí)現(xiàn)

Vue3中怎么使用CompositionAPI解決問題

Vue3中怎么使用CompositionAPI解決問題

十一、Teleport - 傳送門

功能

類似React中的Portal, 可以將特定的html模板傳送到Dom的任何位置

Vue3中怎么使用CompositionAPI解決問題

基礎(chǔ)語法

通過選擇器QuerySelector配置

Vue3中怎么使用CompositionAPI解決問題

示例代碼

<template>
  <div>
    <teleport to="#end-of-body" :disabled="!showText">
      <!-- 【Teleport : This should be at the end 】 -->
      <div>
        <video src="../assets/flower.webm" muted controls="controls" autoplay="autoplay" loop="loop">
          
        </video>
      </div>
    </teleport>
    <div>【Teleport : This should be at the top】</div>
    <button @click="showText = !showText">Toggle showText</button>
  </div>
</template>
<script>
import { ref } from "vue";
export default {
  setup() {
    const showText = ref(false);
    setInterval(() => {
      showText.value = !showText.value;
    }, 1000);
    return { showText };
  },
};
</script>

到此,關(guān)于“Vue3中怎么使用CompositionAPI解決問題”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI