Quick start Vue3

I Quick start Vue3

1. CDN using Vue3

<script src="https://lib.baomitu.com/vue/3.0.2/vue.global.js"></script>

2.vue-cli

Upgrade to Vue cli v4 5 (remove and install)

npm i -g @vue/cli@next

3. Use Vite

Using the feature that ES6 import will send requests to load files, intercept these requests, do some precompiling, and the provincial webpack takes a long time to pack

// npm
$ npm init vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev

// yarn
$ yarn create vite-app <project-name>
$ cd <project-name>
$ yarn
$ yarn dev

Vue3 highlights:

1. Faster performance than Vue2 (diff algorithm optimization,)
2. On demand compilation, smaller size
3. Composition API composition API
4. Better support for TS
5. Exposed custom rendering API
6. More new advanced components

Diff algorithm optimization:

The virtual DOM in Vue2 is for full comparison

When creating a virtual DOM, Vue3's diff algorithm will add static tags according to whether the contents in the DOM will change (different values of static tags will have different comparison methods)

Vue Template Explorer (vue-next-template-explorer.netlify.app)

Static lift:

In Vue2, no matter whether the element participates in the update or not, it will be recreated each time and then rendered

In Vue3, elements that do not participate in the update will be statically promoted and will only be created once. They can be reused directly during rendering

<div>
  <p>1</p>
  <p>2</p>
  <p>{{msg}}</p>
</div>
import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

const _hoisted_1 = /*#__PURE__*/_createElementVNode("p", null, "1", -1 /* HOISTED */)
const _hoisted_2 = /*#__PURE__*/_createElementVNode("p", null, "2", -1 /* HOISTED */)

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createElementBlock("div", null, [
    _hoisted_1,
    _hoisted_2,
    _createElementVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}

cacheHandlers event listener cache:

By default, onClick is regarded as a dynamic binding, so it will track its changes every time

However, because it is the same function, it does not track changes. It can be directly cached and reused

//cacheHandlers not used
import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

const _hoisted_1 = ["onClick"]

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createElementBlock("div", null, [
    _createElementVNode("button", { onClick: _ctx.click }, "123", 8 /* PROPS */, _hoisted_1)
  ]))
}
//Using cacheHandlers, there is no static tag variable, and there is no need to compare again
import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createElementBlock("div", null, [
    _createElementVNode("button", {
      onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.click && _ctx.click(...args)))
    }, "123")
  ]))
}

SSR rendering:

When there is a large amount of static content, it will be pushed into a buffer as a pure string. Even if there is a dynamic binding, it will be embedded through template interpolation. This will be much faster than rendering through virtual dom

When the static content is large to a certain magnitude, it will be used_ The createStaticVNode method sends the client to a static node in the provincial capital. These static nodes will be directly innerHtml. There is no need to create objects and then render according to the objects

Composition API in Vue3

1, Setup function

1.setup parameters

Receive two parameters: props and context

props: responsive. When a new prop is passed in, it will be updated. (cannot be deconstructed with ES6)

export default {
  props: {
    title: String
  },
  setup(props) {
    console.log(props.title)
  }
}

context: ordinary JavaScript object that exposes other values that may be useful in setup

export default {
  setup(props, context) {
    // Attribute (non responsive object, equivalent to $attrs)
    console.log(context.attrs)

    // Slot (non responsive object, equivalent to $slots)
    console.log(context.slots)

    // Trigger event (method, equivalent to $emit)
    console.log(context.emit)

    // Expose public property (function)
    console.log(context.expose)
  }
}

2.setup execution timing

setup executes before beforecreate

Optional APIHook inside setup
beforeCreateNot needed*
createdNot needed*
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
errorCapturedonErrorCaptured
renderTrackedonRenderTracked
renderTriggeredonRenderTriggered
activatedonActivated
deactivatedonDeactivated

3.setup considerations

3.1 data and methods cannot be used in setup because the periodic declaration function has not been executed when setup() is executed

3.2 inside setup(), this is not a reference to the active instance and is called before parsing other component options. Therefore, the behavior of this inside setup() is completely different from that in other options

3.3 setup() can only be synchronous, not asynchronous

2, Responsive data processing in Vue3

1.reactive,ref

The responsive data in Vue3 is implemented through the Proxy of ES6. The role of reactive and ref is to create responsive data

The reactive parameter must be an object

ref is suitable for listening to simple type data from a performance point of view. For complex types of objects, you can also implement response expressions (in the official website of vue, response packages for refs, ARRS and objects frequently appear, but the. value form is required when using them, resulting in complex creation and access of other response expressions)

ES6 structure assignment usually causes the loss of data responsiveness. Use toRefs to retain the responsive association with the source object

Both reactive and ref are used to define responsive data. Reactive is more recommended to define complex data types. Ref is more recommended to define basic types. The essence of ref and reactive can be simply understood as that ref is the secondary packaging of reactive, and the data defined by ref should be accessed one more time value, use ref to define the basic data type, and ref can also define arrays and objects.

<template>
    <div ref="box">
        I am div
	</div>
</template>

<script>
//ref get dom
import {ref,onMounted} from 'vue'
export default{
    name:'App',
    setup(){
      let box = ref(null)
      
      onMounted(()=>{
          console.log('onMounted',box.value)
      })
        
      return {box}
    }
}
</script>

2. Responsive data implementation

There are many limitations in response expressions in Vue2, which can be solved by proxy in Vue3: 1 Detection of adding and deleting attributes 2 Subscript based modification of the array, for Detection of length modification 3 Support for docking MapSet, etc

a.Proxy

A Proxy is an object that wraps another object and allows you to block any interaction with that object. One difficulty in using Proxy is this binding. We want any method to be bound to this Proxy instead of the target object, so that we can also intercept them. This can be achieved using the new Reflect feature in ES6

let obj  = {name:'lnj',age:18}
let state = new Proxy(obj,handler:{
         		get(target, property, receiver) {
    				return target[property]
				}
				set(target,property){
                    
                }
            })
b.Reflect (does not block the program)

Reflection mechanism: reflection mechanism means that a program can obtain its own information at run time

Reflect is a built-in object used to provide methods to intercept JavaScript operations. It is not a function object and cannot be constructed. (the method is the same as that of porxy handlers)

let obj  = {name:'lnj',age:18}
let state = new Proxy(obj,handler:{
         		get(target, property, receiver) {
    				return Reflect.get(target, property, receiver)
				}
				set(target,property,value,receiver){
                    return Reflect.set(target, property,value,receiver)
                }
            })

3. Recursive and non recursive listening

3.1 recursive listening

By default, both ref and reactive listen recursively
There is a problem (too much data consumes performance)

let state = reactive({
    a:'a',
    gf:{
        b:'b',
        f:{
            c:'c',
            s:{
                d:'d'
            }
        }
    }
})
function myFn(){
    console.log(state)
    console.log(state.gf)
    console.log(state.gf.f)
    console.log(state.gf.f.s)
}
return {state,myFn}

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-puvhxm1p-163964961948) (C: \ users \ xupt \ appdata \ roaming \ typora \ user images \ image-20211117174755249. PNG)]

3.2 non recursive listening (shallowReactive,shallowRef)

shallowRef creates data, and Vue listens to The change of value is not the change of the first layer

let state = shallowReactive({
    a:'a',
    gf:{
        b:'b',
        f:{
            c:'c',
            s:{
                d:'d'
            }
        }
    }
})
function myFn(){
    console.log(state)
    console.log(state.gf)
    console.log(state.gf.f)
    console.log(state.gf.f.s)
}
return {state,myFn}

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-svsxske2-163964969500) (C: \ users \ xupt \ appdata \ roaming \ typora \ typora user images \ image-20211117174852825. PNG)]

3.3 triggerRef method

Actively update the interface according to the incoming data (there is no triggerReactive method)

let state = shallowRef({
    a:'a',
    gf:{
        b:'b',
        f:{
            c:'c',
            s:{
                d:'d'
            }
        }
    }
})
function myFn(){
    state.value.gf.f.s.d = '4'
    triggerRef(state)
}
return {state,myFn}

3.4 generally, we can use ref and reactive. If we need to monitor a large amount of data, we can use shallowRef and shallowReactive

4. toRaw

Proxy proxy generates a proxy object, but the reference point of the original object is the same

setup(){
    let obj = {name:'l',age:18}
    let state = reactive(obj)
    function myFn(){
        obj.name = 'zs'
        console.log(obj)
    }
    return {state,myFn}
}
//If the response type cannot be triggered by modifying OBJ directly, the interface can be updated only by modifying state

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-fme0fzz4-163964961951) (C: \ users \ xupt \ appdata \ roaming \ typora \ typora user images \ image-20211117182038478. PNG)]

setup(){
    let obj = {name:'l',age:18}
    let state = reactive(obj)
    let obj2 = toRaw(state)
    console.log(obj === obj2)	//true
    function myFn(){
        obj2.name = 'zs'
        console.log(obj)
    }
    return {state,myFn}
}
//The toRaw method can obtain the original data

Each modification of ref and reactive data types will be tracked, and the UI interface will be updated, which will greatly degrade the performance

If we do not need to track and update the UI interface, we can use the toRaw method to get its original data for operation to save performance

setup(){
    let obj = {name:'l',age:18}
    let state = ref(obj)
    let obj2 = toRaw(state)
    let obj3 = toRaw(state.value)
    //ref(obj) —> reactive({value:obj})
    console.log(obj === obj2)	//false
    console.log(obj === obj3)	//true
    function myFn(){
        obj2.name = 'zs'
        console.log(obj)
    }
    return {state,myFn}
}
//The toRaw method can obtain the original data

5.markRaw

setup(){
    let obj = {name:'l',age:18}
    obj = markRaw(obj)
    let state = reactive(obj)
    function myFn(){
        obj2.name = 'zs'
        console.log(obj)
    }
    return {state,myFn}
}
//Never be responsive

6.toRef and toRefs

6.1 toRef

setup(){
    let obj = {name:'l',age:18}
    //ref(obj.name)—>ref('l')->reactive({value:'l'})
    //let state = ref(obj.name)
    let state = toRef(obj,'name')
    function myFn(){
        state.value = 'zs'
    }
    return {state,myFn}
}
//If we use ref to change the attributes in an object into responsive data, modifying the responsive data will not affect the original data
//toRef changes the attributes in an object into responsive data. Modifying responsive data will affect the original data, but will not trigger UI interface update

ref: assignment, modifying the response will not affect the previous data, and the interface will be updated
toRef: reference, modifying responsive data will affect previous data, and the interface will not be updated

6.2 toRefs

setup(){
    let obj = {name:'l',age:18}
    //let state = toRef(obj,'name','age') 	// report errors
    
    //let name = toRef(obj,'name')
    //let age = toRef(obj,'age')
    
    let {name,age} = ...toRefs(obj)
    function myFn(){
        state.value = 'zs'
    }
    return {name,age,myFn}
}

7.readonly

readonly: creates read-only data and is recursive read-only

shallowReadonly: non recursive read only

isReadonly: judge whether it is read-only

Vue3 advanced

I setup syntax sugar

1. Automatic component registration

<template>
    <Child />
</template>
<script setup>
import Child from './Child.vue'
</script>

2. Use of component core API

Using props

Specify the current props type by defining props to obtain the props object of the context

<script setup>
  import { defineProps } from 'vue'
  const props = defineProps({
    title: String,
  })
</script>

Using emits

Use defineEmit to define the events contained in the current component, and execute emit through the returned context

<script setup>
  import { defineEmits } from 'vue'
  const emit = defineEmits(['change', 'delete'])
</script>

Get slots and attrs

You can get slots and attrs from the context through useContext. However, after the proposal was formally adopted, the syntax was abolished and divided into useAttrs and useSlots

<script setup>
  import { useContext } from 'vue'
  const { slots, attrs } = useContext()
    
  import { useAttrs, useSlots } from 'vue'
  const attrs = useAttrs()
  const slots = useSlots()
</script>

3.defineExpose API

In the traditional writing method, we can access the contents of child components through ref instances in the parent component, but this method cannot be used in script setup. Setup is equivalent to a closure. No one can access internal data and methods except the internal template template.

If you need to expose the data and methods in setup, you need to use defineExpose AP

<script setup>
	import { defineExpose } from 'vue'
	const a = 1
	const b = 2
	defineExpose({
	    a
	})
</script>

4. Properties and methods need not be returned and can be used directly

In the previous writing method, data and methods defined need to return at the end before they can be used in the template. In script setup, the defined properties and methods do not need to be returned and can be used directly

<template>
  <div>
   	<p>My name is {{name}}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const name = ref('Sam')
</script>

Keywords: Javascript npm Vue Vue.js

Added by Quilmes on Thu, 16 Dec 2021 16:53:40 +0200