目次
Vue のプラグイン システムのおかげで、
次に、応答性とその理由について話しましょう refおよび reactive はデータをリアクティブにすることもできます。
总结
ホームページ ウェブフロントエンド Vue.js Vue2実装APIの原理を解析する

Vue2実装APIの原理を解析する

Jan 13, 2023 am 08:30 AM
フロントエンド vue.js

Vue2実装APIの原理を解析する

Vue3 のリリース以来、composition API という言葉が、Vue を作成する学生の目に入るようになりました。 composition API は以前の options API よりもはるかに優れているということは誰もが聞いたことがあると思います。@vue/composition-api## のリリースにより、 # プラグイン、 Vue2 学生も参加できます。次に、主にレスポンシブ refreactive を使用して、詳細な分析を行います。このプラグインがこの機能をどのように実装するか。

使い方
// 入口文件引入并注册
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 にも変数とメソッドが含まれています。どうすればよいですか? setup# と同じように実行します。 ## 戻り値はマージされます。 [関連する推奨事項: vuejs ビデオ チュートリアル Web フロントエンド開発 ]

  • vue2

    は、 data 内のデータは応答的に処理されますか? refreactive はどのように行うのでしょうか?

  • vue2

    レスポンシブ データによって定義された制約 (元のオブジェクトに割り当てられていない属性の追加、配列の添字の変更など)、ref# を使用します。 ## 代わりに reactive でよろしいでしょうか?

    もちろん、このプラグインは非常に多くの
  • API
を提供し、

Vue3## のほとんどをカバーしているため、まだ多くの疑問があります。 # has, here 主にこれらの質問からそれがどのように行われるかを分析してみましょう。 原理分析

Vue のプラグイン システムのおかげで、

@vue/composition-api

は次のようになります vue-router および vuex も、公式に提供されるプラグインを通じて挿入されます。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// 这里只贴跟本章要讲的相关代码 funciton mixin (Vue) { Vue.mixin({ beforeCreate: functionApiInit } } function install (Vue) { mixin(Vue); } export const Plugin = { install: (Vue: VueConstructor) =&gt; install(Vue), }</pre><div class="contentsignin">ログイン後にコピー</div></div>Vue プラグインは、

install

メソッドを外部に公開します。use が呼び出されると、このメソッドが呼び出され、 Vue コンストラクターはパラメーターとして渡され、対応するフックでミックスするときに関数を処理するために Vue.mixin が呼び出されます。 次のステップは、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 || {}
  }
ログイン後にコピー

なぜなら、Vue

beforeCreated

にあるからです。 created ライフサイクル中、データは initState によって処理されます。data を処理するとき、$options.data が呼び出され、定義されたデータを取得します。 data. , したがって、関数はここで再ラップされます。これが、beforeCreate フック インジェクションが選択される理由の 1 つです。フック インジェクションは、関数が呼び出される前にラップする必要があります。 次に、initSetup <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>function initSetup(vm: ComponentInstance, props: Record&lt;any, any&gt; = {}) { const setup = vm.$options.setup! const ctx = createSetupContext(vm) const instance = toVue3ComponentInstance(vm) instance.setupContext = ctx def(props, &amp;#39;__ob__&amp;#39;, createObserver()) resolveScopedSlots(vm, ctx.slots) let binding: ReturnType&lt;SetupFunction&lt;Data, Data&gt;&gt; | undefined | null activateCurrentInstance(instance, () =&gt; { binding = setup(props, ctx) }) // setup返回是函数的情况 需要重写render函数 const bindingObj = binding Object.keys(bindingObj).forEach((name) =&gt; { let bindingValue: any = bindingObj[name] // 数据处理 asVmProperty(vm, name, bindingValue) }) return } }</pre><div class="contentsignin">ログイン後にコピー</div></div>この関数は比較的長い関数なので、今回説明する本行以外のコードロジックは削除されています。 ctx を実行し、

vm

インスタンスを Vue3 データ型で定義された instance に変換してから、setup を実行します。関数を使用して戻り値を取得し、トラバースします 各プロパティについて、 asVmProperty を呼び出して vm にマウントします もちろん、ここでのマウントはプロパティと値を直接追加することではありませんvm に同期すると、問題が発生します。つまり、この属性に対する後続の変更を 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
        },
      })
    }
}
ログイン後にコピー
これを見て、setup で定義した戻り値が template

data、## で使用できる理由が理解できたと思います。 # メソッド など。返されたものは vm にプロキシされているためです。 応答性 (ref reactive

実装)

次に、応答性とその理由について話しましょう refおよび reactive はデータをリアクティブにすることもできます。

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 はオブジェクトを受け入れる必要があるため、ここでは ref

key

(つまり ) として定数が使用されています。<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>const value = reactive({ &quot;composition-api.refKey&quot;: row })</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export function createRef&lt;T&gt;( options: RefOption&lt;T&gt;, isReadonly = false, isComputed = false ): RefImpl&lt;T&gt; { const r = new RefImpl&lt;T&gt;(options) const sealed = Object.seal(r) if (isReadonly) readonlySet.set(sealed, true) return sealed } export class RefImpl&lt;T&gt; implements Ref&lt;T&gt; { readonly [_refBrand]!: true public value!: T constructor({ get, set }: RefOption&lt;T&gt;) { proxy(this, &amp;#39;value&amp;#39;, { get, set, }) } }</pre><div class="contentsignin">ログイン後にコピー</div></div><p>通过 <code>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
}
ログイン後にコピー

我们通过 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入门教程编程基础视频

以上がVue2実装APIの原理を解析するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Nodeのメモリ制御に関する記事 Nodeのメモリ制御に関する記事 Apr 26, 2023 pm 05:37 PM

ノンブロッキングおよびイベント駆動に基づいて構築されたノード サービスには、メモリ消費量が少ないという利点があり、大量のネットワーク リクエストの処理に非常に適しています。大量のリクエストを前提として、「メモリ制御」に関する問題を考慮する必要があります。 1. V8 のガベージ コレクション メカニズムとメモリ制限 Js はガベージ コレクション マシンによって制御されます

PHP と Vue: フロントエンド開発ツールの完璧な組み合わせ PHP と Vue: フロントエンド開発ツールの完璧な組み合わせ Mar 16, 2024 pm 12:09 PM

PHP と Vue: フロントエンド開発ツールの完璧な組み合わせ 今日のインターネットの急速な発展の時代において、フロントエンド開発はますます重要になっています。 Web サイトやアプリケーションのエクスペリエンスに対するユーザーの要求がますます高まっているため、フロントエンド開発者は、より効率的で柔軟なツールを使用して、応答性の高いインタラクティブなインターフェイスを作成する必要があります。フロントエンド開発の分野における 2 つの重要なテクノロジーである PHP と Vue.js は、組み合わせることで完璧なツールと見なされます。この記事では、PHP と Vue の組み合わせと、読者がこれら 2 つをよりよく理解し、適用できるようにするための詳細なコード例について説明します。

クロスドメインの問題を解決するにはどうすればよいですか?一般的なソリューションの簡単な分析 クロスドメインの問題を解決するにはどうすればよいですか?一般的なソリューションの簡単な分析 Apr 25, 2023 pm 07:57 PM

クロスドメインは開発においてよく遭遇するシナリオであり、インタビューでもよく議論される問題でもあります。一般的なクロスドメイン ソリューションとその背後にある原則を習得すると、開発効率が向上するだけでなく、面接でのパフォーマンスも向上します。

フロントエンド開発に Go 言語を使用するにはどうすればよいですか? フロントエンド開発に Go 言語を使用するにはどうすればよいですか? Jun 10, 2023 pm 05:00 PM

インターネット技術の発展に伴い、フロントエンド開発の重要性がますます高まっています。特にモバイル デバイスの人気により、効率的で安定しており、安全で保守が容易なフロントエンド開発テクノロジーが必要です。 Go 言語は、急速に発展しているプログラミング言語として、ますます多くの開発者によって使用されています。では、フロントエンド開発に Go 言語を使用することは可能でしょうか?次に、この記事ではフロントエンド開発にGo言語を使用する方法を詳しく説明します。まずはフロントエンド開発にGo言語が使われる理由を見てみましょう。多くの人は Go 言語は

フロントエンドの面接官からよく聞かれる質問 フロントエンドの面接官からよく聞かれる質問 Mar 19, 2024 pm 02:24 PM

フロントエンド開発のインタビューでは、HTML/CSS の基本、JavaScript の基本、フレームワークとライブラリ、プロジェクトの経験、アルゴリズムとデータ構造、パフォーマンスの最適化、クロスドメイン リクエスト、フロントエンド エンジニアリング、デザインパターン、新しいテクノロジーとトレンド。面接官の質問は、候補者の技術スキル、プロジェクトの経験、業界のトレンドの理解を評価するように設計されています。したがって、候補者はこれらの分野で自分の能力と専門知識を証明するために十分な準備をしておく必要があります。

Django はフロントエンドですか、バックエンドですか?それをチェックしてください! Django はフロントエンドですか、バックエンドですか?それをチェックしてください! Jan 19, 2024 am 08:37 AM

Django は、迅速な開発とクリーンなメソッドを重視した Python で書かれた Web アプリケーション フレームワークです。 Django は Web フレームワークですが、Django がフロントエンドなのかバックエンドなのかという質問に答えるには、フロントエンドとバックエンドの概念を深く理解する必要があります。フロントエンドはユーザーが直接対話するインターフェイスを指し、バックエンドはサーバー側プログラムを指し、HTTP プロトコルを通じてデータと対話します。フロントエンドとバックエンドが分離されている場合、フロントエンドとバックエンドのプログラムをそれぞれ独立して開発して、ビジネス ロジックとインタラクティブ効果、およびデータ交換を実装できます。

golang はフロントエンドとして使用できますか? golang はフロントエンドとして使用できますか? Jun 06, 2023 am 09:19 AM

Golang はフロントエンドとして使用できます。Golang は、フロントエンド アプリケーションなど、さまざまなタイプのアプリケーションの開発に使用できる非常に多用途なプログラミング言語です。Golang を使用してフロントエンドを作成することで、 JavaScript などの言語によって引き起こされる一連の問題、たとえば、型安全性の低さ、パフォーマンスの低下、コードの保守の困難などの問題です。

C# 開発経験の共有: フロントエンドとバックエンドの共同開発スキル C# 開発経験の共有: フロントエンドとバックエンドの共同開発スキル Nov 23, 2023 am 10:13 AM

C# 開発者としての私たちの開発作業には、通常、フロントエンドとバックエンドの開発が含まれますが、テクノロジーが発展し、プロジェクトが複雑になるにつれて、フロントエンドとバックエンドの共同開発はますます重要かつ複雑になってきています。この記事では、C# 開発者が開発作業をより効率的に完了できるようにする、フロントエンドとバックエンドの共同開発テクニックをいくつか紹介します。インターフェイスの仕様を決定した後、フロントエンドとバックエンドの共同開発は API インターフェイスの相互作用から切り離せません。フロントエンドとバックエンドの共同開発をスムーズに進めるためには、適切なインターフェース仕様を定義することが最も重要です。インターフェイスの仕様にはインターフェイスの名前が含まれます

See all articles