Skip to content

Initial proposal of breaking changes in 3.0Β #2

Closed
@yyx990803

Description

@yyx990803

Changes

Props

Component no longer need to delcare props in order to receive props. Everything passed from parent vnode's data (with the exception of internal properties, i,e. key, ref, slots and nativeOn*) will be available in this.$props and also as the first argument of the render function. This eliminates the need for this.$attrs and this.$listeners.

When no props are declared on a component, props will not be proxied on the component instance and can only be accessed via this.$props or the props argument in render functions.

You still can delcare props in order to specify default values and perform runtime type checking, and it works just like before. Declared props will also be proxied on the component instance. However, the behavior of undeclared props falling through as attrs will be removed; it's as if inheritAttr now defaults to false. The component will be responsible for merging the props as attrs onto the desired element.

VNodes

Flat Data Format

// before
{
  attrs: { id: 'foo' },
  domProps: { innerHTML: '' },
  on: { click: foo },
  key: 'foo',
  ref: 'bar'
}

// after (consistent with JSX usage)
{
  id: 'foo',
  domPropsInnerHTML: '',
  onClick: foo,
  key: 'foo',
  ref: ref => {
    this.$refs.bar = ref
  }
}
  • Less memory allocation & faster diffs
  • Makes it consistent with JSX
  • Easier spread operations

VNodes are now context-free

h can now be globally imported and is no longer bound to component instacnes. VNodes created are also no longer bound to compomnent instances (this means you can no longer access vnode.context to get the component instance that created it)

Component in Render Functions

No longer resolves component by string names; Any h call with a string is considered an element. Components must be resolved before being passed to h.

import { resolveComponent } from 'vue'

render (h) {
  // only necessary when you are trying to access a registered component instead
  // of an imported one
  const Comp = resolveComponent(this, 'foo')
  return h(Comp)
}

In templates, components should be uppercase to differentiate from normal elements.

NOTE: how to tell in browser templates? In compiler, use the following intuitions:

  1. If uppercase -> Component
  2. If known HTML elements -> element
  3. Treat as unknown component - at runtime, try resolving as a component first, if not found, render as element. (resolveComponent returns name string if component is not found)

Slots

Unifying Normnal Slots and Scoped Slots

Scoped slots and normal slots are now unified. There's no more difference between the two. Inside a component, all slots on this.$slots will be functions and all them can be passed arguments.

Usage Syntax Change

// before
h(Comp, [
  h('div', { slot: 'foo' }, 'foo')
  h('div', { slot: 'bar' }, 'bar')
])

// after
h(Comp, () => h('div', 'default slot'))

// or
import { childFlags } from 'vue/flags'

h(Comp, null, {
  slots: {
    foo: () => h('div', 'foo'),
    bar: () => h('div', 'bar')
  }
}, childFlags.COMPILED_SLOTS)

// also works
h(Comp, null, {
  foo: () => h('div', 'foo'),
  bar: () => h('div', 'bar')
})

Functional Component

Functional components can now really be just functions.

// before
const Func = {
  functional: true,
  render (h, ctx) {
    return h('div')
  }
}

// Now can also be:
const Func = (h, props, slots, ctx) => h('div')
Func.pure = true

Async Component

Async components now must be explicitly created.

import { createAsyncComponent } from 'vue'

const AsyncFoo = createAsyncComponent(() => import('./Foo.vue'))

Directives

  • Now are internally on-vnode hooks with the exact same lifecycle as components.

  • Custom directives are now applied via a helper:

import { applyDirective, resolveDirective } from 'vue'

render (h) {
  // equivalent for v-my-dir
  const myDir = resolveDirective(this, 'my-dir')
  return applyDirective(h('div', 'hello'), [[myDir, this.someValue]])
}

Styles

No longer performs auto-prefixing.

Attributes

  • No longer auto coerces boolean or enumerated attribute values.
  • No longer removes attribute if value is boolean false. Instead, it's set as attr="false" instead. To remove the attribute, use null.

Filters

Filters are gone for good (or can it?)

Refs

  • Function refs are now supported.
  • String refs are no longer supported in render functions (now only supported in templates and compiled into function refs)
  • String refs no longer automatically generates an array when used with v-for. Instead, use something like :ref="'foo' + key" or function refs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions