亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄
如何使用
原理解析
回應式( ref ?reactive 的實作)
總結
首頁 web前端 Vue.js 解析Vue2實作composition API的原理

解析Vue2實作composition API的原理

Jan 13, 2023 am 08:30 AM
前端 vue.js

解析Vue2實作composition API的原理

自從Vue3 發(fā)布之後,composition API 這個字走入寫Vue 同學的視野之中,相信大家也一直聽到composition API 比之前的options API 有多好多強,如今由於@vue/composition-api 外掛程式的發(fā)布, Vue2 的同學也可以上車咯,接下來我們主要以響應式的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 啊,我之前的datamethods 裡面也有變數(shù)和方法,怎麼做到跟setup 傳回值打通合併在一起的。 【相關推薦:vuejs影片教學、web前端開發(fā)

  • vue2 不是只有定義在 data 裡面的資料才會被處理成響應式的嗎? refreactive 是怎麼做到的呢?

  • vue2 響應式資料定義的約束(新增賦值原始物件沒有的屬性,陣列下標修改等),改用refreactive 就沒問題嗎?

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

原理解析

得益於Vue 的外掛系統(tǒng),@vue/composition-api 像是 vue-router 、vuex 一樣也是透過官方提供的外掛程式來注入。

// 這里只貼跟本章要講的相關代碼

funciton mixin (Vue) {
    Vue.mixin({
      beforeCreate: functionApiInit
   }
}

function install (Vue) {
    mixin(Vue);
}

export const Plugin = {
  install: (Vue: VueConstructor) => install(Vue),
}

Vue 外掛程式就是向外面暴露一個install 的方法,當呼叫use 的時候會呼叫該方法,並且把Vue 建構子作為參數(shù)傳入,然後呼叫Vue.mixin 混入對應鉤子時要處理的函數(shù)。

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

function functionApiInit(this: ComponentInstance) {
  const vm = this
  const $options = vm.$options
  const { setup, render } = $options
  
  // render 相關
  
  
  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 對資料進行處理,其中對data的處理時就會呼叫$options.data拿到定義的數(shù)據(jù),所以這裡重新對該函數(shù)其包裹一層,這也是為什麼要選擇beforeCreate 鉤子注入的一個原因,必須在該函數(shù)調用前進行包裹。 接下來看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, &#39;__ob__&#39;, 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 實例轉換成Vue3 資料型別定義的instance ,然後執(zhí)行setup 函數(shù)得到回??傳值,然後遍歷每個屬性,呼叫asVmProperty 掛載到vm 上面,當然這裡的掛載不是直接透過把屬性和值加到vm 上面,這麼做會有一個問題,就是後續(xù)對該屬性的修改不能同步到vm 中,這裡採用的還是Vue 最常見的資料代理。

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 中定義返回的為什麼能夠在templatedata 、 methods 等之中去使用了,因為傳回的東西都已經(jīng)被代理到vm 之上了。

回應式( ref ?reactive 的實作)

接下來我們來說說響應式相關的,為什麼refreactive 也可以讓資料成為響應式的。

ref 的實作其實是對 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 接受的必須是一個對象,所有這裡使用了一個常數(shù)作為 ref# 的 key, 也就是

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, &#39;value&#39;, {
      get,
      set,
    })
  }
}

通過 new RefImpl 實例,該實例上有一個 value 的屬性,對 value 做代理,當取值的時候返回 value[RefKey],賦值的時候賦值給 value[RefKey], 這就是為什么 ref 可以用在基本類型,然后對返回值的 .value 進行操作。調用 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 進行處理時,會調用 observe 返回的一樣,這里在 Vue2.6+observe 函數(shù)向外暴露為 Vue.observable,如果是低版本的話,可以通過重新 new 一個 vue 實例,借助 data 也可以返回一個 observed 實例,如上述代碼。

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

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

總結

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

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

(學習視頻分享:vuejs入門教程、編程基礎視頻

以上是解析Vue2實作composition API的原理的詳細內(nèi)容。更多資訊請關注PHP中文網(wǎng)其他相關文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發(fā)現(xiàn)涉嫌抄襲或侵權的內(nèi)容,請聯(lián)絡admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

PHP與Vue:完美搭檔的前端開發(fā)利器 PHP與Vue:完美搭檔的前端開發(fā)利器 Mar 16, 2024 pm 12:09 PM

PHP與Vue:完美搭檔的前端開發(fā)利器在當今網(wǎng)路快速發(fā)展的時代,前端開發(fā)變得愈發(fā)重要。隨著使用者對網(wǎng)站和應用的體驗要求越來越高,前端開發(fā)人員需要使用更有效率和靈活的工具來創(chuàng)建響應式和互動式的介面。 PHP和Vue.js作為前端開發(fā)領域的兩個重要技術,搭配起來可以稱得上是完美的利器。本文將探討PHP和Vue的結合,以及詳細的程式碼範例,幫助讀者更好地理解和應用這兩

Go語言前端技術探秘:前端開發(fā)新視野 Go語言前端技術探秘:前端開發(fā)新視野 Mar 28, 2024 pm 01:06 PM

Go語言作為一種快速、高效的程式語言,在後端開發(fā)領域廣受歡迎。然而,很少有人將Go語言與前端開發(fā)聯(lián)繫起來。事實上,使用Go語言進行前端開發(fā)不僅可以提高效率,還能為開發(fā)者帶來全新的視野。本文將探討使用Go語言進行前端開發(fā)的可能性,並提供具體的程式碼範例,幫助讀者更了解這一領域。在傳統(tǒng)的前端開發(fā)中,通常會使用JavaScript、HTML和CSS來建立使用者介面

Django是前端還是後端?一探究竟! Django是前端還是後端?一探究竟! Jan 19, 2024 am 08:37 AM

Django是一個由Python編寫的web應用框架,它強調快速開發(fā)和乾淨方法。儘管Django是web框架,但要回答Django是前端還是後端這個問題,需要深入理解前後端的概念。前端是指使用者直接和互動的介面,後端是指伺服器端的程序,他們透過HTTP協(xié)定進行資料的互動。在前端和後端分離的情況下,前後端程式可以獨立開發(fā),分別實現(xiàn)業(yè)務邏輯和互動效果,資料的交

vue.js vs.反應:特定於項目的考慮因素 vue.js vs.反應:特定於項目的考慮因素 Apr 09, 2025 am 12:01 AM

Vue.js適合中小型項目和快速迭代,React適用於大型複雜應用。 1)Vue.js易於上手,適用於團隊經(jīng)驗不足或項目規(guī)模較小的情況。 2)React的生態(tài)系統(tǒng)更豐富,適合有高性能需求和復雜功能需求的項目。

前端面試官常問的問題 前端面試官常問的問題 Mar 19, 2024 pm 02:24 PM

在前端開發(fā)面試中,常見問題涵蓋廣泛,包括HTML/CSS基礎、JavaScript基礎、框架和函式庫、專案經(jīng)驗、演算法和資料結構、效能最佳化、跨域請求、前端工程化、設計模式以及新技術和趨勢。面試官的問題旨在評估候選人的技術技能、專案經(jīng)驗以及對行業(yè)趨勢的理解。因此,應試者應充分準備這些方面,以展現(xiàn)自己的能力和專業(yè)知識。

Django:前端和後端開發(fā)都能搞定的神奇框架! Django:前端和後端開發(fā)都能搞定的神奇框架! Jan 19, 2024 am 08:52 AM

Django:前端和後端開發(fā)都能搞定的神奇框架! Django是一個高效、可擴展的網(wǎng)路應用程式框架。它能夠支援多種Web開發(fā)模式,包括MVC和MTV,可以輕鬆地開發(fā)出高品質的Web應用程式。 Django不僅支援後端開發(fā),還能夠快速建構出前端的介面,透過模板語言,實現(xiàn)靈活的視圖展示。 Django把前端開發(fā)和後端開發(fā)融合成了一種無縫的整合,讓開發(fā)人員不必專門學習

Golang與前端技術結合:探討Golang如何在前端領域發(fā)揮作用 Golang與前端技術結合:探討Golang如何在前端領域發(fā)揮作用 Mar 19, 2024 pm 06:15 PM

Golang與前端技術結合:探討Golang如何在前端領域發(fā)揮作用,需要具體程式碼範例隨著互聯(lián)網(wǎng)和行動應用的快速發(fā)展,前端技術也愈發(fā)重要。而在這個領域中,Golang作為一門強大的後端程式語言,也可以發(fā)揮重要作用。本文將探討Golang如何與前端技術結合,以及透過具體的程式碼範例來展示其在前端領域的潛力。 Golang在前端領域的角色作為一門高效、簡潔且易於學習的

Vue.js很難學習嗎? Vue.js很難學習嗎? Apr 04, 2025 am 12:02 AM

Vue.js不難學,特別是對於有JavaScript基礎的開發(fā)者。 1)其漸進式設計和響應式系統(tǒng)簡化了開發(fā)過程。 2)組件化開發(fā)讓代碼管理更高效。 3)使用示例展示了基本和高級用法。 4)常見錯誤可以通過VueDevtools調試。 5)性能優(yōu)化和最佳實踐如使用v-if/v-show和key屬性可提升應用效率。

See all articles