Getting started with vue3 (summary)

sequence:

After a long iteration, on September 18, 2020, Vue.js released version 3.0, code-named: One Piece (One Piece) used to Typescriptcarry out a large-scale refactoring, bringing Composition API RFCa version that is similar React Hookto writing Vueand can be customized my ownhooks

1. Vue2 compared to Vue3

  • Unfriendly to TypeScriptsupport (all attributes are placed on thisthe object, it is difficult to deduce the data type of the component)
  • A large number of APImounts are mounted Vueon the prototype of the object, which is difficult to achieve TreeShaking.
  • The architecture level is not friendly to cross-platform domrendering development support
  • CompositionAPI. ReactHookinspired by
  • Vue3 is more convenient to supportjsx
  • TemplateMultiple root tags are not supported
  • Vue3 rewrites the virtual DOM and optimizes the compilation of templates...

2. Advantages of Vue3

2.1. Performance improvement

  • 41% reduction in bundle size

  • 55% faster initial render, 133% faster update render

  • 54% less memory

2.2. Source code upgrade

  • Use Proxy instead of defineProperty to achieve responsiveness

  • Rewrite the implementation of virtual DOM and Tree-Shaking

2.3. Embrace TypeScript

  • Vue3 can better support TypeScript

2.4. New Features

  1. Composition API (composition API)

    • ​ setup()

    • ​ ref()

    • ​ reactive()、shallowReactive()

    • ​ isRef()

    • ​ toRefs()

    • ​ readonly()、isReadonly()、shallowReadonly()

    • ​ computed()

    • ​ watch()

    • ​ LifeCycle Hooks (new life cycle)

    • ​ Template refs

    • ​ globalProperties

    • ​ Suspense

    • ​ Provide/Inject

    • ​ …

  2. new built-ins

    • Fragment
    • Teleport
    • Suspense
  3. other changes

    • new lifecycle hook
    • The data option should always be declared as a function
    • Remove keyCode support as v-on modifier

1. Create a Vue3.0 project

1. Use vue-cli to create

official document

## 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
vue --version
## 安装或者升级你的@vue/cli
## 升级一 npm i -g @vue/cli to update!
## 升级二 npm uninstall vue-cli -g (先卸载后安装)
npm install -g @vue/cli
## 创建
vue create v3-ts-team
## 启动
cd vue_test
npm run serve

[External link image transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the image and upload it directly (img-eH3tDROQ-1663692950473) (C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\ image-20220810222758702.png)]

some options:

?Check the features needed for your project:

Choose Vue version (choose VUE version)
Babel (JavaScript compiler, which can convert code to backward compatibility)
TypeScript (programming language, recommended for large projects)
Progressive Web App (PWA) Support-APP uses
Router (routing)
Vuex (Vuex )
CSS Pre-processors (css preprocessing)
Linter / Formatter (code style/formatting)
Unit Testing (unit testing)
E2E Testing (e2e testing)

[External link image transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the image and upload it directly (img-ZMIgkX1S-1663692950475) (C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\ image-20220810223604589.png)]

[External link image transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the image and upload it directly (img-vbEtqPdw-1663692950475) (C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\ image-20220810223958019.png)]

2. Use vite to create

Vue official document vite official website

  • What is vite? — A new generation of front-end build tools.
  • The advantages are as follows:
    • In the development environment, no packaging operation is required, and it can be cold started quickly.
    • Lightweight and fast Hot Reload (HMR).
    • True on-demand compilation, no longer waiting for the entire application to be compiled.
## 创建工程
npm init vite-app <project-name>
## 进入工程目录
cd <project-name>
## 安装依赖
npm install
## 运行
npm run dev

2. Common Composition API

official document

1.setup()

  1. setup is all Composition API (composition API) "performance stage" .
  2. The components used in the components: data, methods, etc., must be configured in the setup.
  3. Two return values ​​of the setup function:
    1. If an object is returned, the properties and methods in the object can be used directly in the template. (Focus!)
    2. If it returns a rendering function: you can customize the rendering content. (learn)
  4. important point:
    1. Try not to mix with Vue2.x configuration
      • Properties and methods in setup can be accessed in Vue2.x configuration (data, methos, computed...) .
      • But Vue2.x configuration (data, methos, computed...) cannot be accessed in setup .
      • If there are duplicate names, setup takes precedence.
    2. setup cannot be an async function, because the return value is no longer the return object, but a promise, and the template cannot see the properties in the return object. (You can also return a Promise instance later, but it requires the cooperation of Suspense and asynchronous components)
    3. setupThe function will be executed before , beforeCreateand these two hooks are also canceled and replaced with unified . This function is equivalent to a life cycle function. In the past , , and so on are all written in the function with corresponding new additionscreatedvue3setupvuedatamethodswatchapisetup()
setup(props, context) {
    
    
    // Attribute (非响应式对象,等同于 $attrs)
    context.attrs
    // 插槽 (非响应式对象,等同于 $slots)
    context.slots
    // 触发事件 (方法,等同于 $emit)
    context.emit
    // 暴露公共 property (函数)
    context.expose
    
    return {
    
    }
  }
  • props: Used to receive propsdata , propsit is responsive, propswhen , it will be updated.
  • contextUsed to define the context, the context object contains some useful properties, these properties need to thisbe setup()cannot be accessed in the function this, it is aundefined
  • contextis a plain JavaScriptobject , that is, it is not reactive, which means you can safely contextuse ES6destructuring on .
  • Return value: return {}, returns responsive data, the function that needs to be used in the template

Note: because propsis reactive, you can't use ES6 destructuring , which would remove the prop's responsiveness. But you can use the following way to deal with

<script lang="ts">
import {
    
     defineComponent, reactive, ref, toRefs } from 'vue';
export default defineComponent({
    
    
  setup(props, context) {
    
    
  
    const {
    
     title } = toRefs(props)
    
    console.log(title.value)
    
    return {
    
    }
  }
});
</script>

If titleis an optional prop, it propsmay not be present in the passed in title. In this case, toRefsno ref will be titlecreated . You need to toRefreplace it with:

<script lang="ts">
import {
    
     defineComponent, reactive, toRef, toRefs } from 'vue';
export default defineComponent({
    
    
  setup(props, context) {
    
    
  
    const {
    
     title } = toRef(props, 'title')
    
    console.log(title.value)
    
    return {
    
    }
  }
});
</script>

2.ref()

  • Role: Define a responsive data
  • grammar:const xxx = ref(initValue)
    • Create a reference object (reference object, ref object for short) that contains responsive data .
    • Data manipulation in JS:xxx.value
    • Read data in the template: No need for .value, directly:<div>{ {xxx}}</div>
  • Remark:
    • The received data can be: basic type or object type.
    • Basic types of data: Reactive is still dependable Object.defineProperty()and getcomplete set.
    • Object type data: internally "rescues" a new function in Vue3.0 - reactivefunction.
<template>
    <div class="mine">
        {
    
    {
    
    count}} // 10
    </div>
</template>

<script lang="ts">
import {
    
     defineComponent, ref } from 'vue';
export default defineComponent({
    
    
  setup() {
    
    
    const count = ref<number>(10)
    // 在js 中获取ref 中定义的值, 需要通过value属性
    console.log(count.value);
    return {
    
    
       count
    }
   }
});
</script>

3.reactive()

  • Function: Define an object type of responsive data (do not use it for basic types, but use reffunctions)
  • Syntax: const 代理对象= reactive(源对象)Receive an object (or array) and return a proxy object (the instance object of Proxy, referred to as proxy object)
  • The reactive data defined by reactive is "deep".
  • The internal ES6-based Proxy implementation operates on the internal data of the source object through the proxy object.

reactive()The function receives a common object and returns a reactive data object, which is equivalent Vue 2.xto Vue.observable()the API in , and the reactive transformation is "deep" - it affects all nested properties. Based on the proxy, it is also very simple to use the created responsive data. After creating it, go out in it setupand call it returndirectly intemplate

<template>
  {
   
   {state.name}} // test
<template>

<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from 'vue';
export default defineComponent({
  setup(props, context) {
  
    let state = reactive({
      name: 'test'
    });

    return state
  }
});
</script>

Note: This API returns a reactive object state. This reactive transformation is a "deep transformation" - it affects all nested properties of the passed object.

Access created reactive data in reactiveobjectref

<template>
    <div class="mine">
        {
    
    {
    
    count}} -{
    
    {
    
    t}} // 10 -100
    </div>
</template>

<script lang="ts">
import {
    
     defineComponent, reactive, ref, toRefs } from 'vue';
export default defineComponent({
    
    
  setup() {
    
    
    const count = ref<number>(10)
    const obj = reactive({
    
    
      t: 100,
      count
    })
   
    // 通过reactive 来获取ref 的值时,不需要使用.value属性, ref 将被自动解包
    console.log(obj.count); // 10
    console.log(obj.count === count.value); // true
    
    // count 改变时,更新 `obj.count
    count.value = 12
    console.log(count.value) // 12
    console.log(obj.count) // 12
    
    // 反之,修改obj 的count 值 ,ref 也会更新
   obj.count = 20
   console.log(obj.count) // 20
   console.log(count.value) // 20
    
    return {
    
    
       ...toRefs(obj)
    }
   }
});
</script>

reactiveWill unwrap all deep ones refswhile maintaining the responsiveness of the ref. The ref will be automatically unwrapped when refassigning to the propertyreactive

4. Responsive principle in Vue3.0

Responsiveness of vue2.x

  • Implementation principle:

    • Object type: Object.defineProperty()Intercept (data hijacking) by reading and modifying attributes.

    • Array type: interception is achieved by overriding a series of methods for updating the array. (The change method of the array is wrapped).

      Object.defineProperty(data, 'count', {
              
              
          get () {
              
              }, 
          set () {
              
              }
      })
      
  • There is a problem:

    • When adding or deleting attributes, the interface will not be updated.
    • Modify the array directly through the subscript, and the interface will not be automatically updated.

Responsiveness of Vue3.0

  • Realization principle:
    • Through Proxy (proxy): Intercept the change of any attribute in the object, including: reading and writing attribute values, adding attributes, deleting attributes, etc.
    • Through Reflect (reflection): operate on the properties of the source object.
    • Proxy and Reflect described in the MDN document:
      • Proxy

      • Reflect

        new Proxy(data, {
                  
                  
        	// 拦截读取属性值
            get (target, prop) {
                  
                  
            	return Reflect.get(target, prop)
            },
            // 拦截设置属性值或添加新属性
            set (target, prop, value) {
                  
                  
            	return Reflect.set(target, prop, value)
            },
            // 拦截删除属性
            deleteProperty (target, prop) {
                  
                  
            	return Reflect.deleteProperty(target, prop)
            }
        })
        
        proxy.name = 'tom'   
        

5. reactive vs. ref

  • From the perspective of defining data:
    • ref is used to define: basic type data .
    • reactive is used to define: object (or array) type data .
    • Remarks: ref can also be used to define object (or array) type data , which will be automatically converted to reactivea proxy object internally .
  • From the perspective of principle comparison:
    • ref implements responsiveness (data hijacking) Object.defineProperty()through getAND .set
    • reactive implements responsiveness (data hijacking) by using Proxy , and manipulates the data inside the source object through Reflect .
  • From a usage point of view:
    • Data defined by ref: required for.value data manipulation , but not required.value for direct reading in the template when reading data .
    • The data defined by reactive: operation data and read data: neither is required.value .

6. Two points of attention for setup

  • The timing of setup execution

    • Executed once before beforeCreate, this is undefined.
  • parameter of setup

    • props: The value is an object, including: the properties passed from outside the component and received by the internal declaration of the component.
    • context: context object
      • attrs: The value is an object, including: attributes passed from outside the component but not declared in the props configuration, equivalent to this.$attrs.
      • slots: Received slot content, equivalent to this.$slots.
      • emit: A function that dispatches custom events, equivalent to this.$emit.

7. Computed properties and monitoring

1.computed function

  • Consistent with the computed configuration function in Vue2.x

  • Create a read-only computed property

    import {
          
           computed, defineComponent, ref } from 'vue';
    export default defineComponent({
          
          
      setup(props, context) {
          
          
        const age = ref(18)
    
        // 根据 age 的值,创建一个响应式的计算属性 readOnlyAge,它会根据依赖的 ref 自动计算并返回一个新的 ref
        const readOnlyAge = computed(() => age.value++) // 19
    
        return {
          
          
          age,
          readOnlyAge
        }
      }
    });
    </script>
    
  • Create a readable and writable computed property through the set() and get() methods

    <script lang="ts">
    import {
          
           computed, defineComponent, ref } from 'vue';
    export default defineComponent({
          
          
      setup(props, context) {
          
          
        const age = ref<number>(18)
    
        const computedAge = computed({
          
          
          get: () => age.value + 1,
          set: value => age.value + value
        })
        // 为计算属性赋值的操作,会触发 set 函数, 触发 set 函数后,age 的值会被更新
        age.value = 100
        return {
          
          
          age,
          computedAge
        }
      }
    });
    </script>
    

2. watch function

  • Two small "pits":

    • When monitoring the responsive data defined by reactive: oldValue cannot be obtained correctly, and deep monitoring is forcibly enabled (the deep configuration is invalid).
    • When monitoring an attribute in the reactive data defined by reactive: the deep configuration is valid.
    //情况一:监视ref定义的响应式数据
    watch(sum,(newValue,oldValue)=>{
          
          
    	console.log('sum变化了',newValue,oldValue)
    },{
          
          immediate:true})
    
    //情况二:监视多个ref定义的响应式数据
    watch([sum,msg],(newValue,oldValue)=>{
          
          
    	console.log('sum或msg变化了',newValue,oldValue)
    }) 
    
    /* 情况三:监视reactive定义的响应式数据
    			若watch监视的是reactive定义的响应式数据,则无法正确获得oldValue!!
    			若watch监视的是reactive定义的响应式数据,则强制开启了深度监视 
    */
    watch(person,(newValue,oldValue)=>{
          
          
    	console.log('person变化了',newValue,oldValue)
    },{
          
          immediate:true,deep:false}) //此处的deep配置不再奏效
    
    //情况四:监视reactive定义的响应式数据中的某个属性
    watch(()=>person.job,(newValue,oldValue)=>{
          
          
    	console.log('person的job变化了',newValue,oldValue)
    },{
          
          immediate:true,deep:true}) 
    
    //情况五:监视reactive定义的响应式数据中的某些属性
    watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{
          
          
    	console.log('person的job变化了',newValue,oldValue)
    },{
          
          immediate:true,deep:true})
    
    //特殊情况
    watch(()=>person.job,(newValue,oldValue)=>{
          
          
        console.log('person的job变化了',newValue,oldValue)
    },{
          
          deep:true}) //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效
    

2.1. Listen to the data source declared with reactive

```ts
<script lang="ts">
import { computed, defineComponent, reactive, toRefs, watch } from 'vue';
interface Person {
  name: string,
  age: number
}
export default defineComponent({
  setup(props, context) {
    const state = reactive<Person>({ name: 'vue', age: 10 })

    watch(
      () => state.age,
      (age, preAge) => {
        console.log(age); // 100
        console.log(preAge); // 10
      }
    )
    // 修改age 时会触发watch 的回调, 打印变更前后的值
    state.age = 100
    return {
      ...toRefs(state)
    }
  }
});
</script>
```

2.2. Listen to the data source declared with ref

<script lang="ts">
import {
    
     defineComponent, ref, watch } from 'vue';
interface Person {
    
    
  name: string,
  age: number
}
export default defineComponent({
    
    
  setup(props, context) {
    
    
    const age = ref<number>(10);

    watch(age, () => console.log(age.value)); // 100
    
    // 修改age 时会触发watch 的回调, 打印变更后的值
    age.value = 100
    return {
    
    
      age
    }
  }
});
</script>

2.3. Listening to multiple values ​​at the same time

<script lang="ts">
import {
    
     computed, defineComponent, reactive, toRefs, watch } from 'vue';
interface Person {
    
    
  name: string,
  age: number
}
export default defineComponent({
    
    
  setup(props, context) {
    
    
    const state = reactive<Person>({
    
     name: 'vue', age: 10 })

    watch(
      [() => state.age, () => state.name],
      ([newName, newAge], [oldName, oldAge]) => {
    
    
        console.log(newName);
        console.log(newAge);

        console.log(oldName);
        console.log(oldAge);
      }
    )
    // 修改age 时会触发watch 的回调, 打印变更前后的值, 此时需要注意, 更改其中一个值, 都会执行watch的回调
    state.age = 100
    state.name = 'vue3'
    return {
    
    
      ...toRefs(state)
    }
  }
});
</script>

2.4.stop stop monitoring

setup()A watch created inside a function watchwill automatically stop when the current component is destroyed. If you want to explicitly stop a monitoring, you can call the return value of watch()the function , as follows:

<script lang="ts">
import {
    
     set } from 'lodash';
import {
    
     computed, defineComponent, reactive, toRefs, watch } from 'vue';
interface Person {
    
    
  name: string,
  age: number
}
export default defineComponent({
    
    
  setup(props, context) {
    
    
    const state = reactive<Person>({
    
     name: 'vue', age: 10 })

    const stop =  watch(
      [() => state.age, () => state.name],
      ([newName, newAge], [oldName, oldAge]) => {
    
    
        console.log(newName);
        console.log(newAge);

        console.log(oldName);
        console.log(oldAge);
      }
    )
    // 修改age 时会触发watch 的回调, 打印变更前后的值, 此时需要注意, 更改其中一个值, 都会执行watch的回调
    state.age = 100
    state.name = 'vue3'

    setTimeout(()=> {
    
     
      stop()
      // 此时修改时, 不会触发watch 回调
      state.age = 1000
      state.name = 'vue3-'
    }, 1000) // 1秒之后讲取消watch的监听
    
    return {
    
    
      ...toRefs(state)
    }
  }
});
</script>

3. watchEffect function

  • The routine of watch is: specify not only the attribute of monitoring, but also the callback of monitoring.

  • The routine of watchEffect is: no need to specify which attribute to monitor, which attribute is used in the monitoring callback, then which attribute to monitor.

  • watchEffect is a bit like computed:

    • But computed pays attention to the calculated value (the return value of the callback function), so the return value must be written.
    • And watchEffect pays more attention to the process (the function body of the callback function), so there is no need to write the return value.
    //watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
    watchEffect(()=>{
          
          
        const x1 = sum.value
        const x2 = person.age
        console.log('watchEffect配置的回调执行了')
    })
    

8. Life cycle

```html
<div style="border:1px solid black;width:380px;float:left;margin-right:20px;">
    
<strong>vue2.x的生命周期</strong><img src="https://cn.vuejs.org/images/lifecycle.png" alt="lifecycle_2" style="zoom:33%;width:1200px" /></div><div style="border:1px solid black;width:510px;height:985px;float:left">
    
<strong>vue3.0的生命周期</strong><img src="https://v3.cn.vuejs.org/images/lifecycle.svg" alt="lifecycle_2" style="zoom:33%;width:2500px" /></div>
```
  • The lifecycle hooks in Vue2.x can continue to be used in Vue3.0, but two of them have been renamed:
    • beforeDestroyrename tobeforeUnmount
    • destroyedrename tounmounted
  • Vue3.0 also provides lifecycle hooks in the form of Composition API, and the corresponding relationship with the hooks in Vue2.x is as follows:
    • beforeCreate===>setup()
    • created=======>setup()
    • beforeMount ===>onBeforeMount
    • mounted=======>onMounted
    • beforeUpdate===>onBeforeUpdate
    • updated =======>onUpdated
    • beforeUnmount ==>onBeforeUnmount
    • unmounted =====>onUnmounted

9. Custom hook function

  • What are hooks? —— It is essentially a function that encapsulates the Composition API used in the setup function.

  • Similar to mixin in vue2.x.

  • Advantages of custom hooks: code reuse, making the logic in setup clearer and easier to understand.

    Vue2.x useCount.tsimplementation:

    import {
          
           ref, Ref, computed } from "vue";
    
    type CountResultProps = {
          
          
      count: Ref<number>;
      multiple: Ref<number>;
      increase: (delta?: number) => void;
      decrease: (delta?: number) => void;
    };
    
    export default function useCount(initValue = 1): CountResultProps {
          
          
      const count = ref(initValue);
    
      const increase = (delta?: number): void => {
          
          
        if (typeof delta !== "undefined") {
          
          
          count.value += delta;
        } else {
          
          
          count.value += 1;
        }
      };
      const multiple = computed(() => count.value * 2);
    
      const decrease = (delta?: number): void => {
          
          
        if (typeof delta !== "undefined") {
          
          
          count.value -= delta;
        } else {
          
          
          count.value -= 1;
        }
      };
    
      return {
          
          
        count,
        multiple,
        increase,
        decrease,
      };
    }
    

    use useCountthis hook:

    <template>
      <p>count: {
         
         { count }}</p>
      <p>倍数: {
         
         { multiple }}</p>
      <div>
        <button @click="increase()">加1</button>
        <button @click="decrease()">减一</button>
      </div>
    </template>
    
    <script lang="ts">
    import useCount from "../hooks/useCount";
     setup() {
        const { count, multiple, increase, decrease } = useCount(10);
            return {
                count,
                multiple,
                increase,
                decrease,
            };
        },
    </script>
    

10.toRef

  • Function: The reactive()created be converted into an ordinary object, but each attribute node on this object is ref()a type of responsive data

  • grammar:const name = toRef(person,'name')

  • Application: When you want to provide a property in the responsive object for external use alone.

  • Extension: Same toRefsas toRefthe function, but multiple ref objects can be created in batches, syntax:toRefs(person)

    <template>
      <div class="mine">
        {
         
         {name}} // test
        {
         
         {age}} // 18
      </div>
    </template>
    
    <script lang="ts">
    import { defineComponent, reactive, ref, toRefs } from 'vue';
    export default defineComponent({
      setup(props, context) {
        let state = reactive({
          name: 'test'
        });
    
        const age = ref(18)
        
        return {
          ...toRefs(state),
          age
        }
      }
    });
    </script>
    

3. Other Composition APIs

1.shallowReactive 与 shallowRef

  • shallowReactive: Create a responsive proxy that tracks the responsiveness of its own properties shallowReactiveto generate non-recursive response data, only handles the responsiveness of the outermost properties of the object, but does not perform deep reactive transformations of nested objects (exposing the original value) ( Shallow Responsive).

  • shallowRef: only handles the response of basic data types, not the response of objects.

  • When to use it?

    • If there is an object data, the structure is relatively deep, but only the outer attribute changes ===> shallowReactive.
    • If there is an object data, the subsequent function will not modify the properties in the object, but generate a new object to replace ===> shallowRef.
    <script lang="ts">
    import {
          
           shallowReactive } from "vue";
    export default defineComponent({
          
          
      setup() {
          
          
        
        const test = shallowReactive({
          
           num: 1, creator: {
          
           name: "撒点了儿" } });
        console.log(test);
    
        
        test.creator.name = "掘金";
    
        return {
          
          
          test
        };
      },
    });
    </script>
    

2.readonly 与 shallowReadonly

  • readonly: pass in refor reactiveobject , and return a read-only proxy of the original object, any nested properties inside the object are also read-only, and are recursively read-only, that is, make a responsive data read-only (deep read-only).

  • shallowReadonly: The function only deals with the responsive (shallow responsive) read-only of the outermost properties of the object, but does not perform deep read-only conversion of nested objects (exposing the original value), that is, making a responsive data read-only (shallow read-only).

  • Application scenario: When the data is not expected to be modified.

    <script lang="ts">
    import {
          
           readonly, reactive } from "vue";
    export default defineComponent({
          
          
      setup() {
          
          
        const test = reactive({
          
           num: 1 });
    
        const testOnly = readonly(test);
    
        console.log(test);
        console.log(testOnly);
        
        test.num = 110;
        
        // 此时运行会提示 Set operation on key "num" failed: target is readonly.
        // 而num 依然是原来的值,将无法修改成功
        testOnly.num = 120;
        
        // 使用isReadonly() 检查对象是否是只读对象
        console.log(isReadonly(testOnly)); // true
        console.log(isReadonly(test)); // false
        
        // 需要注意的是: testOnly 值会随着 test 值变化
    
        return {
          
          
          test,
          testOnly,
        };
      },
    });
    </script>
    

Attachment: readonlyWhat constis the difference between

  • constIt is assignment protection, using constthe defined variable, the variable cannot be reassigned. But if constthe assignment is an object, then the things inside the object can be changed. The reason is that constthe defined variable cannot be changed. That is, the address corresponding to the object cannot be changed.
  • It isreadonly attribute protection, and attributes cannot be reassigned

3. toRaw and markRaw

  • toRaw:
    • Function: Convert a responsive objectreactive generated by a bot into a normal object .
    • Usage scenario: It is used to read the common object corresponding to the responsive object. All operations on this common object will not cause page updates.
  • markRaw:
    • Role: Mark an object so that it will never become a responsive object again.
    • Application scenario:
      1. Some values ​​should not be set responsive, such as complex third-party libraries, etc.
      2. Skipping reactive transformations can improve performance when rendering large lists with immutable data sources.

4.customRef

  • Role: Create a custom ref with explicit control over its dependency tracking and update triggering.

  • To achieve the anti-shake effect:

    <template>
    	<input type="text" v-model="keyword">
    	<h3>{
         
         {keyword}}</h3>
    </template>
    
    <script>
    	import {ref,customRef} from 'vue'
    	export default {
    		name:'Demo',
    		setup(){
    			// let keyword = ref('hello') //使用Vue准备好的内置ref
    			//自定义一个myRef
    			function myRef(value,delay){
    				let timer
    				//通过customRef去实现自定义
    				return customRef((track,trigger)=>{
    					return{
    						get(){
    							track() //告诉Vue这个value值是需要被“追踪”的
    							return value
    						},
    						set(newValue){
    							clearTimeout(timer)
    							timer = setTimeout(()=>{
    								value = newValue
    								trigger() //告诉Vue去更新界面
    							},delay)
    						}
    					}
    				})
    			}
    			let keyword = myRef('hello',500) //使用程序员自定义的ref
    			return {
    				keyword
    			}
    		}
    	}
    </script>
    

5.provide and inject

  • Role: Realize communication between ancestor and descendant components

  • Routine: the parent component has an provideoption to provide data, and the descendant components have an injectoption to start using this data

  • Specifically written:

    1. Basic use:

      setup(){
      	......
          let car = reactive({name:'奔驰',price:'40万'})
          provide('car',car)
       // 父组件
      <script lang="ts">
      import { defineComponent } from 'vue';
      export default defineComponent({
        provide: {
          provideData: { name: "撒点了儿" },
        }
      });
      </script>
      
      // 子组件
      <template>
        <div class="hello">
          <h1>{
             
             { msg }}</h1>
          {
             
             { provideData }}
        </div>
      </template>
      
      <script lang="ts">
      export default defineComponent({
        name: "HelloWorld",
        props: {
          msg: String,
        },
        inject: ["provideData"],
      });
      </script>
      
    2. Use in setup():

      name:parameter name

      value: the value of the attribute

      <script lang="ts">
      import { provide } from "vue";
      import HelloWorldVue from "./components/HelloWorld.vue";
      export default defineComponent({
        name: "App",
        components: {
          HelloWorld: HelloWorldVue,
        },
        setup() {
          provide("provideData", {
            name: "撒点了儿",
          });
        },
      });
      </script>
      
      <script lang="ts">
      import { provide, inject } from "vue";
      export default defineComponent({
        name: "HelloWorld",
        props: {
          msg: String,
        },
        setup() {
          const provideData = inject("provideData");
          
          console.log(provideData); //  { name: "撒点了儿"  }
      
          return {
            provideData,
          };
        },
      });
      </script>
      
    3. pass response data

      
      <script lang="ts">
      import {
              
               provide, reactive, ref } from "vue";
      import HelloWorldVue from "./components/HelloWorld.vue";
      export default defineComponent({
              
              
        name: "App",
        components: {
              
              
          HelloWorld: HelloWorldVue,
        },
        setup() {
              
              
          const age = ref(18);
      
          provide("provideData", {
              
              
            age,
            data: reactive({
              
               name: "撒点了儿" }),
          });
        },
      });
      </script>
      
      
      <script lang="ts">
      import {
              
               inject } from "vue";
      export default defineComponent({
              
              
        name: "HelloWorld",
        props: {
              
              
          msg: String,
        },
        setup() {
              
              
          const provideData = inject("provideData");
      
          console.log(provideData);
      
          return {
              
              
            provideData,
          };
        },
      });
      </script>
      

      We recommend using readonly for provider properties if you want to ensure that data passed through provide will not be changed by injected components.

6. Judgment of responsive data

  • isRef: checks if a value is a ref object
  • isReactive: checks if an object was reactivecreated a reactive proxy
  • isReadonly: checks if an object was readonlycreated a read-only proxy
  • isProxy: Checks if an object reactiveis readonlya proxy created by the or method

4. Advantages of Composition API

1. Problems with the Options API

In the traditional OptionsAPI, if you add or modify a requirement, you need to modify it in data, methods, and computed respectively.

2. Advantages of Composition API

We can organize our code and functions more elegantly. Let the code of related functions be organized together in a more orderly manner.

5. New components

1.Fragment (less divs)

  • In Vue2: Components must have a root tag
  • In Vue3: Components can have no root tags, and multiple tags will be included in a Fragment virtual element internally
  • Benefits: Reduce label levels, reduce memory usage

2.Teleport

  • What is Teleport? -- Teleportis a technique that can move our component html structure to a specified location.

    <teleport to="移动位置">
    	<div v-if="isShow" class="mask">
    		<div class="dialog">
    			<h3>我是一个弹窗</h3>
    			<button @click="isShow = false">关闭弹窗</button>
    		</div>
    	</div>
    </teleport>
    

3.Suspense

ReactSuspensethe components

React.lazyAccepts a function that needs to be called dynamically import(). It must return a Promise, which Promiserequires aresolve component of the .default exportReact

import React, { Suspense } from 'react';
 
 
const myComponent = React.lazy(() => import('./Component'));
 
 
function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <myComponent />
      </Suspense>
    </div>
  );
}

Vue3React.lazyA similar function has also been added defineAsyncComponentto handle dynamically imported (components). defineAsyncComponentA factory function that can accept a return Promise. PromiseThe parse callback that should be called when you retrieved the component definition from the server . You can also indicate reject(reason)that a load has failed by calling

import {
    
     defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>
  import('./components/AsyncComponent.vue')
)

app.component('async-component', AsyncComp)

Vue3 also added a Suspense component:

<template>
  <Suspense>
    <template #default>
      <my-component />
    </template>
    <template #fallback>
      Loading ...
    </template>
  </Suspense>
</template>

<script lang='ts'>
 import { defineComponent, defineAsyncComponent } from "vue";
 const MyComponent = defineAsyncComponent(() => import('./Component'));

export default defineComponent({
   components: {
     MyComponent
   },
   setup() {
     return {}
   }
})
</script>

6. Others

1. Transfer of global API

  • Vue 2.x has many global APIs and configurations.

    • For example: registering global components, registering global directives, etc.

      //注册全局组件
      Vue.component('MyButton', {
              
              
        data: () => ({
              
              
          count: 0
        }),
        template: '<button @click="count++">Clicked {
              
              { count }} times.</button>'
      })
      
      //注册全局指令
      Vue.directive('focus', {
              
              
        inserted: el => el.focus()
      }
      
  • These APIs have been adjusted in Vue3.0:

    • Adjust the global API, ie: Vue.xxxto the application instance ( app)

      2.x Global API ( Vue) 3.x instance API ( app)
      Vue.config.xxxx app.config.xxxx
      Vue.config.productionTip remove
      Vue.component app.component
      Directive.view app.directive
      Vue.mixin app.mixin
      Vue.use app.use
      Vue.prototype app.config.globalProperties

2. Other changes

  • The data option should always be declared as a function.

  • Excessive class name changes:

    • Vue2.x writing method

      .v-enter,
      .v-leave-to {
              
              
        opacity: 0;
      }
      .v-leave,
      .v-enter-to {
              
              
        opacity: 1;
      }
      
    • Vue3.x writing method

      .v-enter-from,
      .v-leave-to {
              
              
        opacity: 0;
      }
      
      .v-leave-from,
      .v-enter-to {
              
              
        opacity: 1;
      }
      
  • Remove keyCode as a v-on modifier, and no longer supportconfig.keyCodes

  • removev-on.native modifier

    • Bind event in parent component

      <my-component
        v-on:close="handleComponentEvent"
        v-on:click="handleNativeClickEvent"
      />
      
    • Declare custom events in subcomponents

      <script>
        export default {
          emits: ['close']
        }
      </script>
      
  • remove filter

    Filters While this seems convenient, it requires a custom syntax that breaks the assumption that expressions inside curly braces are "just JavaScript", which has not only a learning cost, but an implementation cost as well! It is recommended to replace filters with method calls or computed properties.

Seven, vue 3.x complete component template structure (TS version)

<template>
  <div class="mine" ref="elmRefs">
    <span>{
   
   {name}}</span>
    <br>
    <span>{
   
   {count}}</span>
    <div>
      <button @click="handleClick">测试按钮</button>
    </div>

    <ul>
      <li v-for="item in list" :key="item.id">{
   
   {item.name}}</li>
    </ul>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, getCurrentInstance, onMounted, PropType, reactive, ref, toRefs } from 'vue';

interface IState {
  count: number
  name: string
  list: Array<object>
}

export default defineComponent({
  name: 'demo',
  // 父组件传子组件参数
  props: {
    name: {
      type: String as PropType<null | ''>,
      default: 'vue3.x'
    },
    list: {
      type: Array as PropType<object[]>,
      default: () => []
    }
  },
  components: {
    /// TODO 组件注册
  },
  emits: ["emits-name"], // 为了提示作用
  setup (props, context) {
    console.log(props.name)
    console.log(props.list)
    
    
    const state = reactive<IState>({
      name: 'vue 3.0 组件',
      count: 0,
      list: [
        {
          name: 'vue',
          id: 1
        },
        {
          name: 'vuex',
          id: 2
        }
      ]
    })

    const a = computed(() => state.name)

    onMounted(() => {

    })

    function handleClick () {
      state.count ++
      // 调用父组件的方法
      context.emit('emits-name', state.count)
    }
  
    return {
      ...toRefs(state),
      handleClick
    }
  }
});
</script>

Ecology of vue 3

UI component library

Guess you like

Origin blog.csdn.net/MoXinXueWEB/article/details/126964554