dynamic-directive-arguments

Since directive parameters are static, current users will have to think of dynamic representations of properties and methods

<! -- v-bind with dynamic key --> <div v-bind:[key]="value"></div> <! -- v-bind shorthand with dynamic key --> <div :[key]="value"></div> <! -- v-on with dynamic event --> <div v-on:[event]="handler"></div> <! -- v-on shorthand with dynamic event --> <div @[event]="handler"></div> <! -- v-slot with dynamic name --> <foo> <template v-slot:[name]> Hello </template> </foo> <! -- v-slot shorthand with dynamic name --> <! -- pending #3 --> <foo> <template #[name]> Default slot </template> </foo>Copy the code

treeshaking

As the Vue API has grown, efforts have been made to balance features and reduce bundle sizes. Officials want to keep the size of Vue to a minimum, but don’t want to limit its functionality due to size limitations.

With the friendly setup of the ES module’s static analysis, Treeshaking can compile only the apis that are packaged for use

import Vue, { nextTick, observable } from 'vue'

Vue.nextTick // undefined

nextTick(() => {})

const obj = observable({})
Copy the code

teleport

Before 2.x if you needed to create global prompt components, use js calls like iView and element-ui and hang them under the body node, the general idea was to do so

Alert.newInstance = properties => { const props = properties || {}; const Instance = new Vue({ data: props, render (h) { return h(Alert, { props: props }); }}); const component = Instance.$mount(); document.body.appendChild(component.$el); const alert = Instance.$children[0];Copy the code

Alert. vue is compiled by Webpack’s vue-loader, which compiles the template into the Render function, which eventually becomes a JS object and can be extended naturally

In the vue3 telport

<body> <div id="app"> <h1>Move the #content with the portal component</h1> <teleport to="#endofbody"> <div id="content">  <p> this will be moved to #endofbody.<br /> Pretend that it's a modal </p> <Child /> </div> </teleport> </div> <div id="endofbody"></div> <script> new Vue({ el: "#app", components: { Child: { template: "<div>Placeholder</div>" } } }); </script> </body>Copy the code

The built-in component that exposes Teleport configures the HTML elements that need to be hung on

composition-api

When I used the option-API of vue2. X, I believed that when I was maintaining 200 lines of vUE components, I needed to modify or modify a requirement repeatedly in data, methods, computed. It was possible to use mixins at the time, but beware of naming conflicts and completely obscure data sources, as seen in the composition-API 3.x post release example

<template>
  <button @click="increment">
    Count is: {{ state.count }}, double is: {{ state.double }}
  </button>
</template>

<script>
import { reactive, computed } from 'vue'

export default {
  setup() {
    const state = reactive({
      count: 0,
      double: computed(() => state.count * 2)
    })

    function increment() {
      state.count++
    }

    return {
      state,
      increment
    }
  }
}
</script>
Copy the code

It is better to split the business logic by focusing only on the split JS files and exposed methods and variables, and return in setup

async-component-api

In vue2.x you should make sure that components load asynchronously to reduce the first white screen, which is often done with code splitting

{    path: '/login',    component: () => import( /* webpackChunkName: "login" */ '@/views/login/index'),    hidden: true  },
Copy the code

You may need to be elegant for VUe3

import { defineAsyncComponent } from "vue" // simple usage const AsyncFoo = defineAsyncComponent(() => import("./Foo.vue")) // with options const AsyncFooWithOptions = defineAsyncComponent({ loader: () => import("./Foo.vue"), loadingComponent: LoadingComponent, errorComponent: ErrorComponent, delay: 200, timeout: 3000})Copy the code

global-api-change

before

import Vue from 'vue'
import App from './App.vue'

Vue.config.ignoredElements = [/^app-/]
Vue.use(/* ... */)
Vue.mixin(/* ... */)
Vue.component(/* ... */)
Vue.directive(/* ... */)

Vue.prototype.customProperty = () => {}

new Vue({
  render: h => h(App)
}).$mount('#app')
Copy the code

after

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

app.config.isCustomElement = tag => tag.startsWith('app-')
app.use(/* ... */)
app.mixin(/* ... */)
app.component(/* ... */)
app.directive(/* ... */)

app.config.globalProperties.customProperty = () => {}

app.mount(App, '#app')
Copy the code

Technically, Vue 2 has no concept of “application”. Each instance created from the same Vue constructor shares the same global configuration. If there are two Vue instances in the project, for example, the prototype extended function methods are shared. CreateApp provides config.globalProperties to help you extend Vue

v-model-api-change

Previously when you used v-model= “foo” vue compiled it for you

h(Comp, {
  value: foo,
  onInput: value => {
    foo = value
  }
})
Copy the code

This will compile after 3.0

h(Comp, {
  modelValue: foo,
  'onUpdate:modelValue': value => (foo = value)
})
Copy the code

It would be written like this, supporting multiple V-models

<InviteeForm
  v-model:name="inviteeName"
  v-model:email="inviteeEmail"
/>
Copy the code

end

These are just the tip of the iceberg for Vue3.0, more changes such as some runtime optimizations, diff optimizations, etc. This article is just part of my opinion of Vue3.0, welcome to point out the mistakes.