Vue3 has become the default version, and these intersections with vue3 are here

catalogue

It is said that Vue3 has become the default version. Learn it quickly!

Common knowledge points related to Vue3

I Encounter with Composition composite API

1.1 initial intersection with setup

  1. setup is a new configuration item of Vue3. The value is a function

  2. All properties and methods used by the component need to be configured in setup, and then return them to an object for use by the template

  3. The data of setup can be accessed in the configuration item of Vue2, but the data of Vue2 cannot be accessed in setup; In case of duplicate names, the data defined by setup will be preferentially displayed

  4. You can't add async before setup because the return value is no longer a return object, but a promise. The template can't see the attributes in the return object;

    You can also return a Promise instance, but suspension and asynchronous components are required

    I'm Vue3 test component

    {{username}}---{{password}}

1.2 ref function

Usually, we use ref to change the basic data type into a responsive data type. At this time, we need to use the ref function

For basic types of data, the response expression still depends on object get and set of defineproperty();

For data of reference type, a reactive function is used internally

  1. You can use the data source returned by setup normally in the template

  2. If you want to modify the data, you can only use the attribute name value to modify

    User name: {username}}

    Password: {password}}

1.3 reactive function

Usually, we will use reactive to create a responsive object to store the corresponding data source;

<template>
  <p>{{ person.username }}</p>
  <p>{{ person.password }}</p>
  <br />
  <p>{{ person.job.name }}</p>
  <button @click="changeInfo()">Modify information</button>
</template>

<script>
import { reactive } from "vue";
export default {
  setup() {
    const person = reactive({
      username: "zhangsan",
      password: "999",
      job: {
        name: "Web front end",
        salary: "30k",
      },
    });

    const changeInfo = () => {
      (person.username = "aaaaaaaa"), (person.job.name = "Java development");
    };
    return {
      person,
      changeInfo,
    };
  },
};
</script>

<style></style>

1.4 precautions for setup

  • Timing of setup execution

    • Execute once before beforeCreate. this is undefined.
  • Parameters of setup

    • props: the value is an object, including the attributes passed from outside the component and declared and received inside 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, which is equivalent to this$ attrs.
      • Slots: received slot content, equivalent to this$ slots.
      • Emit: a function that distributes custom events, equivalent to this$ emit.

1.5 calculation attributes

<template>
  surname: <input type="text" v-model="person.firstName">
  name: <input type="text" v-model="person.lastName">
  <p>
    full name: <input v-model="person.fullName" />
  </p>
</template>

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

export default {
  setup() {
    const person  = reactive({
      firstName: 'Zhang',
      lastName: 'Ais',
    })
    /* Calculation attribute abbreviation */
    /* person.fullName = computed(()=>{
      return person.firstName + '-' + person.lastName
    }) */

    /* Calculation attribute complete writing method */
    person.fullName = computed({
      get(){
        return person.firstName + '-' + person.lastName
      },
      set(value){
        const nameArr = value.split("-");
        person.firstName = nameArr[0]
        person.lastName = nameArr[1]
      }
    })
    return {
      person
    }
  }
}
</script>

<style>

</style>

1.6 watch monitoring

Two points of attention

  1. When watch monitors the responsive data defined by reactive: oldValue cannot be obtained correctly, and deep monitoring is forced on (deep configuration fails),
  2. When watch monitors an object attribute in the reactive data defined by reactive, the deep configuration is valid

When watch monitors ref data, there is no need to go to basic types of data value is used to monitor. When monitoring the object data defined by ref, in fact, the internal reactive function is used, and there is no need to monitor value, you only need to configure the deep attribute inside the third configuration object

<template>
  <h1>watch monitor</h1>
  <span>Current summation is: {{ sum }}</span>
  <button @click="sum++">Point me+1</button>
  <p @click="message += '!'">{{ message }}</p>
  <hr />
  <p @click="person.name += '~'">full name: {{ person.name }}</p>
  <p @click="person.age++">Age: {{ person.age }}</p>
  <p>Working salary:{{ person.job.Java.money }}k</p>
  <button @click="person.job.Java.money++">Salary rise</button>
</template>

<script>
import { ref, watch, reactive } from "vue";
export default {
  setup() {
    let sum = ref(0);
    let message = ref("How do you do");
    const person = reactive({
      name: "Wang Wu",
      age: 12,
      job: {
        Java: {
          money: 20,
        },
      },
    });
    /* Monitor individual data changes */
    watch(
      sum,
      (newValue, oldValue) => {
        console.log(newValue, oldValue); // 1 0
      },
      {
        immediate: true,
        deep: true,
      }
    );

    /* Monitor multiple data changes */
    watch(
      [sum, message],
      (newValue, oldValue) => {
        console.log(newValue, oldValue); //  [0, 'Hello!' [0, 'hello']
      },
      {
        immediate: true,
      }
    );

    /* Monitor all attributes of reactive data */
    /* Question:
      1.If you want to monitor reactive data, the oldValue will not get correctly
      2.Depth monitoring is started by default, and it is invalid to turn off depth monitoring
    */
    watch(
      person,
      (newValue, oldValue) => {
        console.log(newValue, oldValue);
      },
      {
        deep: false, // deep is invalid here
      }
    );

    /* Monitor individual properties of reactive data */
    watch(
      () => person.name,
      (newValue, oldValue) => {
        console.log("person.name The value of has changed!", newValue, oldValue);
      }
    );

    /* reactive data list */
    watch([() => person.name, () => person.age], (newValue, oldValue) => {
      console.log("person.name The value of has changed!", newValue, oldValue);
    });

    /* Object properties for monitoring reactive data */
    watch(
      () => person.job,
      (newValue, oldValue) => {
        console.log("person.job The internal value has changed!", newValue, oldValue);
      },
      // deep here is valid
      { deep: true }
    );

    return {
      sum,
      message,
      person,
    };
  },
};
</script>

<style></style>

1.7 watchEffect function

The watchEffect function does not indicate which attribute to monitor, but which attributes are used in the monitored callback.

Compute is similar to effect

  • computed pays more attention to the calculated return value

  • watchEffect pays more attention to the process, the function body of the callback function, and there is no need to write the return value

    watchEffect function

    The current sum is: {sum}}

1.8 life cycle function of vue3

In Vue3, you can also use the configuration lifecycle function of Vue2 or the combined API lifecycle function provided by Vue3

Vue3.0 also provides a lifecycle hook in the form of Composition API, which is similar to vue2 The corresponding relationship of hooks in X is as follows:

  • beforeCreate===>setup()
  • created=======>setup()
  • beforeMount ===>onBeforeMount
  • mounted=======>onMounted
  • beforeUpdate===>onBeforeUpdate
  • updated =======>onUpdated
  • beforeUnmount ==>onBeforeUnmount
  • unmounted =====>onUnmounted

be careful:

  1. The execution time of each configuration lifecycle function of Vue2 is one step slower than that of Vue3's combined API

  2. Soft the beforeCreate and created hook functions into setup

    I'm HelloWorld component

    The current sum is: {sum}}

1.9 customize the hooks function and experience the advantages of combined API

A function function is uniformly encapsulated using the composite API, and other modules only need to be called. There is no need to care about the internal implementation logic of the function!

Usepoint. In the hooks folder JS function

import { reactive, onMounted, onBeforeUnmount } from 'vue'

export default function () {
  const point = reactive({
    x: 0,
    y: 0,
  });
  /* Custom hooks function to get mouse focus */
  function getPointPosition(event) {
    point.x = event.pageX;
    point.y = event.pageY;
    console.log(point.x, point.y);
  }

  onMounted(() => {
    window.addEventListener("click", getPointPosition);
  });

  onBeforeUnmount(() => {
    window.removeEventListener("click", getPointPosition);
  });
  // Hand over the coordinate object so that other modules can use the functions of this module
  return point
}

HelloWorld component

<template>
  <h1>I am HelloWorld assembly</h1>
  <h2>Custom get mouse coordinates hooks function</h2>
  <span>
    x Coordinates of: {{ point.x }}
    <br />
    y Coordinates of: {{ point.y }}
  </span>
</template>

<script>
import { ref } from "vue";
import getPointHooks from '../hooks/usePoint'
export default {
  setup() {
    let sum = ref(0);
    // Get the hooks function of the custom module
    let point = getPointHooks()

    return {
      sum,
      point,
    };
  },
};
</script>

App components

<template>
  <div>
    <button @click="isShow = !isShow">Exhibition/Hide Components</button>
    <HelloWorld v-if="isShow" />
  </div>
</template>

<script>
import { ref } from "vue";
import HelloWorld from "./components/HelloWorld.vue";
export default {
  components: { HelloWorld },
  setup() {
    let sum = ref(0);
    let isShow = ref(true);
    return {
      sum,
      isShow,
    };
  },
};
</script>

1.10 use of toref and toRefs

  • Function: create a ref object whose value points to an attribute in another object.

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

  • Application: when you want to provide a property in a responsive object to external users separately.

  • Extension: the function of toRefs is the same as that of toRef, but multiple ref objects can be created in batch. Syntax: toRefs(person)

    I'm HelloWorld component

    toRef and toRefs

    {{ person }}

    {{ person.username }}

    {{ person.password }}


    {{ person.job.name }}

    {{ person.job.salary }}k

2, Other uncommon composition APIs

2.1 shallowReactive and shallowRef

  • shallowReactive: deals only with the response of the outermost attribute of the object (shallow response).

  • shallowRef: only the response of basic data type is processed, and the response of object is not processed.

  • When to use

    • If there is an object data, the structure is relatively deep, but the change is only the outer attribute change = = = > shallowreactive.
    • If there is an object data, the subsequent function will not modify the attributes in the object, but generate a new object to replace = = = > shallowref.

    I'm HelloWorld component

    shallowReactive and shallowRef

    {{ person }}

    {{ person.username }}

    {{ person.password }}

    {{ person.age }}

2.2 readonly and shallowReadonly

  • readonly: change a responsive data into read-only data (deep read-only, nested deep data cannot be modified)
  • shallowReadonly: make a responsive data read-only (shallow read-only, nested deep-level data can be modified, and the first level data cannot be modified)

Data can be used to prevent modification when it does not want to be modified

<template>
  <h1>I am HelloWorld assembly</h1>
  <h2>shallowReactive And shallowRef</h2>

  <h3>{{ person }}</h3>
  <p>{{ person.username }}</p>
  <p>{{ person.password }}</p>
  <p>{{ person.age }}</p>
  <button @click="person.age++">Modify age</button>
  <br />
  <p>{{ person.job.name }}</p>
  <p>{{ person.job.salary }}k</p>
  <button @click="person.job.salary++">Modify salary</button>
  <button @click="changeInfo()">Modify information</button>
  <hr>
</template>

<script>
import { ref, reactive, toRef, toRefs, shallowReactive,shallowRef, readonly, shallowReadonly } from "vue";
export default {
  setup() {
    let sum = ref(0);
    let person = shallowReactive({
      username: "zhangsan",
      password: "999",
      age:1,
      job: {
        name: "Web front end",
        salary: 30,
      },
    });
    /* Using readonly to mark responsive data is only readable */
    // person = readonly(person)

    // Use shallowReadonly to mark data
    person = shallowReadonly(person)

    const changeInfo = () => {
      person.username = "aaaaaaaa";
      person.password = '111111111111111111111'
      person.job.name = "Java development";
      person.job.salary++;
    };

    return {
      sum,
      person,
      changeInfo,
    };
  },
};
</script>

2.3 toRaw and markRaw

  • toRaw transforms a reactive marked responsive object into an ordinary object. In short, it is to make the object lose the responsive object

    Used for: the need to change data without causing page update

  • markRaw: mark an object so that it will never become a responsive object

    Sometimes we need to add a property to a specific responsive object, but we don't want it to be responsive, so we need this

    <template>
      <h1>I am HelloWorld assembly</h1>
      <h2>shallowReactive And shallowRef</h2>
    
      <h3>{{ person }}</h3>
      <p>{{ person.username }}</p>
      <p>{{ person.password }}</p>
      <p>{{ person.age }}</p>
      <button @click="person.age++">Modify age</button>
      <br />
      <p>{{ person.job.name }}</p>
      <p>{{ person.job.salary }}k</p>
      <p v-show="person.car">{{ person.car }}</p>
      <button @click="person.job.salary++">Modify salary</button>
      <button @click="changeInfo()">Modify information</button>
      <button @click="changeRawObj">Change the responsive object to the original object</button>
      <button @click="addCar">Add a car</button>
      <button @click="person.car.name += '~'">Modify the name of the car</button>
      <hr />
    </template>
    
    <script>
    import {
      ref,
      toRaw,
      shallowReactive,
      shallowRef,
      readonly,
      shallowReadonly,
      markRaw,
    } from "vue";
    export default {
      setup() {
        let sum = ref(0);
        let person = shallowReactive({
          username: "zhangsan",
          password: "999",
          age: 1,
          job: {
            name: "Web front end",
            salary: 30,
          },
        });
    
        const changeInfo = () => {
          person.username = "aaaaaaaa";
          person.password = "111111111111111111111";
          person.job.name = "Java development";
          person.job.salary++;
        };
        const changeRawObj = () => {
          // Change the reactive object defined by reactive into the original object
          const rawObj = toRaw(person);
          console.log(rawObj);
        };
        const addCar = () => {
          let car = markRaw({
            name: "bmw",
            price: "30w",
          });
          person.car = car;
        };
        return {
          sum,
          person,
          changeInfo,
          addCar,
          changeRawObj,
        };
      },
    };
    </script>
    

    2.4 customRef

    Create a custom ref to track and trigger its dependencies

    <template>
      <h1>custom Ref</h1>
      <input v-model="keyWord" /> <br />
      <span>{{ keyWord }}</span>
    </template>
    
    <script>
    import { customRef } from 'vue'
    export default {
      setup() {
        function myRef(value, delay) {
          let timer;
          return customRef((track, trigger)=>{
            return {
              get(){
                console.log(`Someone from myRef The data is read from this container. The value is ${value}`);
                // The track function is used to track the change of value
                track();
                return value
              },
    
              set(newValue){
                console.log(`myRef The data of the container has been modified,Value is ${newValue}`);
                clearTimeout(timer)
                timer = setTimeout(()=>{
                  value = newValue;
                  // Notify Vue to re resolve the template
                  trigger()
                }, delay)
              }
            }
          })
        }
        
        let keyWord = myRef("HelloWorld", 10);
    
    
        return {
          keyWord,
        };
      },
    };
    </script>
    

2.4 provide and inject

Provide and inject are used to realize the communication between root components and descendant components. Of course, sub components can also obtain the data provided by provide. We generally use props directly

Parent component:provide('Communication name', Communication data)Subcomponents const data = inject('Communication name')

2.5 judgment of responsive data

  • isRef: check whether a value is a ref object
  • isReactive: checks whether an object is a reactive proxy created by reactive
  • isReadonly: checks whether an object is a read-only proxy created by readonly
  • isProxy: check whether an object is a proxy created by the reactive or readonly method

3, New components

3.1Fragment

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

3.2 Teleport

  • What is teleport—— Teleport is a technology that can move our component html structure to a specified location.

    <teleport to="Move position"> // to="body | html | div| #box ..."
    	<div v-if="isShow" class="mask">
    		<div class="dialog">
    			<h3>I am a pop-up window</h3>
    			<button @click="isShow = false">Close pop-up window</button>
    		</div>
    	</div>
    </teleport>
    

3.3 Suspense

  • Render some extra content while waiting for asynchronous components, so that the application has a better user experience

  • Use steps:

    • Asynchronous import component

      import {defineAsyncComponent} from 'vue'const Child = defineAsyncComponent(()=>import('./components/Child.vue'))
      
    • Use suspend to wrap components and configure default and fallback

      <template>	<div class="app">		<h3>I am App assembly</h3>		<Suspense>			<template v-slot:default>				<Child/>			</template>			<template v-slot:fallback>				<h3>Loading.....</h3>			</template>		</Suspense>	</div></template>
      

4, Other

4.1 transfer of global API

  • Vue 2.x has many global API s and configurations.

    • For example: register global components, register global instructions, etc.

      //Register the global component Vue component('MyButton', {  data: () => ({    count: 0  }),  template: '<button @click="count++">Clicked {{ count }} times.</ Button > '}) / / register the global instruction Vue directive('focus', {  inserted: el => el.focus()}
      
  • Vue3. These API s have been adjusted in 0:

    • The global API, Vue XXX is adjusted to 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

      Vue.directive

      app.directive

      Vue.mixin

      app.mixin

      Vue.use

      app.use

      Vue.prototype

      app.config.globalProperties

4.2 other changes

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

  • Excessive class name change:

    • Vue2.x writing

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

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

  • Remove v-on Native modifier

    • Binding events in parent component

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

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

5, Integrating TS in Vue3

First, after integrating TS in Vue3, the corresponding components are written as follows

<template>

</template>

<script lang="ts">
// You need to introduce defineComponent to define components and limit the types of data in components
import {defineComponent} from 'vue'

export default defineComponent({
  name:''
  
})
</script>

5.1 initial integration of TS

<template>
  <hr />
  <h2>I am HelloWorld assembly</h2>
  <hr />
  <div>{{ msg }}</div>
  <button @click="changeMsg()">Modify data</button>
  <div>{{ newsData }}</div>
  <div>{{newsData2}}</div>
  <div>Calculation properties: {{newMsg}}</div>
  <hr />
  <p>setup Data</p>
  <div>{{ new2 }}</div>
  <button @click="changeMsg2()">modify new2 Data</button>
</template>

<script lang="ts">
import { defineComponent, reactive } from "vue";

const msg = "I am a type check data";

interface News {
  title: string;
  id: number;
  desc: string;
  content?: string;
}
// The first way to write
let newsData: News = {
  title: "Message 1",
  id: 1,
  desc: "I'm message 1",
};


export default defineComponent({
  name: "HelloWorld.vue",
  data() {
    return {
      msg,
      newsData,
      // The second way to write
      newsData2: {
        title: "Message 2",
        id: 2,
        desc: "I'm message 2",
      } as News,
    };
  },
  methods: {
    changeMsg(): void {
      this.msg = "Modified data";
    },
  },
  computed: {
    newMsg(): string {
      return this.msg.split("").reverse().join("")
    }
  },
  setup() {
    let new2: News = reactive({
      title: "Message 1",
      id: 1,
      desc: "I'm message 1",
      content: "Today's work is done today",
    });
    function changeMsg2(): void {
      new2.title += "!";
      new2.id += 1;
    }
    return {
      new2,
      changeMsg2,
    };
  },
});
</script>

5.2 integrating TS in Composition API

<template>
  <hr />
  <h2>I am HelloWorld assembly</h2>
  <h3>stay Vue3 in Composition API integrate TS</h3>
  <p>full name: {{ username }}</p>
  <p>Age: {{ age }}</p>
  <button @click="setUserName('aaaaaaaa')">Change your name</button>
  <p>Reading age: {{ getUserName() }}</p>
  <hr />
  <p>check ref Data type:{{ count }}</p>
  <p>Calculation properties: {{reverseName}}</p>
</template>

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

interface User {
  username: string;
  age: number | string;
  setUserName(username: string): void;
  getUserName(): string;
}

export default defineComponent({
  name: "HelloWorld.vue",
  setup() {
    /* The first way to write type verification */
    /* const user: User = reactive({
      username: "Zhang San ",
      age: 10,
      getUserName(): string {
        return this.username;
      },
      setUserName(usesrname: string): void {
        this.username = usesrname;
      }
    }); */
    /* The second way to write type verification */
    /* const user = reactive<User>({
      username: "Zhang San ",
      age: 10,
      getUserName(): string {
        return this.username;
      },
      setUserName(usesrname: string): void {
        this.username = usesrname;
      }
    }); */
    /* The third way to write type verification */
    const user = reactive({
      username: "Zhang San",
      age: 10,
      getUserName(): string {
        return this.username;
      },
      setUserName(usesrname: string): void {
        this.username = usesrname;
      },
    }) as User;
    console.log(toRefs(user));

    /* Verify ref data type */
    // let count: string = ref('22'); // Type 'Ref<string>' is not assignable to type 'string'.
    let count = ref<number | string>("22");

    /* Test calculation properties */
    let reverseName = computed((): string => {
      return user.username.split("").reverse().join("");
    });
    console.log(reverseName);
    
    return {
      ...toRefs(user),
      count,
      reverseName,
    };
  },
});
</script>

5.3 using Vuex in Composition

store.ts

import { createStore } from 'vuex'

export default createStore({
  state: {
    count: 0
  },
  mutations: {
    changeCount(state,payload) {
      // state.count++
      state.count = payload
    }
  },
  actions: {
    asyncChangeCount({commit}, payload) {
      setTimeout(()=>{
        commit('changeCount', payload)
      },1000)
    }
  },
  getters: {
    countGetter(state){
      return state.count * 10;
    },
  },
  modules: {
  }
})

app.vue

In the composite API, if you want to access Vuex, you need to use useStore

<template>
  <h1>I am App Root component</h1>
  <h2>stay Vuex Medium integration TS</h2>
  <p>current count For:{{count}}</p>
  <button @click="changeCount()">change Vuex Medium count</button>
  <hr>
  <p>getters: {{countGetters}}</p>
</template>

<script lang="ts">

import { defineComponent, computed } from "vue";
import { useStore } from 'vuex';


export default defineComponent({
  name: "App.vue",
  setup() {
    const store = useStore()
    let count = computed(()=>{
      return store.state.count
    })
    const changeCount = ()=>{
      // store.commit('changeCount')
      store.dispatch('asyncChangeCount', 20)
    }
    const countGetters = computed(()=>{
      return store.getters.countGetter
    })
    return {
      count,
      changeCount,
      countGetters
    }
  }
});
</script>

<style lang="less">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

#nav {
  padding: 30px;

  a {
    font-weight: bold;
    color: #2c3e50;

    &.router-link-exact-active {
      color: #42b983;
    }
  }
}
</style>

Keywords: Javascript Front-end Vue.js html

Added by discombobulator on Sat, 05 Mar 2022 18:52:37 +0200