Code Monkey home page Code Monkey logo

composition-api's Introduction

@vue/composition-api

Vue 2 plugin for Composition API

npm GitHub Workflow Status Minzipped size

English | 中文Composition API Docs

⚠️ With the release of Vue 2.7, which has Composition API built-in, you no longer need this plugin. Thereby this plugin has entered maintenance mode and will only support Vue 2.6 or earlier. This project will reach End of Life by the end of 2022.

Installation

NPM

npm install @vue/composition-api
# or
yarn add @vue/composition-api

You must install @vue/composition-api as a plugin via Vue.use() before you can use the Composition API to compose your component.

import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'

Vue.use(VueCompositionAPI)
// use the APIs
import { ref, reactive } from '@vue/composition-api'

💡 When you migrate to Vue 3, just replacing @vue/composition-api to vue and your code should just work.

CDN

Include @vue/composition-api after Vue and it will install itself automatically.

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/@vue/[email protected]"></script>

@vue/composition-api will be exposed to global variable window.VueCompositionAPI.

const { ref, reactive } = VueCompositionAPI

TypeScript Support

TypeScript version >4.2 is required

To let TypeScript properly infer types inside Vue component options, you need to define components with defineComponent

import { defineComponent } from '@vue/composition-api'

export default defineComponent({
  // type inference enabled
})

JSX/TSX

JSX is now officially supported on vuejs/jsx. You can enable it by following this document. A community maintained version can be found at babel-preset-vca-jsx by @luwanquan.

To support TSX, create a declaration file with the following content in your project.

// file: shim-tsx.d.ts
import Vue, { VNode } from 'vue';
import { ComponentRenderProxy } from '@vue/composition-api';

declare global {
  namespace JSX {
    interface Element extends VNode {}
    interface ElementClass extends ComponentRenderProxy {}
    interface ElementAttributesProperty {
      $props: any; // specify the property name to use
    }
    interface IntrinsicElements {
      [elem: string]: any;
    }
  }
}

SSR

Even if there is no definitive Vue 3 API for SSR yet, this plugin implements the onServerPrefetch lifecycle hook that allows you to use the serverPrefetch hook found in the classic API.

import { onServerPrefetch } from '@vue/composition-api'

export default {
  setup(props, { ssrContext }) {
    const result = ref()

    onServerPrefetch(async () => {
      result.value = await callApi(ssrContext.someId)
    })

    return {
      result,
    }
  }
}

Browser Compatibility

@vue/composition-api supports all modern browsers and IE11+. For lower versions IE you should install WeakMap polyfill (for example from core-js package).

Limitations

✅ Support     ❌ Not Supported

Ref Unwrap

Should NOT use ref in a plain object when working with Array
const a = {
  count: ref(0),
}
const b = reactive({
  list: [a], // `a.count` will not unwrap!!
})

// no unwrap for `count`, `.value` is required
b.list[0].count.value === 0 // true
const b = reactive({
  list: [
    {
      count: ref(0), // no unwrap!!
    },
  ],
})

// no unwrap for `count`, `.value` is required
b.list[0].count.value === 0 // true
Should always use ref in a reactive when working with Array
const a = reactive({
  list: [
    reactive({
      count: ref(0),
    }),
  ]
})
// unwrapped
a.list[0].count === 0 // true

a.list.push(
  reactive({
    count: ref(1),
  })
)
// unwrapped
a.list[1].count === 1 // true

Template Refs

✅ String ref && return it from setup()
<template>
  <div ref="root"></div>
</template>

<script>
  export default {
    setup() {
      const root = ref(null)

      onMounted(() => {
        // the DOM element will be assigned to the ref after initial render
        console.log(root.value) // <div/>
      })

      return {
        root,
      }
    },
  }
</script>
✅ String ref && return it from setup() && Render Function / JSX
export default {
  setup() {
    const root = ref(null)

    onMounted(() => {
      // the DOM element will be assigned to the ref after initial render
      console.log(root.value) // <div/>
    })

    return {
      root,
    }
  },
  render() {
    // with JSX
    return () => <div ref="root" />
  },
}
❌ Function ref
<template>
  <div :ref="el => root = el"></div>
</template>

<script>
  export default {
    setup() {
      const root = ref(null)

      return {
        root,
      }
    },
  }
</script>
❌ Render Function / JSX in setup()
export default {
  setup() {
    const root = ref(null)

    return () =>
      h('div', {
        ref: root,
      })

    // with JSX
    return () => <div ref={root} />
  },
}
⚠️ $refs accessing workaround

⚠️ Warning: The SetupContext.refs won't exist in Vue 3.0. @vue/composition-api provide it as a workaround here.

If you really want to use template refs in this case, you can access vm.$refs via SetupContext.refs

export default {
  setup(initProps, setupContext) {
    const refs = setupContext.refs
    onMounted(() => {
      // the DOM element will be assigned to the ref after initial render
      console.log(refs.root) // <div/>
    })

    return () =>
      h('div', {
        ref: 'root',
      })

    // with JSX
    return () => <div ref="root" />
  },
}

Reactive

⚠️ reactive() mutates the original object

reactive uses Vue.observable underneath which will mutate the original object.

💡 In Vue 3, it will return a new proxy object.

⚠️ set and del workaround for adding and deleting reactive properties

⚠️ Warning: set and del do NOT exist in Vue 3. We provide them as a workaround here, due to the limitation of Vue 2.x reactivity system.

In Vue 2, you will need to call set to track new keys on an object(similar to Vue.set but for reactive objects created by the Composition API). In Vue 3, you can just assign them like normal objects.

Similarly, in Vue 2 you will need to call del to ensure a key deletion triggers view updates in reactive objects (similar to Vue.delete but for reactive objects created by the Composition API). In Vue 3 you can just delete them by calling delete foo.bar.

import { reactive, set, del } from '@vue/composition-api'

const a = reactive({
  foo: 1
})

// add new reactive key
set(a, 'bar', 1)

// remove a key and trigger reactivity
del(a, 'bar')

Watch

onTrack and onTrigger are not available in WatchOptions
watch(() => {
    /* ... */
}, {
  immediate: true,
  onTrack() {}, // not available
  onTrigger() {}, // not available
})

createApp

⚠️ createApp() is global

In Vue 3, createApp() is introduced to provide context(plugin, components, etc.) isolation between app instances. Due the design of Vue 2, in this plugin, we provide createApp() as a forward compatible API which is just an alias of the global.

const app1 = createApp(RootComponent1)
app1.component('Foo', Foo) // equivalent to Vue.component('Foo', Foo)
app1.use(VueRouter) // equivalent to Vue.use(VueRouter)

const app2 = createApp(RootComponent2)
app2.component('Bar', Bar) // equivalent to Vue.component('Bar', Bar)

createElement / h

⚠️ createElement / h workaround

createElement / h in Vue 2 is only accessable in render() function. To use it outside of render(), you can explicitly bind a component instance to it.

⚠️ Warning: This ability is provided as a workaround Vue 2, it's not part of the Vue 3 API.

import { h as _h } from '@vue/composition-api'

export default {
  setup() {
    const vm = getCurrentInstance()
    const h = _h.bind(vm)

    return () =>
      h('div', {
        ref: 'root',
      })
  },
}

shallowReadonly

⚠️ shallowReadonly() will create a new object and with the same root properties, new properties added will not be readonly or reactive.

💡 In Vue 3, it will return a new proxy object.

readonly

⚠️ readonly() provides only type-level readonly check.

readonly() is provided as API alignment with Vue 3 on type-level only. Use isReadonly() on it or it's properties can not be guaranteed.

props

⚠️ toRefs(props.foo) will incorrectly warn when accessing nested levels of props.
    ⚠️ isReactive(props.foo) will return false.
defineComponent({
  setup(props) {
    const { bar } = toRefs(props.foo) // it will `warn`

    // use this instead
    const { foo } = toRefs(props)
    const a = foo.value.bar
  }
})

computed().effect

⚠️ computed() has a property effect set to true instead of a ReactiveEffect.

Due to the difference in implementation, there is no such concept as a ReactiveEffect in @vue/composition-api. Therefore, effect is merely true to enable differentiating computed from refs:

function isComputed<T>(o: ComputedRef<T> | unknown): o is ComputedRef<T>
function isComputed(o: any): o is ComputedRef {
  return !!(isRef(o) && o.effect)
}

Missing APIs

The following APIs introduced in Vue 3 are not available in this plugin.

  • onRenderTracked
  • onRenderTriggered
  • isProxy

Reactive APIs in data()

❌ Passing ref, reactive or other reactive apis to data() would not work.
export default {
  data() {
    return {
      // will result { a: { value: 1 } } in template
      a: ref(1),
    }
  },
}

emits Options

emits option is provided in type-level only, in order to align with Vue 3's type interface. Does NOT have actual effects on the code.
defineComponent({
  emits: {
    // has no effects
    submit: (eventOption) => {
      if (...) {
        return true
      } else {
        console.warn('Invalid submit event payload!')
        return false
      }
    }
  }
})

Performance Impact

Due the limitation of Vue2's public API. @vue/composition-api inevitably introduces some performance overhead. Note that in most scenarios, this shouldn't be the source of performance issues.

You can check the benchmark results for more details.

composition-api's People

Contributors

antfu avatar brenner8023 avatar chearon avatar dev-itsheng avatar digitorum avatar djaler avatar edwardnyc avatar hyf0 avatar jspoetry avatar kahirokunn avatar kidonng avatar kiroushi avatar leafstark avatar liaoyinglong avatar linusborg avatar liximomo avatar mannil avatar minatohikari avatar mister-hope avatar pikax avatar popolan1986 avatar posva avatar sapphi-red avatar shaonialife avatar sodatea avatar twithers avatar webfansplz avatar xiaoxiangmoe avatar ygj6 avatar yoyo930021 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

composition-api's Issues

provide() can be called only once per component

I've been testing out this new API, and found that provide() can be called only once per component. If there are more than one call to provide() (whether in setup() or hook functions), the latest provide() call seems to override all changes made by previous provide() calls. I believe this should be fixed.

To test this out, you can take a look at App.vue inside my code sandbox. If you uncomment the second provide() line, the app will spit out injection error.

provide / inject not found , overwrite by plugins.

Hi team!

i am using vue-function-api as proxy to make project in Vue2 with Vue3 api style. Today i found issue with provide / inject:

first please see this code snippet :
provide / inject failed jsfiddle demo

step:

  1. run code, the preview box show white card html withthout any content.
  2. in js box remove / comment the line : Vue.use(VeeValidate, { inject: false }).
  3. run code, now inside white card show content injected.

Please see that in vee-validate plugin they allow disable auto-inject feature with option inject: false. But i dont know why provide() result replaced by other plugin, and dont know what vee-validate did underground.

other attention is: if use Vue2.x provide style :

{
    provide: {
       T: { ok: true }
    }
}

then we can inject use inject() at any child component no issue!

[vue-function-api] "onMounted" get called outside of "setup()"

I am trying to create a hook:

import { value, computed, watch, onMounted } from 'vue-function-api';

export function useIntersectionObserver() {

    let intersectionObserver;

    const entry = value({});

    const callback = (entries) => {
        if (entries.length > 0) {
            entry.value = entries[entries.length - 1];
        }
    };

    onMounted(() => {
        intersectionObserver = new IntersectionObserver(callback);
        ...
    });

    onUnmounted(() => {
        intersectionObserver.disconnect();
    });

    return {
        isIntersecting: computed(() => entry.isIntersecting)
    };
}

And use that in some component:

  import { value, computed, watch, onMounted } from 'vue-function-api';
  import useIntersectionObserver from '...';

  export default {
    setup() {

      useIntersectionObserver();
    }
  }

Yet, I get the error:

[vue-function-api] "onMounted" get called outside of "setup()" 

Why is that, and how can I prevent this?

what dose setCurrentVM function doing

Hey gays, I am learning the source code.
and i see the setCurrentVM uesd in setup.ts like:

...
    let preVm = getCurrentVM();
    setCurrentVM(vm);
    try {
      binding = setup(props, ctx);
    } catch (err) {
      logError(err, vm, 'setup()');
    } finally {
      setCurrentVM(preVm);
    }
...

I not sure why here need to set the vm before call setup and reset the vm in finally section .

Can anyone help me to understand waht this is doing?
thx.

Move to @vue/

Wouldn't it make more sense to move this package to @vue/function-api to keep in line with the other official Vue packages?

Cannot work with CSS Modules

<script>
  export default {
    props: {
      themeName: String
    },

    computed: {
      $theme () {
        return this[this.themeName]
      }
    }
  }
</script>

<style module="$a">
  .wrapper {
    background: #000;
  }
</style>

<style module="$b">
  .wrapper {
    background: #fff;
  }
</style>

setup (props, context) cannot work with CSS Modules, because context does not has property $a or $b.

unit test with typescript guide

How to make unit test using jest / mocha with typescript?
@vue/test-utils/shallowMount(component) => wrapper.vm.* does not contain type definitions which are returned from component so I cannot access anything even if returned data from setup exists in the browser when logging component to console.
Could someone provide an example please?

For example how to test returned values from setup?

export default {
  setup(){
    return { testThis: true };
  }
}

"x" get called outside of "setup()" error if you have different versions of `vue-function-api`

I am using a library X that uses [email protected] and my own app uses [email protected]

this creates 2 separate vue-function-api.

one in node_modules/vue-function-api (v2.1.2)
and another one in node_modules/X/node_modules/vue-function-api (v2.1.1)

I noticed vue-function-api uses a variable that is scoped within the package, when library X uses inject or provide, and you use it in your app, it will error out.

e.g.

// library X using [email protected]
export function useX() {
  const provider = inject<XProvider>(X_PROVIDER_KEY);
  if (!provider) {
    throw new Error('Unable to find provider');
  }
  return provider.value;
}

// app that uses [email protected]
export default Vue.extend({
  setup(props, context) {
    useX() // error, inject is called outside of setup
  }
});

Methon breaking changes in release and make this package vue2compatable

It has been 3 days after I commented in #62.
In my option, there should fewer breaking change. We should not start a breaking change as long as we can solve it, not open as much changes as we can. For examaple the name and components options , will probably inherited from vue 2, while now this package force us to hack it.

I really you should consider it carefully. Some users like me couldn't afford hacking and rehacking again and again while releasing new version.

How to access the element (aka $el) reference?

This is more a clarification on how would one (or should one?) access what's now presented as the this.$el HTML root template element.

Have I missed it in the RFC?

My workaround is to manually add an ref="el" to the root template element and use context.refs.el in, say, the onMounted callback.

the `components` option in createComponent() doesn't support vue2 options

After I updated to 2.2.0, I found that when I run npm run serve, the develop server console ouput is just like this:

And I cannot run npm run build, the process will crash because of the error.

However, the browser console didn't show any errors, and it can run normally. So I cannot simply reproduce it online... In fact, I just create the project with vue-cli3, and change App.vue to this:

<script lang="ts">
    import {createComponent} from 'vue-function-api';
    import HelloWorld from './components/HelloWorld.vue';

    export default createComponent({
        components: {HelloWorld}
    });
</script>

I read the RFC again, and maybe 3.x will continue to be compatible with the 2.x components option?

And when I went back to 2.1.2, the type error disappeared. Did I go something wrong? Or how can I import and use *.vue components correctly?

Component API in refs

Hey! There is some way to use component methods, when you get it from refs?. Example:

// Input component
export default createComponent({
  setup() {
    function validate() { awesome validation }
    return { validate };
  }
})

// in some components with inputs

export default createComponent({
  setup(props, vm) {
    function create() {
      // This refs hasn't my validate method
      vm.refs.myCustomInputComponent.validate();
    }
    return { create };
  }
})

createComponent in TypeScript not inherit from Vue ComponentOptions

from Vue 2.x , when use with TypeScript we always write shims file d.ts whichs support static type property used inside vue component object.
ex: in Nuxt, each component use as page need defined $options.layout = 'layout name' like this:

{
    name: 'page',
    layout: 'myLayout'
}

To typesafe this custom property, they provide d.ts:

// ComponentOptions is declared in types/options.d.ts
declare module 'vue/types/options' {
  interface ComponentOptions<V extends Vue> {
    layout?: string
  }
}

For now vue-function-api provide function createComponent to help TS's developer can inherit typesafe from package. View d.ts file i see function defined:

export declare function createComponent<PropsOptions, RawBindings>(options: ComponentOptions<PropsOptions, RawBindings>): VueProxy<PropsOptions, RawBindings>;

export interface ComponentOptions<PropsOptions = ComponentPropsOptions, RawBindings = Data, Props = ExtractPropTypes<PropsOptions>> {
    props?: PropsOptions;
    setup?: SetupFunction<Props, RawBindings>;
}

This not inherit from Vue ComponentOptions , so we lost all typesafe from shims file.

A modify d.ts code will help a lot to inherit from Vue 2.x setup env .
Thankyou!

Error: [vue-function-api] "onCreated" get called outside of "setup()"

The hook is not working properly

import {value, computed, watch, onMounted, onDestroyed, onCreated, state, createComponent} from 'vue-function-api';
    import Vue from 'vue';

    const MessageComponent = {
        setup() {
            const msg = value('hello');
            onMounted(() => console.log('hello'));
            return {
                msg
            };
        }
    };
    export default createComponent({
        setup() {
            const Message = Vue.extend(MessageComponent);
            const message = new Message();
            onCreated(() => console.log('create message'));
            return {};
        }
    });

Error: [vue-function-api] "onCreated" get called outside of "setup()"

Examples with vuex (mapState), router inside setup()

In Vue 2.x we can use this.$store and this.$router, inside setup, we should use context.store or something? The only way I could use it is import the store in every SFC, but I prefer have global access, like in Vue 2.x if it's possible... thanks!

lack of life cycle method `serverPrefetch`

There is no life cycle method serverPrefetch , so can not be fully used on SSR.

In order to support SSR, the only choice is to remain serverPrefetch() method. And then, all methods and data properties used by serverPrefetch() has to be remained. And then, very little code can be ported into setup() method. And the code is in "mixed style", very ugly.

Do you support TypeScript-only Props Typing?

This specification.
https://github.com/vuejs/rfcs/blob/function-apis/active-rfcs/0000-function-api.md#typescript-only-props-typing

This component's props will be an empty object.

<template>
  <div> <!-- There is a div to prevent inheritance -->
    <button :type="type" :disabled="disabled"><slot /></button>
  </div>
</template>

<script lang="ts">
import { createComponent } from 'vue-function-api';

type Props = {
  type?: 'button' | 'submit';
  disabled?: boolean;
};

export default createComponent({
  setup(props: Props) {
    console.log(props); // Empty object {}
    const { type = 'button', disabled = false } = props;
    return {
      type,
      disabled,
    };
  },
});
</script>

The new watch is different from the old

create demo with cli, add code into App.vue

import { watch } from 'vue-function-api'

export default {
  watch: {
    $route: {
      handler: function (val, oldVal) {
        console.log('oldWatch: ', val)
      },
      immediate: true
    }
  },
  setup (props, ctx) {
    const { $route } = ctx.root

    watch(() => $route, (val, oldVal) => {
      console.log('newWatch: ', val)
    })
  }
}

the browser console output:
深度截图_选择区域_20190801110429

How to extends the context with e.g. $axios?

How to extend the context with own attrs? I use the Quasar framework with TypeScript and I can extends Vue instance with prototype inheritance.


export default async ({ Vue }) => {
  Vue.prototype.$axios = axios
}

declare module 'vue/types/vue' {
  interface Vue {
    $axios: AxiosStatic;
  }
}

Unfortunately, context.root contains Vue instance but it does not contain any prototyped extensions. :(

Local Component Access on Context Param

I've been playing with the new API the past couple days and really enjoy it. Thank you for all the work.

I may have missed it, or there is an alternate method to access the local component from within the setup function, but I have not been able to determine it.

From the RFC, it makes sense:

setup() {
  function onClick() {
    this // not the `this` you'd expect!
  }
}

The request is to either make it more clear how to access the local component for less astute people such as myself or add the functionality. Or perhaps help me understand why I wouldn't want to. An example.

Refs are undefined in setup() outside of lifecycle method

As a follow-up to liximomo/vue-function-api#10 (comment), the refs are now injected, but they can only be accessed inside of a lifecycle method. I don't believe this is the desired usage.

For example, I have a custom hook that binds and removes an event listener to the DOM node passed into it as a parameter. Because my custom hook cannot be called inside of a lifecycle method (because it has lifecycle methods inside of it), I can only call my custom hook at the first level of setup(). I like this functionality, and the errors were clear.

console.log("outside:");
console.log(context.refs.elementKeypress); // undefined

onMounted(() => {
  console.log("inside:");
  console.log(context.refs.elementKeypress); // <div data-v-763db97b="" class="element-keypress-demo">Ref</div>
});

// hook fails to bind event listener to 'undefined'
useElementKeypress("u", context.refs.elementKeypress, () => {
  console.log("clicked!");
});

See my CodeSandbox example

My problem is that the ref is undefined when passing it into the custom hook.

Define reactive state for return of setup() automatically

When setup() return some plain props like this:

const Test = Vue.extend({
  render(h) {
    return h('div', [
      h('span', this.count),
      h('button', {
        on: {
          click: () => this.count++,
        },
      }, 'Increment'),
    ]);
  },
  setup() {
    return { count: 0 };
  },
});

count is not reactive but is attached to vm, so that it becomes a "immutable" state? Anyway, it might confuse the user.
Consider following implemention in src/setup.ts at line 58:

    Object.keys(binding).forEach(name => {
      let bindingValue = binding[name];
      if (!isWrapper(bindingValue)) {
        bindingValue = value(bindingValue);
      }
      bindingValue.setVmProperty(vm, name);
    });

Component created with createComponent() throws a type error when used in a render function

This sandbox reproduces the error I get in App.tsx

https://codesandbox.io/s/vue-function-api-typescript-issue-vrycw

For some reason the sandbox fails to import the components, but the code actually works when opened in vscode.

The code actually works without issue, it's just that typescript complains that JSX element type 'HelloWorld' does not have any construct or call signatures. when using a component declared with createComponent and a render function

Using vue-function-api in a new project

We are new in vue and we want start a new project in next three months. Well we want to make sure that we are choosing the best environment which will be compatible with Vue future development path. And we want to be Vue3 compatible (as much as possible).

According to this plugin and a complete description at related rfc , the next VueJs movement will be toward function API and the Class API RFC is moved a way.

So using Typescript in a vue project ( for example sample mentioned at https://sobolevn.me/2019/06/really-typing-vue ) will not be a good idea.
Am I correct ?

Is it recommended to use function api and typescript together? And is there any sample which can help to get start.

PS: I have read this comment some where (Vue@3 will have improved typescript support), is it still correct?!

Can I use functional api with vuex?

Hi,

I am really eager to try this new api and especially the typescript integration. But can I use this api with vuex? If so could anybody provide an example? 🙂

Thanks!

Typescript props type inference is incorrect

The type of msg should be string, but is inferred to be of type StringConstructor

import { createComponent } from 'vue-function-api'

    const MyComponent = createComponent({
        props: {
            msg: String
        },
        setup(props) {
            console.log(props.msg == '1'); // string | undefined
           // Error:(13, 25) TS2367: This condition will always return 'false' since the types 'StringConstructor' and '"1"' have no overlap.
        }
    })

Type error with string key using provide/inject.

Here is the declaration file:

import { AnyObject } from '../types/basic';
import { Wrapper } from '../wrappers';
export interface Key<T> extends Symbol {
}
export declare function provide(data: AnyObject): void;
export declare function provide<T>(key: Key<T>, value: T | Wrapper<T>): void;
export declare function inject<T>(key: Key<T>): Wrapper<T> | void;

But the doc says:

provide, inject

▸ provide(key: string | symbol, value: any)

▸ inject(key: string | symbol)

Equivalent with provide and inject from 2.x

So when I use string instead of exporting and importing symbols accross file, I got type error.

按照api写的watch不能正常工作

const route = ctx.root.$route;
const parentDeptID = computed(() => route.params.id);
watch(parentDeptID, () => {
console.log(parentDeptID.value);
});

路由更改时候却没有执行console

the onErrorCaptured() hook is not working as expected

I tried to use the the onErrorCaptured hook just as I used it in 2.x: code in CodeSandbox , outputs are in console.

The result is not in line with my expectation. Actually, the error was not captured, and because I usedVue.config.warnHandler, I found that the error was treated as a warn, onErrorCaptured was not called. But if I used it as 2.x, using errorCaptured hook, it works properly. Did I get something wrong? Thanks.

And sorry for my poor English.

how use filters

"export 'filters' was not found in 'vue-function-api';
how use filters api in vue-function-api

Vue-Router navigation guards?

vue-function-api currently lacks support for vue-router in-component navigation guards (beforeRouteEnter, beforeRouteUpdate, and beforeRouteLeave). Any plans to implement them in the near future, or it's out of scope of this project?

[vue-function-api] "setup" must return a "Object", get "Function"

When using the plugin I get this error
[vue-function-api] "setup" must return a "Object", get "Function"

But the RFC says you can return a function from setup for manual renders https://github.com/vuejs/rfcs/blob/function-apis/active-rfcs/0000-function-api.md#usage-with-manual-render-functions

like this

import { value, createElement as h } from 'vue'

const MyComponent = {
  setup(initialProps) {
    const count = value(0)
    const increment = () => { count.value++ }

    return (props, slots, attrs, vnode) => (
      h('button', {
        onClick: increment
      }, count.value)
    )
  }
}

How to access $scopedSlots?

Context supplied to setup only contains slots and this.$scopedSlots doesn't work inside setup.

Is there an official way to access scoped slots?

this.nextTick()

I have been relying on this for a significant part of a QA application I have been writing. Will this be available in some form or another in Vue 3? or should I begin rewriting things in .then()?

Thanks

[TypeScript] Props type infer

I met a problems here. And here is my solution. I wonder if there is any other solution which is better?

props:{
  src: { type: String, required: true }
},
setup(props){
    onMounted(() => {
      const img = new Image(); // Create new Image instance

      img.src = props.src as unknown as string;

      ...
    });
}

Call plugin function

Excuse me, I can't find how call plugin in new Vue API.

import myPlugin from './myPlugin';
Vue.use(myPlugin);

const myPlugin = {
	install(Vue) {
		Vue.prototype.$test = 'test string';
	}
}
export default myPlugin;
<script>
	export default {
		name: 'test',
		setup(props, vm) {
			console.log(vm.$test); //??
		}
	}
</script>

Wrapped array value dont work correctly

codesandbox here

versions: "vue-function-api": "^2.1.1"

<script lang="ts">
import { createComponent, value, Wrapper } from "vue-function-api";

export default createComponent({
  setup(props, context) {

    const tabs: Wrapper<string[]> = value(["tab2"]);
    tabs.value.push("tab3"); // ['tab2', 'tab3']

    // should ['tab1', 'tab2', 'tab3'] but ['tab2', 'tab2', 'tab3']
    tabs.value.unshift("tab1");

    // worked correctly
    const tabs2: string[] = ["tab2"];

    tabs2.push("tab3");

    // ['tab1', 'tab2', 'tab3']
    tabs2.unshift("tab1");

    return {
      tabs,
      tabs2
    };
  }
});
</script>

by the way, version 2.0.6 worked fine

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.