What about Vue3 now

It has been more than a year since Vue3 was released on September 18, 2020. During this time, the Vue team also released two minor versions 3.1 and 3.2, of which 3.1 mainly made some compatibility with Vue2, 3.2 added some new features (such as

According to @Evan You, changes will be made to the latest version of the Vue NPM package when the new Vue3 documentation is complete.

Vue3 new document

On December 25, 2021, @Evan You announced the new Vue3 documentation on its Twitter feed. Some parts of the new document are not yet complete (90% complete) and the final release is likely to be in mid-January 2022.

The new document uses VitePress, source code in Vue Docs.

New documentation: new design, Composition API/Options API toggle for sample code, better explanation, friendlier for beginners, better use/learning advice, and more.

You can get everything you need to know about Vue3 from the documentation, and you’re sure to learn.

The advantage of Vue3

Smaller size: Tree-shaking is introduced to reduce packaging volume

Better performance: Data hijacking optimization (Object.defineProperty to Proxy) and compilation optimization (Block Tree patchFlags and static upgrade)

Best development experience: Composition API (optimized for logical organization and reuse) and source code with Typescrip’s better type support

I think Vue

Good development experience

Best practice Vitesse

It is highly recommended to take a look at the Vitesse template to see some of the best practices of Vue3 combined with Vite that can be used as a reference or as a starting template for your learning.

Editor plug-in Volar

Use volar as an editor plug-in with more powerful support for the new Vue3 features. (Vetur is banned to avoid conflict.)

script setup

< Script Setup > is a compile-time syntactic sugar for using composite apis in single-file components (SFC). If you don’t know how to use it, check out the official documentation, experience the experience online and see the compiled content here.

You can combine unplugin-vue-Components with unplugin-auto-import to automatically import API plug-ins for a better development experience.

style v-bind

Ref Sugar(Experimental)

Ref sugar RFC

Setup props

See more RFC

Peripheral libraries that you might use

Component library for Vue3

PC:

  • Ant Design of Vue
  • element-plus
  • Arco Design Vue

Mobile client:

  • Vant
  • NutUI
  • Ionic

There are plenty of other great component libraries out there, but this is just a list of the ones THAT I think have a certain ecology.

Pinia next generation state management library

Pinia is a lightweight state management library for Vue that relies on the new Reactivity and composition API builds and has received a lot of attention recently. Pinia is also a Vue team member. It has the following advantages:

  • Full TypeScript support
  • The API design is very friendly and simple enough to use. (Close to Vuex 5 RFC)
  • Modular design, support automatic code split.
  • Support the Vue devtools
  • Extremely light (about 1KB)

Pinia’s authors state that Pinia is not intended to replace Vuex, but to make it easier for developers to migrate to Vuex and integrate with Vuex in the future. Check out Comparison with Vuex for details (Evan You also said pinia is the actual Vex5)

other

  • Nuxt 3 beta
  • vitesse vue3 vite Starter Template
  • Vue vben admin Is a background management template based on Vue3, Vite and TypeScript
  • Vueuse applies to the library of functions that can be combined with Vue2 and Vue3
  • Vue-demi creates common libraries for Vue2 and Vue3

Vue2 to Vue3

Migration guidelines and tools

  1. Official Migration Guide
  2. GoGoCode is an open source migration tool.

Vue2 is still used

You can use viet-plugin-vue2 and unplugin-script-setup-vue2 and still get a very good development experience.

2.7 will be the last minor version of Vue2.

Vue devtools

Chrome Beta installation

If you have a stable version installed, disable it first to avoid conflicts. If you find that there is no Vue option in the developer tools, it is recommended that you refresh the page and restart DevTools.

Auxiliary tool

  • Vue SFC Playground
  • Vue3 Template Explorer Vue3 Template compilation

composition api

The Setup function provides a set of responsive apis and life cycles that allow you to develop a component without relying on the Options API. The same functional logic can be grouped together and no longer scattered, making the code more maintainable and reusable

Easy to reuse, flexible to combine, better context support, better type support, logical organization is no longer scattered

It is highly recommended that you learn and use the Vueuse composite API toolkit that supports both 2 and 3.

Component data communication

Components of communication about so several ways Father and son | | | and future generations between the two generations what relationship between brothers

There are several ways for Vue components to communicate:

  • Component props pass (Parent to child)
  • $emit triggers a custom event (child to parent)
  • Use ref (instance where parent uses child)
  • EventBus (Brother)
  • Attrs and Listeners
  • Provide and Inject
  • Vuex (Cross-component and centralized storage)

Provide/Inject (dependency injection) is an alternative to Vuex. (You’ll see it in vue-router-next and Pinia’s source code.)

Usage:

// Inject ref or reactive objects into reactive components
provide(key,value)
// In the grandson component
inject(key)
// Ts can be synchronized with InjectionKey
Copy the code

Core /runtime/SRC/apiinject.ts

The child component inherits the parent component’s provides property, so it can be accessed layer by layer. The provide method writes key-value to the provides on the current instance overwrite if the key exists (so if a renamed key accesses the nearest one) Inject gets the key from the provides on the current instance

The life cycle

Debug hooks renderTracked and renderTriggered

Instructions and built-in components

v-memo

V-memo is a new instruction in 3.2. It is similar to v-once. The only difference is that v-once stops subsequent updates, and the V-Memo conditionally stops subsequent updates of certain templates.

// Receive an array, and if every value in the array is the same as the last render, the entire subtree update will be skipped.<div v-memo="[valueA, valueB]">.</div>
Copy the code

Further components

CreateApp did what

Use the Debugger method before createApp.

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import './index.css'
debugger;
const app = createApp(App)
app.use(router)
app.config.isCustomElement = tag= > tag.startsWith('wx-open')
app.config.globalProperties.$utils = {}
app.mount('#app')
Copy the code
// vue-next-master/packages/runtime-dom/src/index.ts
const createApp = (. args) = >{
  // If you call createApp with only reActivity responsiveness and no display then the renderer code will not be packaged, tree-shaking
  constapp = ensureRenderer().createApp(... args) app.mount =(containerOrSelector) = > {}
  return app
}
Copy the code
// vue-next-master/packages/runtime-dom/src/index.ts
// Create a renderer object
const ensureRenderer = () = > {
  const render = (vnode, container, isSVG) = >{
    // Component rendering logic
  }
  function createAppAPI(render) {
    return function createApp(rootComponent, rootProps = null){
      // Create an app object
      const app = {
        _uid: uid++,
        _component: rootComponent,
        _props: rootProps,
        use(){},
        mixin(){},
        component(){},...mount(){}}}}return {
    render,
    createApp: createAppAPI(render)
  }
}
Copy the code
// vue-next-master/packages/runtime-core/src/apiCreateApp.ts
// Standard mount method
const mount = (rootContainer) = >{
  / / create a vnode
  const vnode = createVNode(rootComponent, rootProps)
  / / render vnode
  render(vnode, rootContainer)
  app._container = rootContainer
  return vnode.component.proxy
}
// Override the mount method
const mount = (containerOrSelector) = >{
  // For strings passed in, convert them to DOM objects
  const container = normalizeContainer(containerOrSelector)
  // Clear HTML before mounting
  container.innerHTML = ' '
  // Perform the component mount
  // The argument in turn is the container, isHydate, whether it is SVG or not
  return mount(container, false, container instanceof SVGElement)
}
Copy the code

The flow of component rendering

// app.vue
<template>
  <div id="app" class="app-class">
    <p>hello vue</p>
  </div>
</template>
Copy the code

Assuming our component template looks like this, open the debugger in front of.mount and start debugging.

Then the main process of component rendering is as follows:

  1. Create a VNode for the incoming App componentcreateVNode
  2. Start rendering the VNoderender
  3. Enter thepatchSince the VNode type is a component, enter the method that handles the componentprocessComponent
  4. Enter themountComponentStart mounting the component, create the component instance, set up the component instance, and run the render function with side effects
  5. Enter thesetupRenderEffectRender to generate a subtree vNode
  6. Once again into thepatchMount the subtree vNode because the type is a DOM element
  7. Enter theprocessElementHandle the DOM element and entermountElement, creates an element node whose child elements are arrays, and entersmountChildren, traverses the child nodepachMount to the parent node.
  8. Enter thehostInsertInserts the created node into#appOn.

The main process in the source code:

// vue-next-master/packages/runtime-core/src/renderer.ts
/ / render vnode
const render = (vnode, container) = > {
  if (vnode == null) {
    // Destroy the component
  } else {
    // Create the update component
    patch(container._vnode || null, vnode, container)
  }
}
Copy the code
// vue-next-master/packages/runtime-core/src/renderer.ts
// Main parameters old node, new node, DOM container
const patch = (n1,n2,container) = > {
  const { type, ref, shapeFlag } = n2
  switch (type) {
    // Process different vNodes according to node type
    // For example, processText processes text
    // processComponent processes components}}Copy the code
// The vNode type is component
const processComponent = (n1,n2,container) = > {
  if(n1 == null) {// Mount the component
    mountComponent()
  }else{
    // Update the component
    updateComponent()
  }
}

// Mount the component
const mountComponent = () = >{
  // Create a component instance
 const instance = createComponentInstance()
  // Set the component instance
  setupComponent(instance)
  // Set the render function with side effects
  setupRenderEffect(instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized)
}
// Render functions with side effects, such as executing render functions when data is modified
const setupRenderEffect= () = > {
  instance.update = effect(function componentEffect(){
    if(! instance.isMounted){// Render component
      const subTree = (instance.subTree = renderComponentRoot(instance))
      // Mount the subtree vnode and continue with patch
      patch(null,subTree,container,anchor,instance,parentSuspense,isSVG)
    }else{
      // Update the component}})}Copy the code
// If vNode type is an element
const processElement = () = > {
  if(n1 == null){
    mountElement()
  }else{
    // Update the element}}// Mount the element
const mountElement = () = >{
  el = vnode.el = hostCreateElement()
  // Mount the child nodes if the child nodes are arrays
  mountChildren()
}

const mountChildren = () = > {
  // Mount patch for the for loop
  for(){
    patch()
  }
}

Copy the code

Component updates

The main process of component update:

When an element’s child node is updated:

// Set the side effect rendering function
const setupRenderEffect= () = > {
  instance.update = effect(function componentEffect(){
    if(! instance.isMounted){// Render component
    }else{
      // Update the component
      let { next, bu, u, parent, vnode } = instance
      // next: new component vNode
      if (next) {
        next.el = vnode.el
        // Update component vNode information
        updateComponentPreRender(instance, next, optimized)
      } else {
        next = vnode
      }
      // Render a new subtree vnode
      const nextTree = renderComponentRoot(instance)
      // Old subtree vnode
      const prevTree = instance.subTree
      // Update the subtree vnode
      instance.subTree = nextTree
      // The component updates the old and new subtree patchespatch(prevTree,nextTree,hostParentNode(prevTree.el!) ! ,getNextHostNode(prevTree),instance,parentSuspense,isSVG) } }) }// Update component methods
const updateComponent = (n1,n2,optimized) = > {
  // Whether the subcomponents need to be updated
  if (shouldUpdateComponent(n1, n2, optimized)){
    instance.next = n2
    // Avoid repeated updates of child components
    invalidateJob(instance.update)
    // Subcomponent side effects render function
    instance.update()
  }else{
    // Copy the properties without updating
    n2.component = n1.component
    n2.el = n1.el
    instance.vnode = n2
  }
}



Copy the code

Responsive system

Principle of responsiveness

Vue responsiveness principle

Debugging computed 3.2 +

// Computed can be debugged and only works in development mode
const getCount = computed(() = > count.value + 1, {
  onTrack(e) {
    Emitted when count.value is traced as a dependency
    debugger
  },
  onTrigger(e) {
    // Triggered when count.value is modified
    debugger}})// To access getCount, onTrack should be triggered
console.log(getCount.value)
// Change count.value to trigger onTrigger
count.value++

Copy the code

Watch and watchEffect

  • watchIs lazy and only performs callbacks when the listening source changes
  • watchKnow exactly what state should trigger a callback
  • watchYou can access values that change before and after the state
  • watchEffectThe function passed in is executed immediately and rerun when it depends on a change
  • watchPostEffectComponents are updated and re-runwatchSyncEffectAlways force synchronization trigger (3.2+)

EffectScope scope API 3.2+

EffectScope is an API that creates a scope object to capture internally created reactive effects (compute properties/listeners, etc.) so that they can be processed uniformly, primarily for library authors. RFC

You can see it in pinia’s source code, for example.

export function createPinia() :Pinia {
	Detached: true The detached mode will not be collected by the parent's side effects scope
	const scope = effectScope(true)... }Dispose dispose dispose dispose dispose dispose dispose dispose dispose dispose dispose dispose dispose dispose dispose dispose
function $dispose() {
	scope.stop()
	subscriptions = []
	actionSubscriptions = []
	pinia._s.delete($id)
}

Copy the code

Template compilation

When we write the component structure with
, Vue compiles it into the component’s render function, which you can view online using the template export tool.

Template compilation generally goes through three processes: parsing the template to the AST, transforming the AST, and generating code. You can view the AST structure in the AST export tool here.

The process of compiling templates

Template compilation optimization

  • Block Tree and PatchFlags optimization
  • Static ascension
  • Cache Event handler

About patchFlags and shapFlags

PatchFlags (packages/Shared/SRC/patchFlags ts) is a compile time transform called AST nodes on the optimization of the logo, when during the diff, we can accurately updated.

ShapFlags (packages/Shared/SRC/shapeFlags ts) as the name implies, is the type of element definitions. Such as elements, function components, slots, and so on.

Update record

I will keep this post up to date…

  • December 26: Added content for the new Vue3 documentation.

Write it at the end

Thank you for reading so far, and if you have any suggestions/corrections for this article, please let me know. Like/retweet if you think it’s ok.

Wish you can be happy at this time, see you next time! 💖