Rumah > hujung hadapan web > View.js > teks badan

Analisis prinsip Vue2 melaksanakan API komposisi

青灯夜游
Lepaskan: 2023-01-13 20:23:23
ke hadapan
2718 orang telah melayarinya

Analisis prinsip Vue2 melaksanakan API komposisi

Sejak keluaran Vue3, perkataan composition API telah masuk ke ufuk pelajar yang menulis Vue Saya percaya semua orang telah mendengar bahawa composition API adalah lebih baik daripada options API sebelumnya sangat berkuasa Kini, terima kasih kepada pemalam @vue/composition-api, pelajar Vue2 juga boleh menaiki bas, terutamanya ref dan reactive untuk menganalisis secara mendalam cara pemalam ini melaksanakan fungsi ini.

Bagaimana untuk menggunakan

// 入口文件引入并注册
import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'

Vue.use(VueCompositionAPI)
Salin selepas log masuk
// 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
     }
  }
})
Salin selepas log masuk

Adakah anda merasakan sama seperti vue3 Anda mungkin berfikir:

  • Ini adalah vue2 saya sebelum ini data dan methods juga mempunyai pembolehubah dan kaedah. [Cadangan berkaitan: setuptutorial video vuejs, pembangunan bahagian hadapan web]

  • Bukan sahaja data yang ditakrifkan dalam vue2 Adakah ia akan dibuat responsif? Bagaimanakah data dan ref melakukannya? reactive

  • Kekangan yang ditakrifkan oleh data responsif (menambah atribut yang tidak diberikan kepada objek asal, mengubah suai subskrip tatasusunan, dll.), adakah boleh menggunakan vue2 dan ref sebaliknya ? reactive

Sudah tentu masih terdapat banyak keraguan, kerana pemalam menyediakan cukup banyak

, merangkumi kebanyakan perkara yang API ada di sini isu ini. Begini caranya. Vue3

Analisis Prinsip

Terima kasih kepada sistem pemalam

, Vue seperti @vue/composition-api dan vue-router turut disediakan oleh palam rasmi -dalam sistem suntikan. vuex

// 这里只贴跟本章要讲的相关代码

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

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

export const Plugin = {
  install: (Vue: VueConstructor) => install(Vue),
}
Salin selepas log masuk

Pemalam mendedahkan kaedah Vue ke luar Apabila install dipanggil, kaedah ini akan dipanggil dan pembina use akan dihantar masuk sebagai. parameter, dan kemudian dipanggil Vue Fungsi yang akan diproses apabila mencampurkan dalam cangkuk yang sepadan. Vue.mixin

Langkah seterusnya ialah melihat apa yang

lakukan 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 || {}
  }
Salin selepas log masuk
kerana

akan Vue melaksanakan pemprosesan data antara beforeCreated dan created kitaran hayat. Pemprosesan, apabila memproses initState, data akan dipanggil untuk mendapatkan data yang ditetapkan, jadi di sini kita bungkus semula fungsi Ini juga salah satu sebab mengapa suntikan cangkuk dipilih Balut sebelum panggilan fungsi. Seterusnya, mari lihat apa yang $options.data lakukan beforeCreateinitSetup

Fungsi ini agak panjang, dan logik kod yang tidak ada pada baris utama yang akan dijelaskan kali ini telah dipadamkan terutamanya 🎜> dan meletakkan < Contoh 🎜> ditukar kepada
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返回是函数的情况 需要重写render函数

  const bindingObj = binding

  Object.keys(bindingObj).forEach((name) => {
    let bindingValue: any = bindingObj[name]

    // 数据处理
    
    asVmProperty(vm, name, bindingValue)
  })
  return
  }
}
Salin selepas log masuk
ditakrifkan oleh jenis data

, dan kemudian fungsi ctx dilaksanakan untuk mendapatkan nilai pulangan, dan kemudian setiap atribut dilalui, dan vm dipanggil untuk dipasang pada Vue3 Sudah tentu, pelekap di sini tidak Menambah atribut dan nilai secara langsung ke instance akan menyebabkan masalah, iaitu, pengubahsuaian seterusnya pada atribut tidak boleh disegerakkan ke setup proksi data yang paling biasa asVmProperty digunakan di sini. vmvmvmSelepas melihat ini, saya percaya anda telah memahami mengapa pulangan yang ditakrifkan dalam Vue boleh digunakan dalam

,
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
        },
      })
    }
}
Salin selepas log masuk
,

, dsb., kerana semua yang dikembalikan mempunyai telah diproksikan kepada setup. templatedatamethodsResponsif (pelaksanaan vm

)

refSeterusnya mari kita bincangkan tentang responsif, mengapa reactive dan juga Data boleh dibuat responsif . Pelaksanaan

ref sebenarnya merupakan pengkapsulan semula reactive, terutamanya digunakan untuk jenis asas.

refKerana reactive mesti menerima objek, jadi pemalar digunakan di sini sebagai

's
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),
  })
}
Salin selepas log masuk
, iaitu,

const value = reactive({
  "composition-api.refKey": row
})
Salin selepas log masuk
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,
    })
  }
}
Salin selepas log masuk

通过 new RefImpl 实例,该实例上有一个 value 的属性,对 value 做代理,当取值的时候返回 value[RefKey],赋值的时候赋值给 value[RefKey], 这就是为什么 ref 可以用在基本类型,然后对返回值的 .value 进行操作。调用 object.seal 是把对象密封起来(会让这个对象变的不能添加新属性,且所有已有属性会变的不可配置。属性不可配置的效果就是属性变的不可删除,以及一个数据属性不能被重新定义成为访问器属性,或者反之。但属性的值仍然可以修改。)

我们主要看下 reactive 的实现

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
}
Salin selepas log masuk

我们通过 ref 或者 reactive 定义的数据,最终还是通过了变成了一个 observed 实例对象,也就是 Vue2 在对 data 进行处理时,会调用 observe 返回的一样,这里在 Vue2.6+observe 函数向外暴露为 Vue.observable,如果是低版本的话,可以通过重新 new 一个 vue 实例,借助 data 也可以返回一个 observed 实例,如上述代码。

因为在 reactive 中定义的数据,就如你在 data 中定义的数据一样,都是在操作返回的 observed ,当你取值的时候,会触发 getter 进行依赖收集,赋值时会调用 setter 去派发更新, 只是定义在 setup 中,结合之前讲到的 setup 部分,比如当我们在 template 中访问一个变量的值时,vm.foo -> proxysetup 里面的 foo -> observedfoo ,完成取值的流程,这会比直接在 data 上多代理了一层,因此整个过程也会有额外的性能开销。

因此使用该 API 也不会让你可以直接规避掉 vue2 响应式数据定义的约束,因为最终还是用 Object.defineProperty 去做对象拦截,插件同样也提供了 set API 让你去操作对象新增属性等操作。

总结

通过上面的了解,相信你一定对于 Vue2 如何使用 composition API 有了一定的了解,因为 API 相当多, 响应式相关的就还有 toRefs、toRef、unref、shallowRef、triggerRef 等等,这里就不一一分析,有兴趣的可以继续看源码的实现。

Vue2 的同学也可以不用羡慕写 Vue3 的同学了,直接引入到项目就可以使用起来,虽然没有 vue3 那么好的体验,但是绝大部分场景还是相同的,使用时注意 README 文档最后的限制章节,里面讲了一些使用限制。

(学习视频分享:vuejs入门教程编程基础视频

Atas ialah kandungan terperinci Analisis prinsip Vue2 melaksanakan API komposisi. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan