vue3-basics

insert image description here

document

Shang Silicon Valley Video: https://www.bilibili.com/video/BV1Zy4y1K7SH?p=136
Official Document: https://cn.vuejs.org/guide/introduction.html

This paper summarizes each section first, and then presents the case.

setup

Summarize

  1. Understanding: A new configuration item in vue3.0, 值为一个函数.

  2. The setup is the "stage of performance" of all composition APIs.

  3. The components used in: 数据、方法等等must be configured in the setup.

  4. Two return values ​​of the setup function:

    1. If 返回一个对象, then the attributes 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)
  5. Execution timing: Execute once before beforCreate, at this time this is undefined

  6. 参数

    1. props: The value is an object, which is passed from outside the component, and the internal props of the component declares the received property;
    2. context:context object:
      • attrs: The value is an object, passed by the parent component, but the received attribute is not declared in the internal props; equivalent tothis.$attrs
      • slots: received slot content; equivalent tothis.$slots
      • emit: A function that distributes custom events, equivalent tothis.$emit
  7. important point:

    1. Try not to mix with Vue2.x configuration
      • The properties and methods in the setup can be accessed in the 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.

basic use

The basic use is as follows: (The following methods are non-responsive, and the reactive method needs to use functions such as ref and reactive)
insert image description here

Full code:

<template>
  <h2>name:{
   
   {name}}</h2>
  <h2>age:{
   
   {age}}</h2>
  <h2>sayHello:<button @click="sayHello">点击在控制台打印</button></h2>
</template>

<script>
import {
      
      ref} from "vue"
export default {
      
      
  setup(){
      
      
    //数据
    let name = "ljy";
    let age = ref(18);
    //方法
    function sayHello(){
      
      
      console.log(`你好啊,我是${ 
        name}`)
    }
    //返回一个对象
    return {
      
      
      name,
      age,
      sayHello,
    }
  }
}
</script>

parameter of setup

insert image description here

The complete code is as follows:
parent component App.vue:

<template>
  <school msg="欢迎光临" name="张三" @myEvent="myEvent">
    <!-- 用于测试子组件接收插槽内容 -->
    <template v-slot:slot1>
      <span>插槽内容...</span>
    </template>
  </school>
</template>

<script>
import School from './components/School.vue'
export default {
      
      
  components: {
      
       School },
  beforeCreate() {
      
      
    console.log("beforeCreate");
  },
  setup() {
      
      
    //用于测试setup在beforeCreate之前,且this为undefined
    console.log("setup");

    return {
      
      
      //用于子组件触发自定义事件
      myEvent() {
      
      
        alert('触发MyEvent事件')
      }
    }
  }
}
</script>

Subcomponent School.vue

<template>
  <button @click="onclick">点我触发myEvent事件</button>
</template>

<script>
export default {
      
      
    emits:["myEvent"],
    props:["msg"],
    setup(props,context){
      
      
        //测试setup的参数:
        console.log("props",props);//属性是props接收的
        console.log("attrs",context.attrs);//父组件传了,但props没接收的(捡漏)
        console.log("slots",context.slots);//父组件定义的插槽信息
        console.log("emit",context.emit);//父组件绑定的事件

        return{
      
      
            //点击后,触发父组件中的myEvent事件:
            onclick(){
      
      
                context.emit("myEvent")
            }
        }
    }
}
</script>

<style>

</style>

ref function

Summarize:

  • Role: define a 响应式data

  • grammar:const xxx = ref(初始值);

    • 引用对象Create a (reference object, ref object for short) that contains responsive data
    • Data manipulation in JS:xxx.value
    • Read data in the template: no need to write .value, { { xxx }}just do it directly
  • Remark:

    • The received data can be: basic type, or object type
    • 基本类型Data: Responsiveness still depends on the get and set of Object.defineProperty()
    • 对象类型data: internally "responses" to a new function in Vue3 – the reactive function

example:

If you want to define a responsive value (for example, age), you can use the following method:

  • basic type:
    insert image description here
  • Object: (actually with the help of reactive function)
    insert image description here

Full code:

<template>
  <h2>name:{
   
   {name}}</h2>
  <h2>age:{
   
   {age}}</h2>
  <h2>sayHello:<button @click="sayHello">点击在控制台打印</button></h2>
  <h2>incrementAge:<button @click="incrementAge">点击增加age</button></h2>
  <h2>info.hobby:{
   
   {info.hobby}}</h2>
  <h2>info.address:{
   
   {info.address}}</h2>
  <h2>updateInfo:<button @click="updateInfo">点击修改info</button></h2>
</template>

<script>
import {
      
      ref} from "vue"
export default {
      
      
  setup(){
      
      
    //数据
    let name = "ljy";
    let age = ref(18);
    let info = ref({
      
      
      hobby:"电影",
      address:"西安"
    });
    //方法
    function sayHello(){
      
      
      console.log(`你好啊,我是${ 
        name}`)
    }
    function incrementAge(){
      
      
      age.value++;
    }
    function updateInfo(){
      
      
      info.value.hobby = "vue";
      info.value.address = "上海";
    }
    //返回一个对象
    return {
      
      
      name,
      age,
      sayHello,
      incrementAge,
      info,
      updateInfo,
    }
  }
}
</script>

reactive function

Summarize:

  • Function: define a 对象类型responsive data ( 基本数据类型不要用它, use reffunction)
  • Syntax: const 代理对象 = reactive(源对象) Receive an object (or array), return an代理对象(Proxy对象)
  • The reactive data defined by reactive is " 深层次of"
  • Internally based on the Proxy implementation in ES6, the internal data of the source object is manipulated through the proxy object

basic use

insert image description here

Full code:

<template>
  <h2>info.hobby:{
   
   {info.hobby}}</h2>
  <h2>info.address:{
   
   {info.address}}</h2>
  <h2>updateInfo:<button @click="updateInfo">点击修改info</button></h2>
</template>

<script>
import {
      
      reactive} from "vue"
export default {
      
      
  setup(){
      
      
    //数据
    let info = reactive({
      
      
      hobby:["音乐","视频"],
      address:"西安"
    });
    //尝试修改数据
    function updateInfo(){
      
      
      //改数组
      info.hobby[0] = "学习",
      //改属性
      info.address = "上海"
    }

    return {
      
      
      info,
      updateInfo,
    }
  }
}
</script>

computed computed property

Summarize:

  • Consistent with the computed configuration function in |vue2
  • Writing:
    insert image description here

example:

insert image description here

Full code:

<template>
  <h2>firstName:<input type="text" v-model="firstName"></h2>
  <h2>lastName:<input type="text" v-model="lastName"></h2>
  <h2>fullName:{
   
   { fullName }}</h2>
  <h2>set fullName:<input type="text" v-model="setFullName"></h2>
</template>

<script setup>
import {
      
       ref, computed } from "vue";

const firstName = ref("张");
const lastName = ref("三")

//计算属性的简写:
const fullName = computed(() => {
      
      
  return firstName.value + "-" + lastName.value;
})

//计算属性的get、set
const setFullName = computed({
      
      
  get() {
      
      
    return firstName.value + "-" + lastName.value;
  },
  set(newVal) {
      
      
    const index = newVal.indexOf("-");
    firstName.value = newVal.substring(0, index);
    lastName.value = newVal.substring(index + 1);
  }
})
</script>

watch listener

Summarize:

  • Consistent with the watch configuration function in vue2.x
  • Two pits:
    • When monitoring the responsive data defined by reactive, , oldVal无法正常获取is forced to open 深度监视(deep configuration invalid)
    • When monitoring the reactive data defined by reactive 某个属性,deep配置有效
  • Regarding the question of monitoring whether the object defined by ref uses .value:
    • Monitoring basic data types does not use .value, because using .value takes out the actual value and cannot be monitored
      insert image description here
    • To monitor an object, you need to use .value, because at this time .value is a Proxy object generated by reactive; if you do not use .value at this time, you need to configure deep:true
      insert image description here

Basic use:

Monitor the reactive data defined by ref:

js:
insert image description here
html:
insert image description here
effect:
insert image description here


Monitor the reactive data defined by reactive:

js:
insert image description here
html:
insert image description here
effect:
insert image description here


Monitor certain properties of reactive data defined by reactive:

js:
insert image description here
html:
insert image description here
effect:
insert image description here

Full code:

<template>
  <h3>num1:{
   
   { num1 }}<button @click="num1++">点我num1++</button></h3>
  <h3>num2:{
   
   { num2 }}<button @click="num2++">点我num2++</button></h3>
  <h3>sum:{
   
   { num1 + num2 }}</h3>
  <hr>
  <h2>cat:</h2>
  <h3>name:{
   
   { cat.name }}<button @click="cat.name += '~'">点我修改</button></h3>
  <h3>age:{
   
   { cat.age }}<button @click="cat.age++">点我修改</button></h3>
  <h3>friend.name:{
   
   { cat.friend.name }}<button @click="cat.friend.name += '-'">点我修改</button></h3>
  <hr />
  <h2>person:</h2>
  <h3>name:{
   
   { person.name }}<button @click="person.name += '~'">点我修改</button></h3>
  <h3>pass:{
   
   { person.pass }}<button @click="person.pass += '*'">点我修改</button></h3>
  <h3>age:{
   
   { person.age }}<button @click="person.age++">点我修改</button></h3>
  <h3>car.color:{
   
   { person.car.color }}
    <!-- 切换color的颜色: -->
    <button @click="person.car.color = (person.car.color == 'red' ? 'blue' : 'red')">点我修改</button>
  </h3>
</template>

<script setup>
import {
      
       ref, reactive, watch } from "vue";

//---------------------
//监视ref定义的数据:
var num1 = ref(1);
var num2 = ref(1);
var sum = num1 + num2;
//监视一个:
watch(num1, (newVal, oldVal) => {
      
      
  console.log(`num1由${ 
        oldVal}变成了${ 
        newVal}`)
})
//监视多个:
watch([num1, num2], (newVal, oldVal) => {
      
      
  console.log("num1或num2发生了改变:", newVal, oldVal);
  sum = newVal[0] + newVal[1];
})
//--------------------------
//监视reactive定义的数据:
var cat = reactive({
      
      
  name: "tom",
  age: 2,
  friend: {
      
      
    name: "tom2"
  }
})
//oldVal无效,和newVal相同;deep配置无效;
watch(cat, (newVal, oldVal) => console.log("cat发生变化:", newVal, oldVal));

//---------------------
//监视reactive定义的数据中的某些属性,此时oldVal、deep均有效
var person = reactive({
      
      
  name: "张三",
  pass: "1234",
  age: 18,
  car: {
      
      
    color: "red"
  }
})
//监视一个
watch(() => person.name, (newVal, oldVal) => {
      
      
  console.log("person.name发生变化;", newVal, oldVal);
})
//监视多个:
watch([() => person.pass, () => person.age], (newVal, oldVal) => {
      
      
  console.log("person的pass或age发生变化;", newVal, oldVal);
})
//测试deep是否有效:(一会修改car的color,但监视color)
watch(() => person.car, (newVal) => {
      
      
  //如果修改person.car.color,该句话不会被打印!
  console.log("检测到person.car发生变化(未配置deep)");
})
watch(() => person.car, (newVal) => {
      
      
  console.log("检测到person.car发生变化(配置deep为true)");
}, {
      
      
  deep: true
})
</script>

watchEffect monitoring

Summarize:

  • The routine of watch is: not only specify the attribute of monitoring, but also specify the callback of monitoring
  • The routine of watchEffect is: no need to specify which attribute to monitor, monitor the callback用到哪个属性,就监视哪个属性
  • watchEffect and computed are a bit like:
    • computed pays attention to the calculated value (the return value of the callback), so the return value must be written
    • watchEffect focuses on the process (the function body of the callback), so there is no need to write the return value

example:

insert image description here

Full code:

<template>
  <h3>price:{
   
   { price }}<button @click="price++">点我price++</button></h3>
  <h3>count:{
   
   { count }}<button @click="count++">点我count++</button></h3>
  <h3>total:{
   
   { total }}</h3>
</template>

<script setup>
import {
      
       ref, watchEffect} from "vue";
//单价
var price = ref(10);
//数目
var count = ref(10);
//总价
var total = ref(0);

//监视:
watchEffect(() => {
      
      
  total.value = price.value * count.value;
})
</script>

hook function

insert image description here

Summarize:

  • The essence is a function that encapsulates the Composition API used in the setup function
  • Similar to mixin in vue2.x
  • Advantages of custom hooks: reuse code to make the logic in setup clearer and easier to understand

example:

useMouse.js in the hooks directory:
insert image description here
use:
insert image description here

Full code:

useMouse.js:

// mouse.js
import {
    
     ref, onMounted, onUnmounted } from 'vue'

// 按照惯例,组合式函数名以“use”开头
export function useMouse() {
    
    
  // 被组合式函数封装和管理的状态
  const x = ref(0)
  const y = ref(0)

  // 组合式函数可以随时更改其状态。
  function update(event) {
    
    
    x.value = event.pageX
    y.value = event.pageY
  }

  // 一个组合式函数也可以挂靠在所属组件的生命周期上
  // 来启动和卸载副作用
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  // 通过返回值暴露所管理的状态
  return {
    
     x, y }
}

app.view:

<template>
  <h3>Mouse position is at: {
   
   { x }}, {
   
   { y }}</h3>
</template>

<script setup>
import {
      
      useMouse} from "./hooks/useMouse"
const {
      
      x,y} = useMouse();
</script>

toRef and toRefs:

Summarize:

  • Function: Create a ref object whose value points to an attribute of another object
  • grammar:const name = toRef(person,'name;)
  • Application: To provide a property of the responsive object for external use alone
  • Extension: toRefs has the same function as toRef, but multiple ref objects can be created in batches, syntax: toRefs(person), similar to using toRef() for all attributes of a person

example:

insert image description here

Full code:

<template>
  <h3>person:{
   
   { person }}</h3>
  <hr>
  <h3>pName:{
   
   { pName }}<button @click="pName += '~'">点击修改</button></h3>
  <h3>jobName:{
   
   { jobName }}<button @click="jobName += '~'">点击修改</button></h3>
  <hr />
  <h3>name:{
   
   { name }}<button @click="name += '~'">点击修改</button></h3>
  <h3>age:{
   
   { age }}<button @click="age += '~'">点击修改</button></h3>
  <h3>job:{
   
   { job }}</h3>
</template>

<script setup>
import {
      
       reactive, toRef, toRefs } from "vue"
var person = reactive({
      
      
  name: "张三",
  age: 18,
  job: {
      
      
    name: "开发工程师",
    address: "西安"
  }
});

//使用toRef定义一个:
var pName = toRef(person, "name");
var jobName = toRef(person.job, "name");
//使用toRefs定义多个
var {
      
       name, age, job } = toRefs(person)
</script>

Other Composition APIs

shallowReactive 与 shallowRef

Summarize:

  • shallowReactive: Responsive (shallow responsive) that only deals with the outermost properties of the object
  • shallowRef: only handles basic types of responsiveness, not responsive processing of objects
  • When to use it?
    • If there is an object with relatively deep data, but the knowledge outer attribute changes when it changes, use shallowReactive
    • If an object data, the subsequent function will not modify the properties of the object, but generate a new object to replace, then use shallowRef

example:
insert image description here

Full code:

<template>
  <h3>person:{
   
   { person }}</h3>
  <h3>pName:{
   
   { pName }}<button @click="pName += '~'">点击修改</button></h3>
  <h3>jobName:{
   
   { jobName }}<button @click="jobName += '~'">点击修改</button></h3>
  <hr>
  <h3>
    cat name:{
   
   { cat.name }}
    <button @click="cat.name += '~'">点击修改</button>
    <button @click="replaceCat">点击替换</button>
  </h3>
</template>

<script setup>
import {
      
       shallowReactive, shallowRef, toRef } from "vue"
//-------------------
//使用shallowReactive,则不会监视第二层的job.name
var person = shallowReactive({
      
      
  name: "张三",
  job: {
      
      
    name: "开发工程师",
  }
});

var pName = toRef(person, "name");
var jobName = toRef(person.job, "name");

//-------------------
//使用shallowRef,传的对象不会被reactive加工;只有当cat.value改变,才能被vue监视到
var cat = shallowRef({
      
      
  name: "tom"
})
//替换一只猫
function replaceCat() {
      
      
  cat.value = {
      
      
    name: "new tom"
  }
}
</script>

readonly 与 shallowReadonly

Summarize:

  • readonly: Make a responsive data read-only (deep read-only)
  • shallowReadonly: Make a responsive data read-only (shallow read-only)
  • Application scenario: do not want the data to be modified

example:
insert image description here

Full code:

<template>
  <h3>person:{
   
   { person }}</h3>
  <h3>pName:{
   
   { pName }}<button @click="pName += '~'">点击修改</button></h3>
  <h3>jobName:{
   
   { jobName }}<button @click="jobName += '~'">点击修改</button></h3>
  <hr>
  <h3>person2:{
   
   { person2 }}</h3>
  <h3>pName2:{
   
   { pName2 }}<button @click="pName2 += '~'">点击修改</button></h3>
  <h3>jobName2:{
   
   { jobName2 }}<button @click="jobName2 += '~'">点击修改</button></h3>
  <hr>
</template>

<script setup>
import {
      
       reactive, readonly, shallowReadonly, toRef } from "vue"
//-------------------
//使用readonly,所有数据都不让改!
var person = reactive({
      
      
  name: "张三",
  job: {
      
      
    name: "开发工程师",
  }
});
person = readonly(person)
var pName = toRef(person, "name");
var jobName = toRef(person.job, "name");

//-----------------------
//使用shallowReadonly,只有第一层数据不让改,该例中job.name依然能改!
var person2 = reactive({
      
      
  name: "李四",
  job: {
      
      
    name: "教师",
  }
});
person2 = shallowReadonly(person2)
var pName2 = toRef(person2, "name");
var jobName2 = toRef(person2.job, "name");

</script>

toRaw and markRaw

Summarize:

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

example:
insert image description here

Full code:

<template>
  <h3>person: {
   
   { person }}</h3>
  <h3>person name:{
   
   { person.name }}<button @click="person.name += '~'">点击修改</button></h3>
  <hr>
  <h3>person toRaw: {
   
   { pToRaw }}</h3>
  <h3>person toRaw 的 name:{
   
   { pToRaw.name }}<button @click="updatePToRawName">点击修改</button></h3>
  <hr>
  <div v-if="person.job">
    <h3>person.job.name:{
   
   { person.job.name }}<button @click="updatePersonJobName">点击修改</button></h3>
  </div>
</template>

<script setup>
import {
      
       markRaw, reactive, toRaw } from "vue"
var person = reactive({
      
      
  name: "张三",
});

//使用toRaw,返回指定响应式对象的普通对象,此时,我们普通对象的属性值,不会造成页面的变化
var pToRaw = toRaw(person);
function updatePToRawName() {
      
      
  pToRaw.name += "-";
  console.log(`pToRaw.name 被改成了: ${ 
        pToRaw.name}`);//证明数据确实被改了,只是不是响应式的数据
}

//使用markRaw标记一个对象,使其永远不会作为响应式数据
var job = markRaw({
      
      
  name:"工程师"
});
person.job = job;//给person添加新属性,如果没使用markRaw,则添加的属性也是响应式的
function updatePersonJobName(){
      
      
  person.job.name += "-";
  console.log(`person.job.name 被改成了: ${ 
        person.job.name}`);//证明数据确实被改了,只是不是响应式的数据
}
</script>

customRef

Summarize:

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

example:
insert image description here

Full code:

<template>
  <input type="text" v-model="name">
  <h3>name:{
   
   { name }}</h3>
</template>

<script setup>
import {
      
       customRef } from "vue"

function myRef(value, delay = 200) {
      
      
  let timeout;//用于清除定时器
  return customRef((track, trigger) => {
      
      
    return {
      
      
      //当获取该值时
      get() {
      
      
        track();//追踪value的变化,当value变化时重新解析模板
        return value;
      },
      //当更新该值时,延迟更新模板
      set(newValue) {
      
      
        clearTimeout(timeout);//清除定时器
        timeout = setTimeout(() => {
      
      
          value = newValue;
          trigger();//通知vue重新解析模板
        }, delay)
      }
    }
  })
}
var name = myRef("张三");
</script>

Provide and Inject

insert image description here
Summarize:

  • Role: Realize 祖与后代communication between components
  • Routine: the parent component has an provideoption to provide data, and the descendant component has an injectoption to use the data

example:

  • provide:(App.vue中)
    insert image description here

  • inject: (in DeepChild.vue)
    insert image description here

  • Effect:
    insert image description here

Full code:

  • Ancestor: App.vue
<template>
  <div>
    我是App(祖)
    <h3>cat:{
   
   {  cat  }}</h3>
    <Footer></Footer>
  </div>

</template>

<script>
import {
      
       provide, reactive } from "vue"
import Footer from "./components/13/Footer.vue"
export default {
      
      
  components: {
      
       Footer },
  setup() {
      
      
    var cat = reactive({
      
      
      name: "tom",
      color: "black"
    });
    //向下层组件提供数据
    provide("cat", cat);
    return {
      
       cat };
  }
}
</script>

<style scoped>
div {
      
      
  border: 2px red solid;
}
</style>
  • Father: Footer.vue
<template>
    <div>
        我是Footer(父)
        <DeepChild></DeepChild>
    </div>
</template>

<script>
import DeepChild from "./DeepChild.vue"
export default {
      
      
    components: {
      
       DeepChild }
}
</script>

<style scoped>
div {
      
      
    border: 2px red solid;
    margin: 10px;
}
</style>
  • Son: DeepChild.vue
<template>
    <div>
        我是DeepChild(孙)
        <h3>cat:{
   
   { cat }}</h3>
    </div>
</template>
  
<script>
import {
      
       inject } from '@vue/runtime-core'
export default {
      
      
    setup() {
      
      
        //接收上层组件传过来的值
        var cat = inject("cat");
        return {
      
       cat };
    }
}
</script>
  
<style scoped>
div {
      
      
    border: 2px red solid;
    margin: 10px;
}
</style>

isXxx

Summarize:

  • isRef: Checks if a value is a refobject
  • isReactive: Checks if an object was reactivecreated by a reactive proxy
  • isReadonly: Checks if an object was readonlycreated by a read-only proxy
  • isProxy: Checks if an object is a proxy created by the reactiveor methodreadonly

example:
insert image description here

Full code:

<template>
  <pre>
      <code>
        var num = ref(0);
        var b1 = isRef(num);
        b1:{
   
   { b1 }}

        var person = reactive({name:"张三"});
        var b2 = isReactive(person);
        b2:{
   
   { b2 }}

        var p = readonly(person);
        var b3 = isReadonly(p);
        b3:{
   
   { b3 }}

        var b4 = isProxy(person);
        var b5 = isProxy(p);
        b4:{
   
   { b4 }}
        b5:{
   
   { b5 }}
      </code>
  </pre>

</template>

<script setup>
import {
      
       isProxy, isReactive, isReadonly, isRef, reactive, readonly, ref } from 'vue';

var num = ref(0);
var b1 = isRef(num);

var person = reactive({
      
       name: "张三" });
var b2 = isReactive(person);

var p = readonly(person);
var b3 = isReadonly(p);

var b4 = isProxy(person);
var b5 = isProxy(p);
</script>

new components

Fragment

Summarize:

  • 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

Teleport

Official website: https://cn.vuejs.org/guide/built-ins/teleport.html
insert image description here

Summarize:

  • Teleport组件html结构is a technology that can move our body to a specified location
  • toThe value of can be a CSS selector string or a DOM element object. For example: to="body"the function is to tell Vue "pass the template fragment to bodythe tag".

example:

  • MyModal.vueUse in to Teleportmove the component into html's body:
    insert image description here

Full code:

  • app.vue
<template>
  <div class="outer">
    <h3>Tooltips with Vue 3 Teleport</h3>
    <div>
      <MyModal />
    </div>
  </div>
</template>

<script setup>
import MyModal from './components/15/MyModal.vue';
</script>
  • MyModal.vue
<template>
    <button @click="open = true">Open Modal</button>

    <Teleport to="body">
        <div v-if="open" class="modal">
            <p>Hello from the modal!</p>
            <button @click="open = false">Close</button>
        </div>
    </Teleport>
</template>
  
<script setup>
import {
      
       ref } from 'vue'

const open = ref(false)
</script>

<style scoped>
.modal {
      
      
    position: fixed;
    z-index: 999;
    top: 20%;
    left: 50%;
    width: 300px;
    margin-left: -150px;
}
</style>

Suspense

Summarize:

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

  • Steps for usage:

    1. Import components asynchronously
      insert image description here

    2. Use Suspensethe package component, and configure default(which component to display) and fallback(if the component to be displayed is not loaded, the displayed content)
      insert image description here

example:

  • Use Suspensetags:
    insert image description here
  • Adjust the network to slow 3G, when the subcomponent Childis not loaded, 正在加载...the words will be displayed

insert image description here

  • ChildAfter a period of events, the content in the component is displayed :
    insert image description here
    this is Childthe content in the child component:
    insert image description here

Full code:

  • app.vue
<template>
  <div class="outer">
    <h3>我是父组件!!!</h3>
    <Suspense>
      <!-- 主要内容 -->
      <template v-slot:default>
        <Child></Child>
      </template>

      <!-- 加载中状态 -->
      <template v-slot:fallback>
        正在加载...
      </template>
    </Suspense>
  </div>
</template>

<script setup>
import {
      
       defineAsyncComponent } from "@vue/runtime-core"
var Child = defineAsyncComponent(() => import("./components/16/Child.vue"))
</script>
  • app.vue
<template>
    <h3>
        我是子组件!!!
    </h3>
</template>

Other changes for vue2 -> vu3:

Global API transfer:

insert image description here

other changes

insert image description here
insert image description here

おすすめ

転載: blog.csdn.net/m0_55155505/article/details/127657968