<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          @vue/composition-api速成課(通俗易懂版)

          共 5175字,需瀏覽 11分鐘

           ·

          2020-09-25 12:37

          Composition API 將是 Vue 3 的核心功能,它具有許多更改和性能改進。我們也可以在 Vue 2 中通過 npm 插件@vue/composition-api 使用它。本人重點將帶你了解:

          1. @vue/composition-api常見 api 使用
          2. vue3 代碼邏輯提取和復用
          3. 如何使用provide+inject替代vuex方案

          vue2 使用 composition-api

          主文件 main.ts 或者 app.vue 添加

          import?Vue?from?'vue'
          import?VueCompositionAPI?from?'@vue/composition-api'
          Vue.use(VueCompositionAPI)

          Composition API 不再傳入 data、mounted 等參數(shù), 通過引入的 refonMounted等方法實現(xiàn)數(shù)據(jù)的雙向綁定、生命周期函數(shù)的執(zhí)行。

          核心語法

          reactive:接收一個普通對象然后返回該普通對象的響應式代理。

          ref:接受一個參數(shù)值并返回一個響應式且可改變的 ref 對象。ref 對象擁有一個指向內(nèi)部值的單一屬性 .value。

          computed:傳入一個 getter 函數(shù),返回一個默認不可手動修改的 ref 對象。

          readonly:傳入一個對象(響應式或普通)或 ref,返回一個原始對象的只讀代理。一個只讀的代理是“深層的”,對象內(nèi)部任何嵌套的屬性也都是只讀的。

          watchEffect:立即執(zhí)行傳入的一個函數(shù),并響應式追蹤其依賴,并在其依賴變更時重新運行該函數(shù)。可顯式的調(diào)用返回值以停止偵聽。

          watch:全等效于 2.x this.\$watch (以及 watch 中相應的選項)。

          setup 函數(shù)

          現(xiàn)在要介紹的第一個 API 就是 setup 函數(shù)。setup 函數(shù)是一個新的組件選項。作為在組件內(nèi)使用 Composition API 的入口點。先看個簡單 demo

          <template>
          ??<button?@click="increase">count?is:?{{?count?}}button>
          template>
          <script>
          ??export?default?{
          ????setup()?{
          ??????let?count?=?0
          ??????const?increase?=?()?=>?count++
          ??????return?{?count,?increase?}
          ????},
          ??}
          script>

          1、調(diào)用時機

          創(chuàng)建組件實例,然后初始化 props ,緊接著就調(diào)用 setup 函數(shù)。從 vue2 生命周期鉤子的視角來看,它會在 beforeCreate 鉤子之后,created 之前被調(diào)用。

          2、模板中使用

          如果 setup 返回一個對象,則對象的屬性將會被合并到組件模板的渲染上下文。

          3、渲染函數(shù) / JSX 中使用

          setup 也可以返回一個函數(shù),函數(shù)中也能使用當前 setup 函數(shù)作用域中的響應式數(shù)據(jù):

          import?{?h,?ref,?reactive?}?from?'@vue/composition-api'

          export?default?{
          ??setup()?{
          ????const?count?=?ref(0)
          ????const?object?=?reactive({?foo:?'bar'?})

          ????return?()?=>?h('div',?[count.value,?object.foo])
          ??},
          }

          4、兩個參數(shù)props(注意 props 對象是響應式的),context(上下文對象,從原來 2.x 中 this 選擇性地暴露了一些 property。)

          const?MyComponent?=?{
          ??setup(props,?context)?{
          ????let?{
          ??????attrs,
          ??????emit,
          ??????isServer,
          ??????listeners,
          ??????parent,
          ??????refs,
          ??????root,
          ??????slots,
          ??????ssrContext,
          ????}?=?context
          ??},
          }

          ref & reactive

          App.vue 中,點擊事件綁定了 increase,然后修改了 count, 但是頁面并沒有發(fā)生改變,這是因為 setup 函數(shù)返回的對象中 count 不是響應式數(shù)據(jù), 那么如何創(chuàng)建響應式數(shù)據(jù)呢?此時就要掌握響應式系統(tǒng) API,我們可以使用 refreactive 創(chuàng)建。

          <template>
          ??<button?@click="increase">
          ????count?is:?{{?count?}},?state.count?is?{{?state.count?}}
          ??button>
          template>

          <script>
          ??import?{?ref,?reactive?}?from?'vue'
          ??export?default?{
          ????setup()?{
          ??????let?count?=?ref(0)?//?{?value:?0?}
          ??????let?state?=?reactive({?number:?0?})
          ??????const?increase?=?()?=>?{
          ????????count.value++
          ????????state.count++
          ??????}
          ??????return?{?count,?state,?increase?}
          ????},
          ??}
          script>

          接受一個參數(shù)值并返回一個響應式且可改變的 ref 對象。ref 對象擁有一個指向內(nèi)部值的單一屬性 .value

          ref 作為渲染上下文的屬性返回(即在 setup() 返回的對象中)并在模板中使用時, 它會自動解套,無需在模板內(nèi)額外書寫 .value

          Vue 本身已經(jīng)有 "ref" 的概念了。但只是為了在模板中獲取 DOM 元素或組件實例 (“模板引用”)。新的 ref 系統(tǒng)同時用于邏輯狀態(tài)和模板引用。

          reactive 接收一個普通對象然后返回該普通對象的響應式代理。

          響應式轉換是“深層的”:會影響對象內(nèi)部所有嵌套的屬性。基于 ES2015 的 Proxy 實現(xiàn),返回的代理對象不等于原始對象。建議僅使用代理對象而避免依賴原始對象。

          不要解構返回的代理對象,那樣會使其失去響應性:

          <template>
          ??<button?@click="increase">count?is:?{{?count?}}button>
          template>

          <script>
          ??import?{?ref,?reactive?}?from?'@vue/composition-api'
          ??export?default?{
          ????setup()?{
          ??????let?state?=?reactive({?count:?0?})
          ??????const?increase?=?()?=>?state.count++
          ??????return?{?...state,?increase?}?//?展開state屬性將失去響應式
          ????},
          ??}
          script>

          toRef 和 toRefs

          那如果我們真的想展開 state 的屬性,在模板使用 count 而不是 state.count 的寫法那怎么辦呢?我們可以使用 toReftoRefs 這兩個 API,進行轉換成 ref 對象,之前已經(jīng)介紹了 ref 對象是可以直接在模板中使用的。

          toRef 可以用來為一個 reactive 對象的屬性創(chuàng)建一個 ref。這個 ref 可以被傳遞并且能夠保持響應性。

          <template>
          ??<button?@click="increase">
          ????count?is:?{{?count?}},count2?is:?{{?count2?}}
          ??button>
          template>

          <script>
          ??import?{?ref,?reactive,?toRef,?toRefs?}?from?'@vue/composition-api'
          ??export?default?{
          ????setup()?{
          ??????let?state?=?reactive({?count:?0?})
          ??????let?countRef?=?toRef(state,?'count')
          ??????let?state2?=?reactive({?count2:?0?})
          ??????const?increase?=?()?=>?state.count++
          ??????let?stateAsRefs?=?toRefs(state2)
          ??????return?{?count:?countRef,?increase,?...stateAsRefs?}
          ????},
          ??}
          script>

          把一個響應式對象轉換成普通對象,該普通對象的每個 property 都是一個 ref ,和響應式對象 property 一一對應。

          computed & watch

          const?countDouble?=?computed(()?=>?count.value?*?2)
          watch(
          ??()?=>?state.count,
          ??(count,?prevCount)?=>?{
          ????/*?...?*/
          ??}
          )

          代碼邏輯提取和復用

          Composition API 的第一個明顯優(yōu)勢是很容易提取邏輯。解決了

          邏輯提取

          export?const?useCount?=?(number)?=>?{
          ??const?count?=?ref(0)
          ??const?increase?=?()?=>?{
          ????count.value?+=?1
          ??}
          ??const?reset?=?()?=>?{
          ????count.value?=?0
          ??}
          ??onMounted(()?=>?{
          ????count.value?=?number
          ??})
          ??return?{
          ????count,
          ????increase,
          ????reset,
          ??}
          }

          代碼復用

          //?另外一個文件使用:
          const?{?count,?increase?}?=?useCount(1)
          console.log(count)?//輸出1
          increase()
          console.log(count)?//輸出2
          reset()
          console.log(count)?//輸出0

          有效的解決了 mixins 復用命名沖突,難以識別命名來自哪個 mixin 文件的問題。

          替代 vuex 狀態(tài)管理

          狀態(tài) store 可以放在一個單一的文件或者目錄里,比如設置一個全局組件可以只用的配置 config

          //context/config.ts
          import?{?provide,?inject,?ref,?onMounted,?readonly?}?from?'@vue/composition-api'
          const?configSymbol:?symbol?=?Symbol()

          export?const?useProvider?=?{
          ??setup()?{
          ????let?config?=?ref(null)
          ????const?configServer?=?async?()?=>?{
          ??????//?await?一些異步操作,比如api等
          ??????config.value?=?{?name:?'名字'?}
          ????}
          ????onMounted(async?()?=>?{
          ??????await?configServer()
          ????})
          ????provide(configSymbol,?{
          ??????//導出只讀的config只有函數(shù)內(nèi)部可以修改狀態(tài)
          ??????config:?readonly(config),
          ????})
          ??},
          }

          export?const?useInject?=?()?=>?{
          ??return?inject(configSymbol)
          }

          在最頂層的組件(例如 main.ts)上注入,config 就可以在所有的組件中使用

          import?{?defineComponent?}?from?'@vue/composition-api'
          import?{?useProvider?}?from?'./context/config'
          export?default?defineComponent({
          ??setup()?{
          ????useProvider()
          ??},
          })

          業(yè)務邏輯頁面使用 config

          import?{?useInject?}?from?'./context/config'
          const?Components?=?{
          ??setup()?{
          ????const?{?config?}?=?useInject()
          ????console.log(config.value.name)?//輸出“名字”
          ????return?{
          ??????config,
          ????}
          ??},
          }


          瀏覽 51
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美V亚洲V综合V国产 | 婷婷五月丁香狠狠撸 | 国产真实乱婬A片三区高 | 美女插逼 | 亚洲精品UV视频 |