Vue3.0 composition api 特性學習

options-api

首先咱們來看看 option-api。javascript

default export {    
    data() {
        return {
            state:0
        }
    },
    methods:{
        myFun() {
            console.log(this.state)
        }
    }
}

上面代碼的方式就是 option-api, 也是 vue2.x 中最經常使用的方式。
vue

composition-api

在vue3.x中,可使用下面的 composition-api 方式。java

default export {    
    setup(){
    const state = ref(0)
    function myFunOne() {
      console.log(state.value)
    }
    function myFunTwo() {
      console.log(state.value + 1)
    }
    return {
      state,
      myFunOne
    }
    }
}

解決痛點

看下面的圖片(來源:https://composition-api.vuejs.org/#code-organization),相同業務的代碼顏色相同,能夠看見 Options API 的相同業務代碼分散在各處,這樣後期維護起來就會很是麻煩,而Composition-Api 解決了這個痛點。
image.png
node

知識點梳理

關於 composition-api 所包含的函數有以上這麼多,下面根據相關例子一個個來學習。
react

setup

setup功能是新的組件選項。它是組件內部使用Composition-API的入口。
vue-router

可選參數

它有兩個可選參數 props 和 context。
這兩個參數能夠解構使用。api

  • props 和 vue2.x props是同樣的,裏面的屬性是 父組件傳給自組子或 vue-router 傳給 頁面的參數。
  • context具備與vue2.x 中 this.$attrs,this.$slots,this.$emit,this.$parent,this.$root對應的屬性。

示例代碼

props: {
    msg: String
  },
  // 須要在 emits 中聲明 否則會報錯 下面會有解釋
  emits: {
    sayhi: payload => {
      // validate payload by returning a boolean
      return payload
    }
  },
    // 1. 通常使用
    // setup(props, context) {
    //  console.log('====>', props)
    //  context.emit('sayhi', 'hi')
    //}
    // 2. 可解構使用
    setup({ msg }, { emit }) {
       console.log('====>', msg)
       emit('sayhi', 'hi')
    }

注意點⚠️

在 setup 中使用 emit , 須要在emits 中聲明它,不然會報如下錯誤。數組

Extraneous non-emits event listeners (此處是函數名) were passed to component but could not be automatically inherited because component renders fragment or text root nodes. If the listener is intended to be a component custom event listener only, declare it using the "emits" option.

ref

<template>
  <div>
    <div>{{ state }}</div>
    <button @click="addOne">新增1</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, onMounted } from "vue"
export default defineComponent({
  setup(){
    // 經過 ref 初始化一個響應式的對象
    const state = ref(0)
    
    // 在生命週期 onMounted  中打印 state
    onMounted(() => {
      console.log(state)
    })
    
    function addOne() {
        state.value += 1
    }
    
    return {
        state,
        addOne
    }
    }
})
</script>

咱們再來看看這段代碼。
在 dom掛載完畢的生命週期 onMounted  中打印 state , 發現它是一個對象。
image.png
由於 state 是經過ref 傳參,而後返回的一個對象( ref 是一個函數,它接受一個參數,返回的一個響應式對象 )。咱們初始化的這個 0 做爲參數包裹到這個對象中去,在將來能夠檢測到改變並做出對應的相應。
addOne  函數中, 若要改變 這個 state 響應式對象的值, 則須要經過 賦值 state.value  來實現。
在 template 模板中 ,vue 已經幫咱們自動獲取了其 value屬性,因此咱們只須要傳{{ state }}  便可。
dom

reactive

reactive 和 ref 很是類似, 也是一個函數, 可是其接收一個對象。咱們改造上面學習 ref 的 例子來了解 reactive。函數

<template>
  <div>
    <div>{{ state }}</div>
    <button @click="addOne">新增1</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, reactive, toRefs } from "vue"
export default defineComponent({
  setup(){
    // 經過 reactive 初始化數據
    const data = reactive({
      state: 0,
    })
    // const state = ref(0)
    // 在生命週期 onMounted  中打印 state
    onMounted(() => {
      console.log('無 toRefs', data)
      console.log('經過 toRefs 處理', toRefs(data))
    })
    
    function addOne() {
        data.state += 1
    }
    
    return {
        // ...data, // 這樣導出會使數據失去響應式
        ...toRefs(data), // 經過 toRefs 使得 data 中數據得到響應式
        addOne
    }
    }
})
</script>

image.png
與 ref 相比:

  • reactive 能夠將 零散的 變量彙集在一個對象中。
  • reactive 中的變量 的取值和賦值不須要 取其 value 屬性。


注意點:
使用 reactive 時要記得使用 toRefs 保證 reactive  對象屬性保持響應性。

watch 和 watchEffect

代碼示例

// 經過 reactive 初始化數據
const data = reactive({
  state: 0,
  num: 2,
  arr: [1, 2, 3]
})
// 簡單監聽
watch(data, () => {
  console.log(data.state)
})
// 下面直接監聽data.state會報錯。watch 監聽的目標只能是getter/effect函數、ref、reactive對象或數組。
// watch(data.state, (newValue, oldValue) => {
//   console.log('newValue', newValue)
//   console.log('oldValue', oldValue)
// })

// 監聽 新的值和舊值
watch(() => data.state, (newValue, oldValue) => {
  console.log('newValue', newValue)
  console.log('oldValue', oldValue)
})
// watch 監聽多個屬性,返回的也是多個值的數組
watch([() => data.num, () => data.state], (newValue, oldValue) => {
  console.log('old', oldValue)
  console.log('new', newValue)
})
// watchEffect 不須要指定監聽的屬性 
watchEffect(()=>{
  console.log('watchEffect ===>', data.state);
});

watch

A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types. 

watch 監聽源只能是getter/effect函數、ref、reactive對象或數組。
具體用法如上述代碼所見

  1. 簡單監聽值的改變。
  2. 能夠獲取到新值與舊值。
  3. watch 只能監聽指定的屬性而作出變動,vue3.x能夠同時監聽多個屬性。

watchEffect

watchEffect 和 watch 相似,能夠監聽屬性的變化。具體使用方式如上述代碼。

不一樣點

  1. watchEffect 不須要指定監聽的屬性,它會自動的收集依賴,只要咱們回調中引用到了 響應式的屬性, 那麼當這些屬性變動的時候,這個回調都會執行,而 watch 只能監聽指定的一個或多個屬性而作出變動。
  2.  watch  能夠獲取到新值與舊值,而 watchEffect是拿不到的 oldValue 
  3. watchEffect 在組件初始化的時候就會默認執行一次,而 watch 不須要。



computed

計算屬性和vue2.x 中同樣,代碼示例以下。

<template>
  <div>
    <div>{{ state }}</div>
    <div>{{ double }}</div>
    <button @click="addOne">新增1</button>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, reactive, toRefs } from "vue"
export default defineComponent({
  setup(){
    // 經過 reactive 初始化數據
    const data = reactive({
      state: 0,
    })
    // 經過計算屬性得到的新的值
    const double = computed(() => data.state * 2)
    
    function addOne() {
        data.state += 1
    }
    
    return {
        ...toRefs(data), // 經過 toRefs 使得 data 中數據得到響應式
        addOne,
        double
    }
    }
})
</script>

參考文獻
composition-api 官方文檔

相關文章
相關標籤/搜索