Skip to content

v3.1.0 Pluto

Choose a tag to compare
@github-actions github-actions released this 07 Jun 16:39


  • Migration Build: a build of Vue 3 that provides Vue 2 compatible behavior. The Migration Build is intended to help migrating existing Vue 2 apps to Vue 3.
  • compiler-core: whitespace handling strategy (dee3d6a)
  • support component-level compilerOptions when using runtime compiler (ce0bbe0)
  • config: support configuring runtime compiler via app.config.compilerOptions (091e6d6)
  • support casting plain element to component via is="vue:xxx" (af9e699)
  • devtools: improved KeepAlive support (03ae300)
  • devtools: performance events (f7c54ca)
  • onServerPrefetch (#3070) (349eb0f)

Performance Improvements

  • only trigger $attrs update when it has actually changed (5566d39)
  • compiler: skip unncessary checks when parsing end tag (048ac29)
  • avoid deopt for props/emits normalization when global mixins are used (51d2be2)


  • app.config.isCustomElement has been deprecated and should be now nested under app.config.compilerOptions. [Docs]
  • delimiters component option has been deprecated and should now be nested under the compilerOptions component option. [Docs]
  • v-is has been deprecated in favor of is="vue:xxx" [Docs]

Minor Breaking Changes

  • this.$props and the props object passed to setup() now always contain all the keys for declared props, even for props that are absent (4fe4de0). This has always been the behavior in Vue 2 and is therefore considered a fix (see reasoning in #3288). However, this could break Vue 3 code that relied on the keys for prop absence checks. The workaround is to use a Symbol default value for props that need absence checks:

    const isAbsent = Symbol()
    export default {
      props: {
        foo: { default: isAbsent }
      setup(props) {
        if ( === isAbsent) {
          // foo is absent
  • optionMergeStrategies functions no longer receive
    the component instance as the 3rd argument. The argument was technically
    internal in Vue 2 and only used for generating warnings, and should not
    be needed in userland code. This removal enables much more efficient
    caching of option merging.

Bug Fixes

  • compat: revert private properties on $options in comapt mode (ad844cf), closes #3883
  • runtime-core: fix fragment update inside de-opt slots (5bce2ae), closes #3881
  • compat: fix deep data merge with extended constructor (c7efb96), closes #3852
  • compiler-sfc: fix style injection when using normal script + setup (8b94464), closes #3688
  • compiler-sfc: fix template expression assignment codegen for script setup let refs (#3626) (2c7bd42), closes #3625
  • runtime-core: align option merge behavior with Vue 2 (e2ca67b), closes #3566 #2791
  • runtime-dom/v-model: only set selectedIndex when the value changes (#3845) (ecd97ee)
  • suspense: fix suspense regression for errored template component (44996d1), closes #3857
  • watch: avoid traversing objects that are marked non-reactive (9acc9a1)
  • compiler-core: improve the isMemberExpression function (#3675) (9b2e894)
  • compiler-dom: fix in-browser attribute value decoding w/ html tags (6690372), closes #3001
  • compiler-sfc: correctly remove parens used for wrapping (#3582) (6bfb50a), closes #3581
  • reactivity: ensure computed always expose value (03a7a73), closes #3099 #910
  • runtime-core: fix cases of reused children arrays in render functions (#3670) (a641eb2), closes #3666
  • runtime-core: fix resolving inheritAttrs from mixins (#3742) (d6607c9), closes #3741
  • runtime-core: should disable tracking inside directive lifecycle hooks (#3699) (ff50e8d)
  • runtime-core: stricter compat root mount check (32e2133)
  • runtime-dom: should remove attribute when binding null to value (#3564) (e3f5dcb)
  • suspense: fix suspense patching in optimized mode (9f24195), closes #3828
  • transition: fix higher order transition components with merged listeners (071986a), closes #3227
  • keep-alive: include/exclude should work with async component (#3531) (9e3708c), closes #3529
  • runtime-core: properly check forwarded slots type (#3781) (e8ddf86), closes #3779
  • runtime-core: should not track dynamic children when the user calls a compiled slot inside template expression (#3554) (2010607), closes #3548 #3569
  • runtime-core/teleport: ensure the nested teleport can be unmounted correctly (#3629) (4e3f82f), closes #3623
  • scheduler: handle preFlush cb queued inside postFlush cb (b57e995), closes #3806
  • ssr: handle hydrated async component unmounted before resolve (b46a4dc), closes #3787
  • watch: should not leak this context to setup watch getters (1526f94), closes #3603
  • compat: avoid accidentally delete the modelValue prop (#3772) (4f17be7)
  • compat: enum coercion warning (#3755) (f01aadf)
  • compiler-core: fix whitespace management for slots with whitespace: 'preserve' (#3767) (47da921), closes #3766
  • compiler-dom: comments in the v-if branchs should be ignored when used in Transition (#3622) (7c74feb), closes #3619
  • compiler-sfc: support tsx in setup script (#3825) (01e8ba8), closes #3808
  • compiler-ssr: disable hoisting in compiler-ssr (3ef1fcc), closes #3536
  • devtools: send update to component owning the slot (1355ee2)
  • runtime-core: avoid double-setting props when casting (0255be2), closes #3371 #3384
  • runtime-core: avoid the proxy object polluting the slots of the internal instance (#3698) (4ce0df6), closes #3695
  • types: declared prop keys should always exist in props argument (#3726) (9b160b9)
  • types/reactivity: error TS4058 caused by RefSymbol (#2548) (90aa835)
  • compat: correctly merge lifecycle hooks when using Vue.extend (#3762) (2bfb8b5), closes #3761
  • compiler-core: bail out to array children when the element has custom directives + only one text child node (#3757) (a56ab14)
  • compat: handle and warn config.optionMergeStrategies (94e69fd)
  • compiler-core: preserve comment content in production when comments option is enabled (e486254)
  • hmr: don't remove __file key from component type (9db3cbb)
  • hydration: fix update before async component is hydrated (#3563) (c8d9683), closes #3560
  • reactivity: fix tracking for readonly + reactive Map (#3604) (5036c51), closes #3602
  • runtime-core: ensure declare prop keys are always present (4fe4de0), closes #3288
  • runtime-core: watching multiple sources: computed (#3066) (e7300eb), closes #3068
  • Teleport: avoid changing the reference of vnode.dynamicChildren (#3642) (43f7815), closes #3641
  • watch: avoid traversing non-plain objects (62b8f4a)
  • watch: this.$watch should support watching keypath (870f2a7)