欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue2如何支持composition API示例詳解

 更新時間:2023年01月13日 11:26:11   作者:IDuxFE  
這篇文章主要為大家介紹了Vue2如何支持composition API示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

自從 Vue3 發(fā)布之后,composition API 這個詞走入寫 Vue 同學(xué)的視野之中,相信大家也一直聽到 composition API 比之前的 options API 有多好多強,如今由于 @vue/composition-api 插件的發(fā)布,Vue2 的同學(xué)也可以上車咯,接下來我們主要以響應(yīng)式的 refreactive 來深入分析一下,這個插件是怎么實現(xiàn)此功能的。

如何使用

// 入口文件引入并注冊
import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'
Vue.use(VueCompositionAPI)
// vue文件使用
import { defineComponent, ref, reactive } from '@vue/composition-api'
export default defineComponent({
  setup () {
     const foo = ref('foo');
     const obj = reactive({ bar: 'bar' });
     return {
        foo,
        obj
     }
  }
})

怎么樣,看完是不是感覺和 vue3 一模一樣,你可能會想:

  • 這是 vue2 啊,我之前的 data 、methods 里面也有變量和方法,怎么做到跟 setup 返回值打通合并在一起的。
  • vue2 不是只有定義在 data 里面的數(shù)據(jù)才會被處理成響應(yīng)式的嗎? refreactive 是怎么做到的呢?
  • vue2 響應(yīng)式數(shù)據(jù)定義的約束(添加賦值原對象沒有的屬性,數(shù)組下標(biāo)修改等),改用 refreactive 就沒問題嗎?

當(dāng)然還有很多的疑惑,因為插件提供的 API 相當(dāng)多,覆蓋了絕大部分 Vue3 所擁有的,這里主要從這幾個問題來分析一下是如何做到的。

原理解析

得益于 Vue 的插件系統(tǒng),@vue/composition-apivue-router 、vuex 一樣也是通過官方提供的插件式來注入。

// 這里只貼跟本章要講的相關(guān)代碼
funciton mixin (Vue) {
    Vue.mixin({
      beforeCreate: functionApiInit
   }
}
function install (Vue) {
    mixin(Vue);
}
export const Plugin = {
  install: (Vue: VueConstructor) => install(Vue),
}

Vue 插件就是向外面暴露一個 install 的方法,當(dāng)調(diào)用 use 的時候會調(diào)用該方法,并把 Vue 構(gòu)造函數(shù)作為參數(shù)傳入,然后調(diào)用 Vue.mixin 混入對應(yīng)鉤子時要處理的函數(shù)。

接下來主要看下 functionApiInit 做了什么

function functionApiInit(this: ComponentInstance) {
  const vm = this
  const $options = vm.$options
  const { setup, render } = $options
  // render 相關(guān)
  const { data } = $options
  $options.data = function wrappedData() {
    initSetup(vm, vm.$props)
    return isFunction(data)
     ? (
        data as (this: ComponentInstance, x: ComponentInstance) => object
      ).call(vm, vm)
     : data || {}
  }

因為 VuebeforeCreatedcreated 生命周期之間,會 initState 對數(shù)據(jù)進(jìn)行處理,其中對 data的處理時就會調(diào)用 $options.data拿到定義的數(shù)據(jù),所以這里重新對該函數(shù)其包裹一層,這也是為什么要選擇 beforeCreate 鉤子注入的一個原因,必須在該函數(shù)調(diào)用前進(jìn)行包裹。 接下來看 initSetup都做了什么

function initSetup(vm: ComponentInstance, props: Record<any, any> = {}) {
  const setup = vm.$options.setup!
  const ctx = createSetupContext(vm)
  const instance = toVue3ComponentInstance(vm)
  instance.setupContext = ctx
  def(props, '__ob__', createObserver())
  resolveScopedSlots(vm, ctx.slots)
  let binding: ReturnType<SetupFunction<Data, Data>> | undefined | null
  activateCurrentInstance(instance, () => {
    binding = setup(props, ctx)
  })
   // setup返回是函數(shù)的情況 需要重寫render函數(shù)
  const bindingObj = binding
  Object.keys(bindingObj).forEach((name) => {
    let bindingValue: any = bindingObj[name]
    // 數(shù)據(jù)處理
    asVmProperty(vm, name, bindingValue)
  })
  return
  }
}

這個函數(shù)比較長,不在本次要講解的主線上代碼邏輯都刪除了,這個函數(shù)主要是創(chuàng)建了 ctx 和把 vm 實例轉(zhuǎn)換成 Vue3 數(shù)據(jù)類型定義的 instance ,然后執(zhí)行 setup 函數(shù)得到返回值,然后遍歷每個屬性,調(diào)用 asVmProperty 掛載到 vm 上面,當(dāng)然這里的掛載不是直接通過把屬性和值添加到 vm 上面,這么做會有一個問題,就是后續(xù)對該屬性的修改不能同步到 vm 中,這里采用的還是 Vue 最常見的數(shù)據(jù)代理。

export function asVmProperty(
  vm: ComponentInstance,
  propName: string,
  propValue: Ref<unknown>
) {
  const props = vm.$options.props
  if (!(propName in vm) && !(props && hasOwn(props, propName))) {
    if (isRef(propValue)) {
      proxy(vm, propName, {
        get: () => propValue.value,
        set: (val: unknown) => {
          propValue.value = val
        },
      })
    } else {
      proxy(vm, propName, {
        get: () => {
          if (isReactive(propValue)) {
            ;(propValue as any).__ob__.dep.depend()
          }
          return propValue
        },
        set: (val: any) => {
          propValue = val
        },
      })
    }
}    

看到這里,相信你已經(jīng)明白了在 setup 中定義返回的為什么能夠在 templatedatamethods 等之中去使用了,因為返回的東西都已經(jīng)被代理到 vm 之上了。

響應(yīng)式( ref reactive 的實現(xiàn))

接下來我們來說說響應(yīng)式相關(guān)的,為什么 refreactive 也可以讓數(shù)據(jù)成為響應(yīng)式的。

ref 的實現(xiàn)其實是對 reactive 再次封裝,主要用來給基本類型使用。

function ref(raw?: unknown) {
  if (isRef(raw)) {
    return raw
  }
  const value = reactive({ [RefKey]: raw })
  return createRef({
    get: () => value[RefKey] as any,
    set: (v) => ((value[RefKey] as any) = v),
  })
}

因為 reactive 接受的必須是一個對象,所有這里使用了一個常量作為 refkey, 也就是

const value = reactive({
  "composition-api.refKey": row
})
export function createRef<T>(
  options: RefOption<T>,
  isReadonly = false,
  isComputed = false
): RefImpl<T> {
  const r = new RefImpl<T>(options)
  const sealed = Object.seal(r)
  if (isReadonly) readonlySet.set(sealed, true)
  return sealed
}
export class RefImpl<T> implements Ref<T> {
  readonly [_refBrand]!: true
  public value!: T
  constructor({ get, set }: RefOption<T>) {
    proxy(this, 'value', {
      get,
      set,
    })
  }
}

通過 new RefImpl 實例,該實例上有一個 value 的屬性,對 value 做代理,當(dāng)取值的時候返回 value[RefKey],賦值的時候賦值給 value[RefKey], 這就是為什么 ref 可以用在基本類型,然后對返回值的 .value 進(jìn)行操作。調(diào)用 object.seal 是把對象密封起來(會讓這個對象變的不能添加新屬性,且所有已有屬性會變的不可配置。屬性不可配置的效果就是屬性變的不可刪除,以及一個數(shù)據(jù)屬性不能被重新定義成為訪問器屬性,或者反之。但屬性的值仍然可以修改。)

我們主要看下 reactive 的實現(xiàn)

export function reactive<T extends object>(obj: T): UnwrapRef<T> {
    const observed = observe(obj)
    setupAccessControl(observed)
    return observed as UnwrapRef<T>
}
export function observe<T>(obj: T): T {
  const Vue = getRegisteredVueOrDefault()
  let observed: T
  if (Vue.observable) {
    observed = Vue.observable(obj)
  } else {
    const vm = defineComponentInstance(Vue, {
      data: {
        $$state: obj,
      },
    })
    observed = vm._data.$$state
  }
  return observed
}

我們通過 ref 或者 reactive 定義的數(shù)據(jù),最終還是通過了變成了一個 observed 實例對象,也就是 Vue2 在對 data 進(jìn)行處理時,會調(diào)用 observe 返回的一樣,這里在 Vue2.6+observe 函數(shù)向外暴露為 Vue.observable,如果是低版本的話,可以通過重新 new 一個 vue 實例,借助 data 也可以返回一個 observed 實例,如上述代碼。

因為在 reactive 中定義的數(shù)據(jù),就如你在 data 中定義的數(shù)據(jù)一樣,都是在操作返回的 observed ,當(dāng)你取值的時候,會觸發(fā) getter 進(jìn)行依賴收集,賦值時會調(diào)用 setter 去派發(fā)更新, 只是定義在 setup 中,結(jié)合之前講到的 setup 部分,比如當(dāng)我們在 template 中訪問一個變量的值時,vm.foo -> proxysetup 里面的 foo -> observedfoo ,完成取值的流程,這會比直接在 data 上多代理了一層,因此整個過程也會有額外的性能開銷。

因此使用該 API 也不會讓你可以直接規(guī)避掉 vue2 響應(yīng)式數(shù)據(jù)定義的約束,因為最終還是用 Object.defineProperty 去做對象攔截,插件同樣也提供了 set API 讓你去操作對象新增屬性等操作。

總結(jié)

通過上面的了解,相信你一定對于 Vue2 如何使用 composition API 有了一定的了解,因為 API 相當(dāng)多, 響應(yīng)式相關(guān)的就還有 toRefs、toRef、unref、shallowRef、triggerRef 等等,這里就不一一分析,有興趣的可以繼續(xù)看源碼的實現(xiàn)。

Vue2 的同學(xué)也可以不用羨慕寫 Vue3 的同學(xué)了,直接引入到項目就可以使用起來,雖然沒有 vue3 那么好的體驗,但是絕大部分場景還是相同的,使用時注意 README 文檔最后的限制章節(jié),里面講了一些使用限制。

以上就是Vue2如何支持composition API示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Vue 支持composition API的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue按鈕權(quán)限的實現(xiàn)示例

    Vue按鈕權(quán)限的實現(xiàn)示例

    在編寫Vue代碼的時候,經(jīng)常會碰到各種權(quán)限問題,本文主要介紹了Vue按鈕權(quán)限的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2024-08-08
  • 簡單了解vue.js數(shù)組的常用操作

    簡單了解vue.js數(shù)組的常用操作

    這篇文章主要介紹了簡單了解vue.js數(shù)組的常用操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,,需要的朋友可以參考下
    2019-06-06
  • vue實現(xiàn)復(fù)制文字復(fù)制圖片實例詳解

    vue實現(xiàn)復(fù)制文字復(fù)制圖片實例詳解

    這篇文章主要為大家介紹了vue實現(xiàn)復(fù)制文字復(fù)制圖片實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Vue.js暴露方法給WebView的使用操作

    Vue.js暴露方法給WebView的使用操作

    這篇文章主要介紹了Vue.js暴露方法給WebView的使用操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 詳解VUE中常用的幾種import(模塊、文件)引入方式

    詳解VUE中常用的幾種import(模塊、文件)引入方式

    這篇文章主要介紹了詳解VUE中常用的幾種import(模塊、文件)引入方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • 快速處理vue渲染前的顯示問題

    快速處理vue渲染前的顯示問題

    下面小編就為大家分享一篇快速處理vue渲染前的顯示問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • vue中使用moment設(shè)置倒計時的方法

    vue中使用moment設(shè)置倒計時的方法

    這篇文章給大家介紹了vue中使用moment設(shè)置倒計時的方法,文中通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-02-02
  • vue中實現(xiàn)拖拽排序功能的詳細(xì)教程

    vue中實現(xiàn)拖拽排序功能的詳細(xì)教程

    在業(yè)務(wù)中列表拖拽排序是比較常見的需求,下面這篇文章主要給大家介紹了關(guān)于vue中實現(xiàn)拖拽排序功能的詳細(xì)教程,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • 如何利用vue實現(xiàn)css過渡和動畫

    如何利用vue實現(xiàn)css過渡和動畫

    過渡Vue在插入、更新或者移除 DOM 時,提供多種不同方式的應(yīng)用過渡效果這篇文章主要給大家介紹了關(guān)于如何利用vue實現(xiàn)css過渡和動畫的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • vue組件與復(fù)用詳解

    vue組件與復(fù)用詳解

    組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴(kuò)展 HTML 元素,封裝可重用的代碼。這篇文章主要介紹了vue組件與復(fù)用,需要的朋友可以參考下
    2018-04-04

最新評論