Vue3.x changes in components (required for front-end development)

Posted by Hisakata on Thu, 04 Nov 2021 08:17:54 +0100

1, Why is data in a component always in the form of a function?

We try to make a counter case first and change the return form of data into an object. The specific codes are as follows:

<template>
 <div>
  <button @click="num++">+</button>
   {{num}}
  <button @click="num--">-</button>
 </div>
</template>
<script>
const retData = {
 num:0
}
export default {
 data(){
  return retData
 }
}
</script>

The operation results are normal and normal. But we all know that the reason why vue project adopts component form is to reuse it many times, so we try to use our components many times.

The magic effect happened. When we changed the value of the first component, the data of the second component was also modified. When modifying the second component, the data of the first component is also updated synchronously.

Reason: if the same component is reused multiple times, multiple instances will be created. If data is an object, these instances use the same constructor, and the pointer will point to the same place, resulting in the data of the two components being updated at the same time.

In order to ensure that the data in components are independent and will not affect each other, the data of each component must be in the form of function. The purpose is to put the data into a new object, so that the above problems will not occur.

The main meaning of this is to tell us that the data option in Vue3.x is always in the form of a function and returns responsive data.

Vue2.x VS Vue3.x instance creation

2, Changes in functional components

In vue3.x, functional:true   Component option removed. Functional components are not recommended in vue3.x.

Some friends will marvel. My God, I don't know what functional components are. No matter how simple you say, I don't understand. So let's talk about what functional components do and where the original functional properties are placed?

2.1. Functional components in Vue2.x:

Functional component is also a type of component. It is mainly used to define those that do not respond to data and do not need any life cycle hook functions. Only props receives the passed data.

Type 1: template based functional components

<template functional >
 <div>
  Functional component content
 </div>
</template>

Type 2: component registration

Vue.componenet('fun-comp':{
 functional:true,
 props:{
  msg:{
   type:String,
   default:'Component data'
  }
 },
 render:(h,context)=>{
  return h('div',['Component content','++',context.props.msg])
 }
})

Type 3: middleware implementation render method

// FunComps.js file code
export default {
 functional:true,
 props:{
  render:{
   type:Function
  },
  params:{}
 },
 render:(h,ctx)=>{
  return ctx.props.render(h,ctx.props.params)
 }
}

//Component call
<fun-comp :render="renderHandle" :params="['111','222']" />

The renderHandle function can be controlled arbitrarily in the outer layer, which not only saves overhead, but also has high reusability.

2.2. Functional components in Vue3.x:

The functional attribute cannot be used in SFC to declare a functional component. The functional:true attribute is removed.

// Create a new FunComp.vue file
<script>
import { h } from "vue"
function Footer(props,context){
 return h(`h${props.level}`,context.attrs , context.slots )
}
Footer.props = ['level']
export default Footer
</script>

//Using functional components
<template>
 <FunComp level="1.0.0" >Vue3.x Functional component content</FunComp>
</template>
<script >
import FunComp from '../../components/FunComp.vue'
export default{
 component:{
  FunComp
 },
}
</script>

It should be clear where the removed attribute is! Then look at the changes in asynchronous components...

3, Asynchronous component changes

Vue3.x asynchronous components require that they be created using the defineAsyncComponent method.

Since functional components in Vue3 must be defined as pure functions, asynchronous components have the following changes:

  1. You must explicitly wrap with the defineAsyncComponent method
  2. The component option has been renamed loader
  3. The loader function no longer receives the resolve and reject callback methods. And must return a Promise object.

3.1 comparison of asynchronous components without configuration

In Vue2.x, asynchronous components use:

{
 path:'/',
 component: ()=> import("@/view/home/index")
}

In Vue3.x, asynchronous components use:

import { defineAsyncComponent } from 'vue'

{
 path:"/",
 component:defineAsyncComponent(()=>{ import("@/view/home/index.vue") })
}

3.2 asynchronous components with configuration

const asyncPageWithOptions = defineAsyncComponent({
 loader:()=> import("../view/index/index.vue"),
 delay:200,
 timeout:3000,
 errorComponent:ErrorComponent,
 loadingComponent:LoadingComponent
})

The loader option is the previous component option.

4, Changes to the whitelist of custom components

In Vue3.x, custom element detection occurs during template compilation. If you want to add custom elements other than Vue, you need to set them in compiler options   isCustomElement   Options.
When using the build tool, the templates are precompiled with Vue loader   vite.config.js   You can configure the vuecompiler option provided in:

import { defineConfig,vueCompilerOption } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
 plugins: [vue()],
 vueCompilerOptions:{
  isCustomElement:tag => tag==='pie-chart'
 }
})

In this case, when the pie chart element is encountered, skip it directly and do not compile it.

5, Dynamic component

When setting dynamic components in vue3.x, the is attribute can only be used on the component tag.

usage method:

<component :is="currentView"></component>
//currentView is an expression

Let multiple components use the same mount point and switch components dynamically.

5.1 cache of dynamic components

Many times, when multiple components switch back and forth, the instance of the component is recreated, and we need to save its state. At this time, we need to cache the dynamic component.

In Vue2.x:

<keep-alive>
 <component :is="currentView"></component>
</keep-alive>

In Vue3.x: keep alive must be used inside router view

<router-view>
<keep-alive>
 <component :is="currentView"></component>
 </keep-alive>
</router-view>

Topics: Javascript Front-end Vue.js