【vue3笔记】快速上手vue3秘籍

创建vue3项目

1. 使用vue-cli创建项目

安装/升级:npm install -g @vue/cli
查看vue-cli版本(保证版本高于4.5.0以上):vue --version
创建项目:vue create 项目名

2. 使用vite创建项目

创建项目:npm init vite-app 项目名

初见 setup

1. setup

setup函数是所有组合API的入口,只在初始时执行一次(在beforeCreate生命周期回调之前)。
函数返回的是对象,对象中的属性和方法均可在模板中直接使用。

// App.vue
<template>
  <div class="">啦啦啦~</div>
  <h1>{
   
   { num }}</h1>
</template>

<script lang="ts">
// defineComponent函数:用于定义组件,内部可以传入一个配置对象
import { defineComponent } from 'vue';


// 暴露出去一个定义好的组件
export default defineComponent({
  // 当前组件名为App
  name: 'App',
  setup() {
    const num = 66
    return {
      num
    }
  }
});
</script>

2. ref

  • 作用:定义一个数据的响应式
  • 语法: const 参数名 = ref(参数初始值)
    • 创建一个包含响应式数据的引用(reference)对象
    • js中操作数据: 参数名.value
    • html模板中操作数据: 参数名
  • 一般用来定义一个基本类型的响应式数据
<template>
  <h2>setup和ref的基本使用</h2>
  <br />
  <h4>{
   
   { count }}</h4>
  <button @click="updataCount">更新数据</button>
</template>

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

export default defineComponent({
  name: 'App',
  setup() {
    // 变量
    // ref是一个函数,作用:定义一个响应式的数据 ,返回的是一个ref对象
    const count = ref(0) //此时count是一个对象

    // 方法
    function updataCount() {
      console.log('~~')
      count.value++;
    }
    // 返回的是一个对象
    return {
      count,
      updataCount
    }

  }
});
</script>
ref — 获取元素
<template>
  <h2>ref的另一个用法:获取元素</h2>
  <br />
  <input type="text" ref="inputRef">
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';

export default defineComponent({
  name: 'App',
  // 需求:当页面加载完毕后,页面中的文本框可以直接获取焦点(自动获取焦点)
  setup() {
    // 默认是空的,当页面加载完毕后(组件已存在),获取文本框
    const inputRef = ref<HTMLElement | null>(null)

    onMounted(() => {
      inputRef.value && inputRef.value.focus() //自动获取焦点
    })
    return {
      inputRef,
    }
  }
});
</script>

3. reactive

  • 作用:定义多个数据的响应式
  • 语法: const 参数名 = reactive(obj)
    • 接收一个普通对象然后返回该普通对象的响应式代理对象
  • 响应式转换是“深沉的”:会影响对象内部所有嵌套的属性
  • 内部基于es6的Proxy实现,通过代理对象操作源对象内部数据都是响应式的

总结:
操作代理对象,目标对象中的数据也会相应变化;
操作代理对象,界面也会重新渲染。

<template>
  <h2>reactive的基本使用</h2>
  <br />
  <h4>{
   
   { obj.name }}</h4>
  <h4>{
   
   { obj.age }}</h4>
  <h4>{
   
   { obj.cars }}</h4>
  <button @click="updateUser">更新数据</button>
</template>

<script lang="ts">
import { defineComponent, reactive } from 'vue';
export default defineComponent({
  name: 'App',
  setup() {
  // 返回的是一个Proxy的代理对象,被代理的对象就是reactive中传入的对象
    const obj = reactive({
      name: 'eiton',
      age: 12,
      cars: ['奔驰', '宝马']
    })
    const updateUser = () => {
      obj.age++
    }
    return {
      obj, updateUser
    }
  }
});
</script>

比较vue2和vue3的响应式(重要)

响应式:在改变数据的时候,视图也会跟着更新。当修改 Vue 实例中的数据时,视图就会重新渲染,出现新的内容。

vue2的响应式

vue2的响应式是利用Object.defineProperty结合 gettersetter 方法实现的监听和代理,进而来实现数据响应式。

 //源数据
        let person = {
            name: '噸噸',
            age: 21
        }
        //vue2中响应式
         let p = {};
         给p加了个name属性,值是undefined
         Object.defineProperty(p, 'name', {}) 

         Object.defineProperty(p, 'name', {
            configurable: true,
             //只要读取name属性就会触发get方法
             get() {
                 console.log('我得到了');
                 return person.name
             },
             //只要修改name属性就能触发set方法
             set(value) {
                 console.log('有人修改了name属性');
                 person.name = value
             }
         })
        //这种用Object.defineProperty添加新的属性和删除已有的属性就是不响应式的了
  

vue3的响应式

vue3的响应式是通过es6的 Proxy结合Reflect 来实现的。

//vue3响应式
        // window.Proxy window内置的构造函数,不用下载不用安装
        // let p=new Proxy(代理的源对象,{})
        // let p = new Proxy(person, {}) //把p映射到person对象上面,做到响应。console.log(p)可以看到效果
        let p = new Proxy(person, {
            get(target, propName) {
                console.log('读取了p的属性');
                return target[propName]
            },
            set(target, propName, value) {
                console.log('修改或者添加了p的属性');
                return target[propName] = value;
            },
            deleteProperty(target, propName) {
                console.log('执行了删除操作');
                return delete target[propName];
            }
        })

setup细节

setup细节:

  • 执行时机:
    • setup执行时,组件尚未创建,即组件实例对象this不能使用。
    • 所有的composition Api相关回调函数亦不能使用。
  • 返回值:
    • 一般返回一个对象:为模板提供数据,即模板可直接使用对象中的属性/方法
    • 返回对象中的属性与data函数返回的对象的属性合并成为组件对象的属性
    • 返回对象中的方法与methods中的方法合并成为组件对象的方法
    • 若有重名,setup优先 (在vue3中尽量不要混用setup和data / setup和methods)
  • 参数:
    • props参数,是一个对象,里面有父级向子级组件传递的数据,并在子级组件中使用props接收到的所有属性
      • 包含props配置声明且传入的所有属性的对象
    • context参数,是一个对象,对象里包含attre对象(获取当前组件标签上的所有的属性)、emit方法(分发事件的),slots对象(插槽)
      • 包含没有在props配置中声明的属性对象,相当于this.$attrs

ref 和 reactive 细节

  • ref 和 reactive 是vue3中Composition API中最重要的响应式API
  • ref是用来处理ts基本类型的数据,reactive是用来处理对象的数据
  • ref 内部原理:通过对value属性进行setter和getter操作,实现数据劫持
  • reactive 内部原理:利用Proxy实现数据劫持,通过reflect操作内部数据

计算属性 和 监视

<template>
  <h2>计算属性和监视</h2>
  <br />
  <fieldset>
    <legend>姓名操作</legend>
    姓氏: <input type="text" placeholder="请输入姓氏" v-model="user.firstName" />
    <br /> <br />
    名字: <input type="text" placeholder="请输入名字" v-model="user.lastName" />
  </fieldset>
  <fieldset>
    <legend>计算属性和监视 演示:</legend>
    姓名:{
   
   { fullName }}<br />
    姓名:<input type="text" placeholder="显示姓名" v-model="fullName2" /><br />
    姓名:<input type="text" placeholder="显示姓名" v-model="fullName3" /><br />
  </fieldset>

</template>

<script lang="ts">
import { computed, defineComponent, reactive, ref, watch, watchEffect } from 'vue';
export default defineComponent({
  name: 'App',
  setup() {
    const user = reactive({
      firstName: '西方',
      lastName: '常败',
    })
    // 计算属性
    // 返回的是一个类型的对象
    const fullName = computed(() => {
      return user.firstName + '_' + user.lastName
    })
    const fullName2 = computed({
      get() {
        return user.firstName + '_' + user.lastName
      },
      set(val: string) {
        console.log('----', val)
        user.firstName = val.split('_')[0]
        user.lastName = val.split('_')[1]
      }

    })
    // 监视 --- 监视指定数据
    const fullName3 = ref('')
    // watch(user, (val) => {
    //   console.log('监视', val)
    //   fullName3.value = val.firstName + '_' + val.lastName
    // }, { immediate: true })
    // immediate: true 默认开始执行一次 ,deep 深度监视

    // 监视,不需要配置immediate,本身默认就会进行监视,(默认执行一次)
    // watchEffect(() => {
    //   fullName3.value = user.firstName + '_' + user.lastName
    // })

    // 监视fullName3的数据,改变firstName和lastName
    watchEffect(() => {
      const names = fullName3.value.split('_')
      user.firstName = names[0] || ''
      user.lastName = names[1] || ''
    })

    return {
      user,
      fullName,
      fullName2,
      fullName3
    }
  }
});
</script>
   // watch可以监视多个数据
    // watch([user.firstName,user.lastName,fullName3],()=>{
    //   // 这里的代码没有被执行 ---原因---  fullName3是响应式的数据 但user.firstName和user.lastName不是响应式数据
    // })

    // 使用watch监视非响应式的数据,需要回调
      watch([()=>user.firstName,()=>user.lastName,fullName3],()=>{
      console.log('~~~')
    })

watchEffect和watch的区别

  • 属性监听
    watch:手动添加
    watchEffect:自动监听
  • 初始化执行
    watchEffect:页面初始时会执行一次

生命周期

在这里插入图片描述


<script lang="ts">
import { defineComponent, onBeforeMount, onBeforeUpdate, onUpdated, onMounted, onBeforeUnmount, onUnmounted, ref } from 'vue';
export default defineComponent({
  name: 'child',
  // vue 2.x 的生命周期
  beforeCreate() {
    console.log('vue 2.x  ---beforeCreate ')
  },
  created() {
    console.log('vue 2.x  ---created ')
  },
  beforeMount() {
    console.log('vue 2.x  ---beforeMount ')
  },
  mounted() {
    console.log('vue 2.x  ---mounted ')
  },
  beforeUpdate() {
    console.log('vue 2.x  ---beforeUpdate ')
  },
  updated() {
    console.log('vue 2.x  ---updated ')
  },
  // vue 2.x 中的beforeDestroy和destroyed 在 vue 3.x中已更名为beforeUnmount和unmounted,故不能再使用
  beforeUnmount() {
    console.log('vue 2.x  ---beforeDestroy / beforeUnmount ')
  },
  unmounted() {
    console.log('vue 2.x  ---destroyed / unmounted')
  },

  // vue 3.x 组合api
  setup() {
    console.log('vue 3.x  ---setup')
    const msg = ref('vue 3.x  ---setup')
    const update = (() => {
      msg.value += '~'
    })


    onBeforeMount(() => {
      console.log('vue 3.x  ---onBeforeMount ')
    })
    onMounted(() => {
      console.log('vue 3.x  ---onMounted')
    })
    onBeforeUpdate(() => {

      console.log('vue 3.x  ---onBeforeUpdate')

    })
    onUpdated(() => {
      console.log('vue 3.x  ---onUpdated')
    })
    onBeforeUnmount(() => {
      console.log('vue 3.x  ---onBeforeUnmount')
    })
    onUnmounted(() => {
      console.log('vue 3.x  ---onUnmounted')
    })

    return {
      msg,
      update,
    }
  },

});
</script>

自定义hook函数

Vue3 的 hook函数 相当于 vue2 的 mixin;
hook函数 可以帮助我们提高代码的复用性, 让我们能在不同的组件中都利用 hooks 函数;

// src -> hooks -> useMousePosition.ts
import { onBeforeUnmount, onMounted, ref } from 'vue';
export default function () {

  const x = ref(-1)
  const y = ref(-1)

  // 点击事件的回调函数
  const clickHandler = (event: MouseEvent) => {
    x.value = event.pageX
    y.value = event.pageY
  }

  onMounted(() => {
    window.addEventListener('click', clickHandler)
  })
  onBeforeUnmount(() => {
    window.removeEventListener('click', clickHandler)
  })

  return {
    x, y
  }
}

// src ->App.vue
<template>
  <h2>~~自定义hook函数~~</h2>
  <h4>x:{
   
   {x}},y:{
   
   {y}}</h4>
  <h4 v-if="loading">loading...</h4>
  <h4 v-else-if="errorMsg">错误信息:{
   
   {errorMsg}}</h4>
  <!-- 对象数据 -->
  <!-- <ul v-else>
    <li>id:{
   
   { data.id}}</li>
    <li>address:{
   
   {data.address}}</li>
    <li>distance:{
   
   {data.distance}}</li>
  </ul> -->

  <!-- 数组数据 -->
  <div v-else>
    <ul v-for="(item,ind) in data" :key="ind">
      <li>id:{
   
   { item.id}}</li>
      <li>title:{
   
   {item.title}}</li>
      <li>price:{
   
   {item.price}}</li>
    </ul>
  </div>
</template>

<script lang="ts">
import { defineComponent, watch } from 'vue';
import useMousePosition from './hooks/useMousePosition';
import uesRequest from './hooks/uesRequest';
// 定义接口,约束对象的类型
interface AddressData {
  id: number;
  address: string;
  distance: string;
}
interface ProjectData {
  id: string;
  title: string;
  price: number;
}
export default defineComponent({
  name: 'App',
  // 注册组件

  setup() {
    const { x, y } = useMousePosition()
    // const { loading, data, errorMsg } = uesRequest<AddressData>('/data/address.json') //获取对象数据
    const { loading, data, errorMsg } = uesRequest<ProjectData>('/data/products.json') //获取数组对象数据

    watch(data, () => {
      if (data.value) {
        console.log(data.value.length)
      }
    })

    return {
      x, y, loading, data, errorMsg
    }
  },

});
</script>

toRefs的使用

<template>
  <h2>~~toRefs的使用~~</h2>
  <!-- <h4>name:{
   
   {state.name}}</h4>
  <h4>age:{
   
   {state.age}}</h4> -->

  <h4>name:{
   
   {name}}</h4>
  <h4>age:{
   
   {age}}</h4>
  <br />
  <h4>name2:{
   
   {name2}}</h4>
  <h4>age2:{
   
   {age2}}</h4>
</template>

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

function useFeatureX() {
  const state = reactive({
    name2: '制度化',
    age2: 16
  })
  return {
    ...toRefs(state)
  }
}

export default defineComponent({
  name: 'App',

  setup() {
    const state = reactive({
      name: '傲娇地上',
      age: 68
    })

    // toRefs可以把 一个响应式对象 变成 普通对象,该普通对象的每一个property都是一个ref

    const state2 = toRefs(state)

    // 定时器
    setInterval(() => {
      // state.name += '~'
      state2.name.value += "?"
    }, 5000)

    const { name2, age2 } = useFeatureX()

    return {
      // state , //响应式
      // ...state, //非响应式
      ...state2, name2, age2
    }
  },

});
</script>

shallowReactive和shallowRef

<template>
  <h2>shallowReactive和shallowRef</h2>
  <br />
  <h4>{
   
   {m1}}</h4>
  <h4>{
   
   {m2}}</h4>
  <h4>{
   
   {m3}}</h4>
  <h4>{
   
   {m4}}</h4>
  <button @click="update">更改数据</button>
</template>

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

export default defineComponent({
  name: 'App',

  setup() {
    // 深度劫持(深监视)--- 深度响应式
    const m1 = reactive({
      name: '多返回',
      age: 16,
      car: {
        brand: '奔驰',
        color: 'red'
      }
    })
    // 浅劫持(浅监视)--- 浅响应式
    const m2 = shallowReactive({
      name: '多返回',
      age: 16,
      car: {
        brand: '奔驰',
        color: 'red'
      }

    })
    // 深度劫持(深监视)--- 深度响应式 --- 做了reactive的处理
    const m3 = ref({
      name: '多返回',
      age: 16,
      car: {
        brand: '奔驰',
        color: 'red'
      }
    })
    // 浅劫持(浅监视)--- 浅响应式 --- 只处理value的响应式,不进行对象的reactive处理
    const m4 = shallowRef({
      name: '多返回',
      age: 16,
      car: {
        brand: '奔驰',
        color: 'red'
      }
    })

    const update = () => {
      // 更改数据
      // m1.name += '*'
      // m1.car.brand += '*'

      // m2.name += '*'
      // m2.car.brand += '*' // 单独这个,无响应

      // m3.value.name += '*'
      // m3.value.car.brand += '*'

      //m4.value.name += '*' // 无响应
      // m4.value.car.brand += '*' // 无响应
    }


    return {
      m1, m2, m3, m4, update
    }
  }
});
</script>

readonly和shallowReadonly

<template>
  <h2>readonly和shallowReadonly</h2>
  <br />
  <h4>state:{
   
   {state2}}</h4>
  <button v-on:click="update">更新数据</button>
</template>

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

export default defineComponent({
  name: 'App',

  setup() {

    const state = reactive({
      name: '多返回',
      age: 16,
      car: {
        brand: '奔驰',
        color: 'red'
      }
    })

    // const state2 = readonly(state) // 只读,深度只读
    const state2 = shallowReadonly(state) // 只读,浅只读

    const update = () => {
      // state2.name += '*' // 报错 只读不能更改 readonly处理后
      // state2.car.brand += '*' // 报错 只读不能更改 readonly处理后

      // state2.name += '*' // 报错 只读不能更改 shallowReadonly处理后
      state2.car.brand += '*' // 不报错,可修改

    }
    return {
      state2,
      update
    }
  }
});
</script>

toRaw和markRaw

<template>
  <h2>toRaw和markRaw</h2>
  <br />
  <h4>state:{
   
   {state}}</h4>
  <hr />
  <button v-on:click="testToRaw">测试toRaw</button>
  <button v-on:click="testMarkRaw">测试markRaw</button>
</template>

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

interface UserInfo {
  name: string;
  age: number;
  car: object;
  like?: string[];
}

export default defineComponent({
  name: 'App',

  setup() {
    const state = reactive<UserInfo>({
      name: '多返回',
      age: 16,
      car: {
        brand: '奔驰',
        color: 'red'
      }
    })

    const testToRaw = () => {
      // 把 代理对象 变为 普通对象 (数据变化,页面不变化)
      const user = toRaw(state)
      user.name += '*'
      console.log(user)
    }
    const testMarkRaw = () => {
      // state.like = ['吃', '喝']
      // state.like[0] += '-'

      // markRaw标记后的对象数据,从此以后不能再成为代理对象
      const likes = ['吃', '喝']
      state.like = markRaw(likes)
      setInterval(() => {
        if (state.like) {
          state.like[0] += '-'

          console.log('setInterval')
        }
      }, 2000)
    }

    return {
      state, testToRaw, testMarkRaw
    }
  }
});
</script>

<style>
button {
  margin: 0 10px;
}
</style>

toRef的使用及特点

<template>
  <h2>toRef的使用及特点:</h2>
  <br />
  <h4>state:{
   
   {state}}</h4>
  <h4>money:{
   
   {money}}</h4>
  <h4>age:{
   
   {age}}</h4>
  <hr />
  <button v-on:click="update">更新数据</button>
  <hr />
  <Child :age="age"></Child>
</template>

<script lang="ts">
import { defineComponent, reactive, ref, toRef } from 'vue';
import Child from './components/child.vue'

export default defineComponent({
  name: 'App',
  components: {
    Child
  },
  setup() {
    const state = reactive({
      name: '大家',
      age: 12,
      money: 100
    })
    // 把响应式数据state对象中的‘age’属性数据变成ref对象
    const age = toRef(state, 'age') // 数据变化会影响state.age
    // 吧响应式数据state对象中的‘money’属性用ref进行包装,变成一个ref对象
    const money = ref(state.money) // 数据变化不会影响statemoney
    const update = () => {
      state.age += 1
      age.value += 2
      money.value += 100
    }
    return {
      state,
      money,
      age,
      update,
    }
  }
});
</script>
// 子组件 /components/child.vue
<template>
  <h2>child子组件~</h2>
  <h4>age:{
   
   {age}}</h4>
  <h4>length:{
   
   {length}}</h4>
</template>

<script lang="ts">
import { computed, defineComponent, Ref, toRef, } from 'vue';
function useGetLength(age: Ref) {
  return computed(() => {
    return age.value.toString().length
  })
}
export default defineComponent({
  name: 'Child',
  props: {
    age: {
      type: Number,
      required: true
    }
  },
  setup(props) {
    const length = useGetLength(toRef(props, 'age'))
    return {
      length
    }
  }

});
</script>

customRef(不常用)

customRef — 自定义ref

<template>
  <h2>CustomRef的使用</h2>
  <input type="text" v-model="inputValue">
  <h4>inputValue: {
   
   {inputValue}}</h4>
</template>

<script lang="ts">
import { track, trigger } from '@vue/reactivity';
import { customRef, defineComponent } from 'vue';
// 自定义hook 防抖动的函数
function useDebouncedRef<T>(value: T, delay = 200) {
  // 准备一个存储定时器的id变量
  let timer
  return customRef((track, trigger) => {
    return {
      // 返回数据
      get() {
        // 告诉vue追踪数据
        track()
        return value;
      },
      // 设置数据
      set(val: T) {
        // 清理定时器
        clearTimeout(timer)
        // 启动定时器
        timer = setTimeout(() => {
          value = val
          // 通知vue 更新数据
          trigger()
        }, delay)
      },
    }
  })
}

export default defineComponent({
  name: 'App',

  setup() {
    const inputValue = useDebouncedRef('abc', 500)
    return {
      inputValue
    }
  }
});
</script>

provide 和 inject

provide 和 inject 主要用于跨层级组件间的通信

// 爷爷组件
<template>
  <h2>provide 和 inject : 提供依赖注入,实现跨层级组件(祖孙)间通信</h2>
  <h4>当前颜色: {
   
   {color}}</h4>
  <br>
  <button @click="color='red'">红色</button><button @click="color='yellow'">黄色</button><button
    @click="color='blue'">蓝色</button>
  <hr>
  <child></child>
</template>

<script lang="ts">
import { defineComponent, provide, ref } from 'vue';
import child from './components/child.vue';
export default defineComponent({
  name: 'App',
  components: {
    child
  },
  setup() {
    const color = ref('red')
    // 给孙子组件传数据
    provide('color', color)

    return {
      color
    }
  }
});
</script>

<style>
button {
  margin: 0 10px;
}
</style>

//  子组件
<template>
  <h2>child子组件~</h2>
  <hr>
  <grandson />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import grandson from './grandSon.vue';
export default defineComponent({
  name: 'Child',
  components: {
    grandson
  },
  setup() {
    return {
    }
  }

});
</script>

//  孙子组件
<template>
  <h2>grandson孙子组件~</h2>
  <h4>接收爷爷组件传过来的值---{
   
   {color}}</h4>
</template>

<script lang="ts">
import { defineComponent, inject, } from 'vue';
export default defineComponent({
  name: 'GrandSon',

  setup() {
    // 接收爷爷组件传过来的值
    const color = inject('color')

    return {
      color
    }
  }

});
</script>

响应式数据的判断

  • isRef,是否是由ref定义的响应式数据
  • isReactive,是否是由reactive定义的响应式数据
  • isReadonly,是否是由readonly定义的数据
  • isProxy,是否是由reactive或readonly定义的数据

VUE3新内置组件

Fragment(片段)组件

  • vue3时,组件的模板结构中出现多个标签时,可以不用根标签。这是因为vue3会自动将多个标签用fragment包裹。
  • 好处:减少标签层级,减少内存占用.

Teleport(瞬移)组件

vue新增的内置组件Teleport,Teleport可以将特定内容转移至指定位置;

Teleport的两个prop参数:

  • to - string。需要 prop,必须是有效的查询选择器或HTMLElement (如果在浏览器环境中使用)。指定将在其中移动 teleport标签 内容的目标元素。
  • disabled - boolean。此可选属性可用于禁用 teleport标签的功能,这意味着其插槽内容将不会移动到任何位置,而是在您在周围父组件中指定了 teleport标签 的位置渲染。
  <h2>Teleprot(瞬移)组件</h2>
  <p>vue新增的内置组件Teleport,Teleport可以将特定内容转移至指定位置;</p>
  <p>Teleport的两个prop参数</p>
  <p>·to - string。需要 prop,必须是有效的查询选择器或 HTMLElement (如果在浏览器环境中使用)。指定将在其中移动 teleport标签 内容的目标元素</p>
  <p>·disabled - boolean。此可选属性可用于禁用 teleport标签 的功能,这意味着其插槽内容将不会移动到任何位置,而是在您在周围父组件中指定了 teleport标签 的位置渲染。</p>

  <div id="teleprot_id"></div>
  <div class="teleprot_class"></div>
  <Teleport to="body">
    <h4>1.我是Teleport里面的东西~</h4>
  </Teleport>
  <Teleport to="#teleprot_id">
    <h4>2.我是Teleport里面的东西~ id</h4>
  </Teleport>
  <Teleport to=".teleprot_class">
    <h4>3.我是Teleport里面的东西~ class</h4>
  </Teleport>

在这里插入图片描述

Suspense(不确定)组件

等待异步组件时渲染一些额外内容,让应用有更好的用户体验。

<template>
  <h2>Suspense(不确定)组件</h2>
 // 3. 使用Suspense包裹组件,并配置好default 与 fallback
  <Suspense>
    <template #default>
      <AsyncComponent></AsyncComponent>
    </template>
    <template #fallback>
      <!-- loading内容 -->
      <h4>loading~~~</h4>
    </template>
  </Suspense>


</template>

<script lang="ts">
//1.引入组件
import { defineAsyncComponent, defineComponent } from 'vue';
// import AsyncComponent from './components/AsyncComponent.vue'  //静态引入
// vue3中的动态引入
const AsyncComponent = defineAsyncComponent(() => import('./components/AsyncComponent.vue'))
export default defineComponent({
  name: 'App',
  // 2.实例化组件
  components: {
    AsyncComponent
  },

  setup() {
    return {
    }
  }

});
</script>

猜你喜欢

转载自blog.csdn.net/zxsy19966/article/details/126617005