Skip to content

feat: v1.1.0 #780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Aug 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 58 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,68 @@
<a name="1.0.6"></a>
## [1.0.6](https://github.com/vuejs/composition-api/compare/v1.0.5...v1.0.6) (2021-08-09)
<a name="1.1.0-beta.7"></a>
# [1.1.0-beta.7](https://github.com/vuejs/composition-api/compare/v1.1.0-beta.6...v1.1.0-beta.7) (2021-08-09)

### Bug Fixes

* **effectScope:** should have a vaild scope with component ([da21873](https://github.com/vuejs/composition-api/commit/da21873))


<a name="1.1.0-beta.6"></a>
# [1.1.0-beta.6](https://github.com/vuejs/composition-api/compare/v1.1.0-beta.5...v1.1.0-beta.6) (2021-08-09)

* new watchPostEffect api ([92fe90c](https://github.com/vuejs/composition-api/commit/92fe90c))
* support second target argument for lifecycle functions ([0133c1e](https://github.com/vuejs/composition-api/commit/0133c1e))


<a name="1.1.0-beta.4"></a>
# [1.1.0-beta.4](https://github.com/vuejs/composition-api/compare/v1.0.4...v1.1.0-beta.4) (2021-07-22)


### Bug Fixes

* revert module field to `esm.js` version, close [#769](https://github.com/vuejs/composition-api/issues/769) ([92afa6f](https://github.com/vuejs/composition-api/commit/92afa6f))



<a name="1.1.0-beta.3"></a>
# [1.1.0-beta.3](https://github.com/vuejs/composition-api/compare/v1.0.3...v1.1.0-beta.3) (2021-07-18)


### Bug Fixes

* build for mjs and exports all submodules ([c116714](https://github.com/vuejs/composition-api/commit/c116714))



<a name="1.1.0-beta.2"></a>
# [1.1.0-beta.2](https://github.com/vuejs/composition-api/compare/v1.1.0-beta.1...v1.1.0-beta.2) (2021-07-16)


### Bug Fixes

* **effectScope:** should stop along with parent component ([784d96c](https://github.com/vuejs/composition-api/commit/784d96c))



<a name="1.1.0-beta.1"></a>
# [1.1.0-beta.1](https://github.com/vuejs/composition-api/compare/v1.0.2...v1.1.0-beta.1) (2021-07-16)


### Features

* implement `effectScope` api ([#762](https://github.com/vuejs/composition-api/issues/762)) ([fcadec2](https://github.com/vuejs/composition-api/commit/fcadec2))


### Features

* implement `effectScope` api ([#762](https://github.com/vuejs/composition-api/issues/762)) ([fcadec2](https://github.com/vuejs/composition-api/commit/fcadec2))
* support second target argument for lifecycle functions ([3f3b9c6](https://github.com/vuejs/composition-api/commit/3f3b9c6))


<a name="1.0.6"></a>
## [1.0.6](https://github.com/vuejs/composition-api/compare/v1.0.5...v1.0.6) (2021-08-09)


### Features

<a name="1.0.5"></a>
## [1.0.5](https://github.com/vuejs/composition-api/compare/v1.0.4...v1.0.5) (2021-08-01)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Include `@vue/composition-api` after Vue and it will install itself automaticall
<!--cdn-links-start-->
```html
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/@vue/composition-api@1.0.6"></script>
<script src="https://cdn.jsdelivr.net/npm/@vue/composition-api@1.1.0-beta.7"></script>
```
<!--cdn-links-end-->

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { ref, reactive } from '@vue/composition-api'
<!--cdn-links-start-->
```html
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/@vue/composition-api@1.0.6"></script>
<script src="https://cdn.jsdelivr.net/npm/@vue/composition-api@1.1.0-beta.7"></script>
```
<!--cdn-links-end-->

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/composition-api",
"version": "1.0.6",
"version": "1.1.0-beta.7",
"description": "Provide logic composition capabilities for Vue.",
"keywords": [
"vue",
Expand Down Expand Up @@ -42,7 +42,7 @@
"update-readme": "node ./scripts/update-readme.js",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"version": "yarn changelog && yarn update-readme && git add CHANGELOG.md README.*",
"release": "yarn version && yarn test && yarn publish --non-interactive && git push --follow-tags",
"release": "yarn version && yarn test && yarn publish --non-interactive --tag next && git push --follow-tags",
"release-gh": "conventional-github-releaser -p angular"
},
"bugs": {
Expand Down
5 changes: 3 additions & 2 deletions src/apis/computed.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getVueConstructor, getCurrentInstance } from '../runtimeContext'
import { getVueConstructor } from '../runtimeContext'
import { createRef, Ref } from '../reactivity'
import {
warn,
Expand All @@ -7,6 +7,7 @@ import {
getVueInternalClasses,
isFunction,
} from '../utils'
import { getCurrentScopeVM } from './effectScope'

export interface ComputedRef<T = any> extends WritableComputedRef<T> {
readonly value: T
Expand All @@ -32,7 +33,7 @@ export function computed<T>(
export function computed<T>(
getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>
): ComputedRef<T> | WritableComputedRef<T> {
const vm = getCurrentInstance()?.proxy
const vm = getCurrentScopeVM()
let getter: ComputedGetter<T>
let setter: ComputedSetter<T> | undefined

Expand Down
130 changes: 130 additions & 0 deletions src/apis/effectScope.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import {
ComponentInternalInstance,
getCurrentInstance,
getVueConstructor,
withCurrentInstanceTrackingDisabled,
} from '../runtimeContext'
import { defineComponentInstance } from '../utils'
import { warn } from './warn'

let activeEffectScope: EffectScope | undefined
const effectScopeStack: EffectScope[] = []

class EffectScopeImpl {
active = true
effects: EffectScope[] = []
cleanups: (() => void)[] = []

/**
* @internal
**/
vm: Vue

constructor(vm: Vue) {
this.vm = vm
}

run<T>(fn: () => T): T | undefined {
if (this.active) {
try {
this.on()
return fn()
} finally {
this.off()
}
} else if (__DEV__) {
warn(`cannot run an inactive effect scope.`)
}
return
}

on() {
if (this.active) {
effectScopeStack.push(this)
activeEffectScope = this
}
}

off() {
if (this.active) {
effectScopeStack.pop()
activeEffectScope = effectScopeStack[effectScopeStack.length - 1]
}
}

stop() {
if (this.active) {
this.vm.$destroy()
this.effects.forEach((e) => e.stop())
this.cleanups.forEach((cleanup) => cleanup())
this.active = false
}
}
}

export class EffectScope extends EffectScopeImpl {
constructor(detached = false) {
let vm: Vue = undefined!
withCurrentInstanceTrackingDisabled(() => {
vm = defineComponentInstance(getVueConstructor())
})
super(vm)
if (!detached) {
recordEffectScope(this)
}
}
}

export function recordEffectScope(
effect: EffectScope,
scope?: EffectScope | null
) {
scope = scope || activeEffectScope
if (scope && scope.active) {
scope.effects.push(effect)
return
}
// destory on parent component unmounted
const vm = getCurrentInstance()?.proxy
vm && vm.$on('hook:destroyed', () => effect.stop())
}

export function effectScope(detached?: boolean) {
return new EffectScope(detached)
}

export function getCurrentScope() {
return activeEffectScope
}

export function onScopeDispose(fn: () => void) {
if (activeEffectScope) {
activeEffectScope.cleanups.push(fn)
} else if (__DEV__) {
warn(
`onDispose() is called when there is no active effect scope ` +
` to be associated with.`
)
}
}

/**
* @internal
**/
export function getCurrentScopeVM() {
return getCurrentScope()?.vm || getCurrentInstance()?.proxy
}

/**
* @internal
**/
export function bindCurrentScopeToVM(
vm: ComponentInternalInstance
): EffectScope {
if (!vm.scope) {
const scope = new EffectScopeImpl(vm.proxy) as EffectScope
vm.scope = scope
vm.proxy.$on('hook:destroyed', () => scope.stop())
}
return vm.scope
}
19 changes: 18 additions & 1 deletion src/apis/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
export * from '../reactivity'
export * from './lifecycle'
export {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
onErrorCaptured,
onActivated,
onDeactivated,
onServerPrefetch,
} from './lifecycle'
export * from './watch'
export * from './computed'
export * from './inject'
Expand All @@ -8,3 +19,9 @@ export { App, createApp } from './createApp'
export { nextTick } from './nextTick'
export { createElement as h } from './createElement'
export { warn } from './warn'
export {
effectScope,
EffectScope,
getCurrentScope,
onScopeDispose,
} from './effectScope'
10 changes: 8 additions & 2 deletions src/apis/inject.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { ComponentInstance } from '../component'
import { hasOwn, warn, currentVMInFn, isFunction, proxy } from '../utils'
import {
hasOwn,
warn,
getCurrentInstanceForFn,
isFunction,
proxy,
} from '../utils'
import { getCurrentInstance } from '../runtimeContext'

const NOT_FOUND = {}
Expand All @@ -23,7 +29,7 @@ function resolveInject(
}

export function provide<T>(key: InjectionKey<T> | string, value: T): void {
const vm: any = currentVMInFn('provide')
const vm: any = getCurrentInstanceForFn('provide')?.proxy
if (!vm) return

if (!vm._provided) {
Expand Down
26 changes: 14 additions & 12 deletions src/apis/lifecycle.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,51 @@
import { VueConstructor } from 'vue'
import { ComponentInstance } from '../component'
import {
getVueConstructor,
setCurrentInstance,
getCurrentInstance,
ComponentInternalInstance,
} from '../runtimeContext'
import { currentVMInFn } from '../utils/helper'
import { getCurrentInstanceForFn } from '../utils/helper'

const genName = (name: string) => `on${name[0].toUpperCase() + name.slice(1)}`
function createLifeCycle(lifeCyclehook: string) {
return (callback: Function, target?: ComponentInternalInstance | null) => {
const vm = currentVMInFn(genName(lifeCyclehook), target)
const instance = getCurrentInstanceForFn(genName(lifeCyclehook), target)
return (
vm && injectHookOption(getVueConstructor(), vm, lifeCyclehook, callback)
instance &&
injectHookOption(getVueConstructor(), instance, lifeCyclehook, callback)
)
}
}

function injectHookOption(
Vue: VueConstructor,
vm: ComponentInstance,
instance: ComponentInternalInstance,
hook: string,
val: Function
) {
const options = vm.$options as Record<string, unknown>
const options = instance.proxy.$options as Record<string, unknown>
const mergeFn = Vue.config.optionMergeStrategies[hook]
const wrappedHook = wrapHookCall(vm, val)
const wrappedHook = wrapHookCall(instance, val)
options[hook] = mergeFn(options[hook], wrappedHook)
return wrappedHook
}

function wrapHookCall(vm: ComponentInstance, fn: Function): Function {
function wrapHookCall(
instance: ComponentInternalInstance,
fn: Function
): Function {
return (...args: any) => {
let preVm = getCurrentInstance()?.proxy
setCurrentInstance(vm)
let prev = getCurrentInstance()
setCurrentInstance(instance)
try {
return fn(...args)
} finally {
setCurrentInstance(preVm!)
setCurrentInstance(prev)
}
}
}

// export const onCreated = createLifeCycle('created');
export const onBeforeMount = createLifeCycle('beforeMount')
export const onMounted = createLifeCycle('mounted')
export const onBeforeUpdate = createLifeCycle('beforeUpdate')
Expand Down
Loading