Web前端笔记-16、Vue3-组合式API(ref、computed、watch、生命周期函数、父子通信、模板引用)

搭建Vue3项目-create-vue

create-vue是Vue官方新的脚手架工具,底层切换到了vite(下一代前端工具链),为开发提供极速响应。

  1. 前提环境条件。已安装 16.0或更高版本的 Node.js
  2. 创建一个Vue应用npm init vue@latest,这一指令将会安装并执行 create-vue

关键文件:

  1. vite.config.js - 项目的配置文件 基于vite的配置
  2. package.json - 项目包文件 核心依赖项变成了 Vue3.x 和 vite
  3. main.js - 入口文件 createApp函数创建应用实例
  4. app.vue - 根组件 SFC单文件组件 script -template - style
    变化一:脚本script和模板template顺序调整
    变化二:模板template不再要求唯一根元素
    变化三:脚本script添加setup标识支持组合式API
  5. index.html-单页入口 提供id为app的挂载点

组合式API

setup选项

在beforeCreate之前自动执行的。

原始写法: export default{ setup(){ return{} }}

语法糖:<script setup>

只需要定义数据和函数。不需要写 export default setup函数和return

setup中的this还指向组件实例吗?指向undefined

reactive函数和ref函数

reactive()

作用:接受对象类型数据的参数传入并返回一个响应式的对象

传入:一个对象

返回:一个响应式对象

先导入后使用。

<script setup>
import { reactive } from "vue";
const state = reactive({
  count: 0,
});
</script>

<template>
  <div>
    <button @click="state.count++">{{ state.count }}</button>
  </div>
</template>

ref()

作用:接收简单类型或者对象类型的数据传入并返回一个响应式的对象

传入:一个简单类型数据或者对象

返回:一个响应式对象

先导入后使用。

<script setup>
import { ref } from "vue";
const state = ref(0);
</script>

<template>
  <div>
    <button @click="state++">{{ state }}</button>
  </div>
</template>

在模板区域直接使用变量名即可,但要在脚本区域使用值需要state.value

computed计算属性

计算属性基本思想和Vue2的完全一致,组合式API下的计算属性只是修改了写法。

  1. 导入computed函数
  2. 执行函数 在回调参数中return基于响应式数据(ref)做计算的值,用变量接收
<script setup>
import { ref, computed } from "vue";
const list = ref([1, 2, 3, 4, 5, 6, 7, 8]);
const computedList = computed(() => {
  return list.value.fil,ter((item) => item > 2);
});

setTimeout(() => {
  list.value.push(9, 10);
}, 3000);
</script>

<template>
  <div>原始:{{ list }}</div>
  <div>计算后:{{ computedList }}</div>
</template>

最佳实践

  1. 计算属性中不应该有“副作用”。副作用:比如异步请求/修改dom
  2. 避免直接修改计算属性的值。应该是只读的。

watch函数

作用:侦听一个或者多个响应式数据的变化,数据变化时执行回调函数

俩个额外参数:1.immediate(立即执行)2.deep(深度侦听)

侦听单个响应式数据

  1. 导入watch函数
  2. 执行watch函数watch(ref, (newVal, oldVal)=>{}),传入要侦听的响应式数据(ref对象)和回调函数

注意:在watch中,传入的ref对象是不需要.value的,watch会自动处理。

<script setup>
import { ref, watch } from "vue";
const count = ref(0);

watch(count, (val) => {
  console.log("new value:" + val);
});
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>

同时侦听多个响应式数据

同时侦听多个响应式数据的变化,不管哪个数据变化都需要执行回调

<script setup>
import { ref, watch } from "vue";
const count = ref(0);
const name = ref("cp");

watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
  if (newCount != oldCount) console.log("new count:" + newCount);
  if (newName != oldName) console.log("new name:" + newName);
});
</script>

<template>
  <button @click="count++">{{ count }}</button>
  <button @click="name = name + 'a'">{{ name }}</button>
</template>

深度侦听

<script setup>
import { ref, watch } from "vue";
const state = ref({ count: 0, age: 8 });

watch(state, () => console.log("变化"), {
  deep: true,
});
</script>

<template>
  <button @click="state.count++">{{ state.count }}</button>
</template>

精确侦听对象的某个属性

需求:在不开启deep的前提下,侦听age的变化,只有age变化时才执行回调

<script setup>
import { ref, watch } from "vue";
const state = ref({ count: 0, age: 8 });

watch(
  () => state.value.age,
  () => console.log("age变化了")
);
</script>

<template>
  <button @click="state.age++">{{ state.age }}</button>
</template>

deep性能损耗 尽量不开启deep

生命周期函数

生命周期函数基本使用

  1. 导入生命周期函数
  2. 执行生命周期函数 传入回调
选项式API 组合式API
beforeCreate/created setup
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted

生命周期函数是可以执行多次的,多次执行时传入的回调会在时机成熟时依次执行。

父子通信

父传子

  1. 父组件中给子组件绑定属性
  2. 子组件内部通过defineProps()接收

setup语法糖下局部组件无需注册直接使用,直接导入写标签即可。

// 父
const count = ref(100);

<SonVom message="father" :count="count"/>
// 子
const props = defineProps({
  message: String,
  count: Number,
});

子传父

  1. 父组件中给子组件标签通过@绑定自定义事件
  2. 子组件内部通过defineEmits方法生成emit方法。触发自定义事件,并传递参数

YAdPXfMY88XGy9M5jWLh_y2oS4ZAbwKfnBiiILpNwvg=

模板引用

通过ref标识获取真实的dom对象或者组件实例对象

  1. 调用ref函数生成一个ref对象
  2. 通过ref标识绑定ref对象到标签

87fkzimoDNL9H3g59RHmn9FEKjr8_b7TUZrtTlXyqK0=

默认情况下在<script setup>语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose编译宏指定哪些属性和方法允许访问

b1v8Yni7Dfo5J_YZh4Yjz6bjnAtQGpX21cc1nlQCqwA=

provide和inject

作用和场景:顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信。

跨层传递普通数据、响应数据、方法

  1. 顶层组件通过provide函数提供数据(普通数据或ref响应数据)、方法(谁的数据谁负责修改,把修改方法传出去)
  2. 底层组件通过inject函数获取数据

fGduETJ1_qIG-LQUkb-T0jy7hIOA54m_XWJnOPvW150=

posted @ 2025-06-02 18:13  subeipo  阅读(31)  评论(0)    收藏  举报