ホームページ >ウェブフロントエンド >Vue.js >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 } } })
vue3 とまったく同じように感じますか?次のように思うかもしれません:
vue2 です。ああ、以前の
data と
methods にも変数とメソッドが含まれています。どうすればよいですか?
setup# と同じように実行します。 ## 戻り値はマージされます。 [関連する推奨事項: vuejs ビデオ チュートリアル
、Web フロントエンド開発 ]
は、 data
内のデータは応答的に処理されますか? ref
と reactive
はどのように行うのでしょうか?
レスポンシブ データによって定義された制約 (元のオブジェクトに割り当てられていない属性の追加、配列の添字の変更など)、ref# を使用します。 ## 代わりに
reactive でよろしいでしょうか?
Vue3## のほとんどをカバーしているため、まだ多くの疑問があります。 # has, here 主にこれらの質問からそれがどのように行われるかを分析してみましょう。 原理分析
は次のようになります vue-router
および vuex
も、公式に提供されるプラグインを通じて挿入されます。 <pre class="brush:js;toolbar:false;">// 这里只贴跟本章要讲的相关代码
funciton mixin (Vue) {
Vue.mixin({
beforeCreate: functionApiInit
}
}
function install (Vue) {
mixin(Vue);
}
export const Plugin = {
install: (Vue: VueConstructor) => install(Vue),
}</pre>
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
<pre class="brush:js;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>
この関数は比較的長い関数なので、今回説明する本行以外のコードロジックは削除されています。 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
の
(つまり ) として定数が使用されています。<pre class="brush:js;toolbar:false;">const value = reactive({
"composition-api.refKey": row
})</pre><pre class="brush:js;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><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 サイトの他の関連記事を参照してください。