Vue2実装APIの原理を解析する
Vue3
のリリース以来、composition API
という言葉が、Vue
を作成する学生の目に入るようになりました。 composition API
は以前の options API
よりもはるかに優れているということは誰もが聞いたことがあると思います。@vue/composition-api## のリリースにより、 # プラグイン、
Vue2 学生も参加できます。次に、主にレスポンシブ
ref と
reactive を使用して、詳細な分析を行います。このプラグインがこの機能をどのように実装するか。
使い方// 入口文件引入并注册
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
}
}
})
ログイン後にコピー
どうですか?読んだ後、// 入口文件引入并注册 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# と同じように実行します。 ## 戻り値はマージされます。 [関連する推奨事項:vuejs ビデオ チュートリアル
、Web フロントエンド開発 ] - vue2
は、
data
内のデータは応答的に処理されますか?ref
とreactive
はどのように行うのでしょうか? - 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) => install(Vue),
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
Vue
プラグインは、
メソッドを外部に公開します。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
は
と にあるからです。 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<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
}
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
この関数は比較的長い関数なので、今回説明する本行以外のコードロジックは削除されています。 ctx
を実行し、
インスタンスを 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
の
(つまり ) として定数が使用されています。<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>const value = reactive({
"composition-api.refKey": 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<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,
})
}
}</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
-> proxy
到 setup
里面的 foo
-> observed
的 foo
,完成取值的流程,这会比直接在 data
上多代理了一层,因此整个过程也会有额外的性能开销。
因此使用该 API
也不会让你可以直接规避掉 vue2
响应式数据定义的约束,因为最终还是用 Object.defineProperty
去做对象拦截,插件同样也提供了 set API
让你去操作对象新增属性等操作。
总结
通过上面的了解,相信你一定对于 Vue2
如何使用 composition API
有了一定的了解,因为 API
相当多, 响应式相关的就还有 toRefs、toRef、unref、shallowRef、triggerRef
等等,这里就不一一分析,有兴趣的可以继续看源码的实现。
写 Vue2
的同学也可以不用羡慕写 Vue3
的同学了,直接引入到项目就可以使用起来,虽然没有 vue3
那么好的体验,但是绝大部分场景还是相同的,使用时注意 README
文档最后的限制章节,里面讲了一些使用限制。
以上がVue2実装APIの原理を解析するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

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

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

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

ホットトピック









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

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

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

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

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

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

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

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