vue3 知识点

193 阅读4分钟

1. vue3使用的是Composition API(组合式api)

  • 作用让相关功能的代码有序的组织在一起

2. 使用setup语法糖(相当于created生命周期)

  • 所有的组合 API 函数都在此使用, 只在初始化时执行一次
  • 函数如果返回对象, 对象中的属性或方法在模板中可以直接使用
    <script setup>
    #定义好直接可以在模板里面使用 非常的nice!
    const msg = '小樱'
    const sayHi = () => {
        return 'hi'
    }
    </script>
    

3. 定义响应式数据使用的是ref和reactive

  • ref只能对基本数据类型的数据进行定义
    • 使用之前必须先从vue中引入

    • 定义数据之后,模板里面直接使用值

    • 如果要对数据进行修改,则要使用.value 属性来修改

      <script setup>
      #引入ref 函数
      import { ref } from 'vue'
          
      #创建响应式数据
      const 变量名 = ref(初始值)
      ​
      #修改响应式数据   注意别修改原数据
      const change = ()=> {
        变量名.value = 修改之后的值
      }
      </script>
      
  • reactive对引用数据类型的数据进行定义
    • 同样使用之前必须先从vue中引入

    • 作用: 定义多个数据的响应式

    • reactive(obj):接收一个普通对象然后返回该普通对象的响应式代理器对象

    • 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据都是响应式的

      <template>
          {{state.属性1}}
          {{state.属性2}}
      </template>
      
      <script setup>
      #引入reactive 函数
      import { reactive } from 'vue'
      
      #创建响应式数据
      const state = reactive({
          属性1:值1,
          属性2:值2
      })
      </script>
      

4. v-if和v-for的优先级

  • 在vue2中v-for的优先级要高于v-if,在循环的每一次都会去做一次判断,这样极大的浪费了性能
  • 在vue3中v-if优先级要高于v-for,会先进行判断满足条件再在进行循环

5. toRef和toRefs

  • toRef:可以用来为源响应式对象上的某个 property 新创建一个 ref 。然后这个 ref 可以被传递,它会保持对其源 property 的响应式连接。

  • toRefs:将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref 。

  • 当从组合式函数返回响应式对象时,toRefs 非常有用,这样消费组件就可以在不丢失响应式的情况下对返回的对象进行解构/展开。

    • 语法:

      <template>
          {{name}}
          {{age}}
          <button @click='change'>点击我</button>
      </template>
      
      <script setup>
      #引入reactive toRefs 函数
      import { reactive, toRefs } from 'vue'
      
      #创建响应式数据
      const state = reactive({
          name: '小明',
          age: 11,
      })
      
      #数据解构出来,创建属性的ref,都通过value来获取值
      const { name, age } = toRefs(state)
      const change = () => {
          name.value = '小红'
          age.value = 12
      }
      </script>
      

6.计算属性

  • computed函数:

    • 与computed配置功能一致,但是分为两种情况
    • 第一种:只有getter
    • 第二种:有getter和setter
  • 示例

    #getter
    <template>
        <h1>计算属性 computed</h1>
        <div>{{ msg }}</div>
        <div>取反数据:{{ reverseMsg }}</div>
    </template>
    <script setup>
    import { computed, ref } from 'vue';
    const msg = ref('我是一个数据')
    
    // 写法1 只有getter 得到计算属性的结果数据
    const reverseMsg = computed(() => [...msg.value].reverse().join(''))
    </script>
    
    #getter & setter
    <template>
        <h1>计算属性 computed</h1>
        <div>{{ msg }}</div>
        <div>取反数据:{{ reverseMsg }}</div>
        <button @click="changeRes">修改计算属性</button>
    </template>
    <script setup>
    import { computed, ref } from 'vue';
    const msg = ref('我是一个数据')
    
    // 写法2 getter函数 & setter函数  可以修改计算属性的值,必须用到setter
    const reverseMsg = computed({
        //取值 触发 getter函数
        get() {
            return [...msg.value].reverse().join('')
        },
        #改值触发 setter函数
        set(value) {
            msg.value = value
        }
    })
    
    const changeRes = () => {
        #修改计算属性 触发计算属性的setter函数
        reverseMsg.value = '我是计算属性的setter'
    }
    </script>
    

7.侦听器 watch

  • watch函数

    • 与watch配置功能一致
    • 监视指定的一个或多个响应式数据, 一旦数据变化, 就自动执行监视回调
    • 默认初始时不执行回调, 但可以通过配置immediate为true, 来指定初始时立即执行第一次
    • 通过配置deep为true, 来指定深度监视
  • watchEffect函数

    • 不用直接指定要监视的数据, 回调函数中使用的哪些响应式数据就监视哪些响应式数据
    • 默认初始时就会执行第一次, 从而可以收集需要监视的数据
    • 监视数据发生变化时回调
  • 语法

    #简单用法 
    watch(ref 或者reactive 数据,(newV,oldV)=>{
         //观察数据变化执行 里面代码
     },{
        immediate:true, //立即执行
        deep:true //深度监听
     })
     
    #观察多个数据变化
    watch([()=>state.属性1,()=>state.属性2],()=>{
            
    })
     
    #watchEffect 会立即执行里面代码  监视所有回调中使用的数据
    watchEffect(()=>{
         
    })
    

8. 生命周期

因为 setup 是围绕 beforeCreatecreated 生命周期钩子运行的,在这两个钩子中编写的任何代码都应该直接在 setup 函数中编写。

在 setup 内部调用生命周期钩子:

<script setup >
import { onMounted, onActivated, onUnmounted, onUpdated, onDeactivated } from 'vue';
 onMounted(() => {
     console.log("组件挂载")
 })
 onUnmounted(() => {
    console.log("组件卸载")
 })
 onUpdated(() => {
    console.log("组件更新")
 })
 onActivated(() => {
    console.log("keepAlive 组件 激活")
 })
 onDeactivated(() => {
     console.log("keepAlive 组件 非激活")
 })
</script>

9. defineProps 和 defineEmits 父子传参

为了声明 propsemits 选项且具备完整的类型推断,可以使用 definePropsdefineEmits API,它们在 <script setup> 中都是自动可用的。

defineProps 接收与 props 选项相同的值,defineEmits 也接收 emits 选项相同的值。

父传子

#父组件
<template>
  <子组件 自定义属性1='静态' :自定义属性2='动态值'></子组件>
</template>

#子组件
<template>
  {{自定义属性1}}
  {{自定义属性1}}
</template>
<script setup>
  import { toRefs } from 'vue';
  #通过defineProps 接受的数据都在左侧自定义变量 props上[props变量是响应式的]
  #props接收的数据可以直接渲染
  const props = defineProps({
        自定义属性1:{
          type: 类型,
          default: () => 默认值
        },
        自定义属性2:{
          type: 类型,
          default: () => 默认值
        }
  })
</script>

子传父

#子组件
<script setup>
#定义子组件的自定义事件 -- 注册自定义事件
const emits = defineEmits(['自定义事件1','自定义事件2'])
#触发子传父事件
emits('自定义事件1', 数据)
</script>

#父组件
<template>
    <子组件 @自定义事件1="处理函数"></子组件>
</template>

<script setup>
#子组件 触发自定义事件1 父组件的处理函数 收到子传父的数据
const 处理函数 = (data) => {
    console.log(data)
}
</script>

10. 自定义hooks函数

  • 使用Vue3的组合API封装的可复用的功能函数
  • 用来取代vue2 mixin ,目的也是抽离公共js逻辑
  • 命名 useXxx 开头的函数,一般会把一个功能封装在一个js中

11. 其他新组件

Fragment(片断)

-   在Vue2中: 组件必须有一个根标签
-   在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个Fragment虚拟元素中
-   好处: 减少标签层级, 减小内存占用

其实就是两个div被包在 Fragment 虚拟元素中 感觉没有根元素了
<template>
   <div></div>
   <div></div>
</template>


Teleport(传送门)-弹框
-   Teleport 提供了一种干净的方法, 让组件的html在父组件界面外的特定标签
-   例如:可以把一个组件里面的弹窗popUp 直接插进body标签里面

相当于 body.appendChild(弹窗)
<teleport to="body">
   <div class="pop">
      弹窗
   </div>
</teleport>

12. defineExpose 子组件暴露数据方法

使用 <script setup> 的组件是默认关闭的,也即通过模板 ref 或者 $parent 链获取到的组件的公开实例,不会暴露任何在 <script setup> 中声明的绑定。

为了在 <script setup> 组件中明确要暴露出去的属性,使用 defineExpose 编译器宏:

  • 语法

    子组件
    <script setup>
    // 子组件暴露
    defineExpose({
      属性1:值1,
      方法1() {}
    })
    </script>
    
    父组件
    <template>
        <子组件 ref='子组件ref'></子组件>
    </template>
    
    <script setup>
    import { onMounted, ref } from 'vue';
    const 子组件ref = ref(null)
    // 注意 在生命周期onMounted 才能接受子组件暴露的数据和方法
    onMounted(() => {
        子组件ref.value.方法1();
        子组件ref.value.属性1
    })
    </script>