组合式API【Vue3】

Vue3组合式API体验

通过一个 Counter(自增)案例 体验Vue3新引入的组合式API
Vue2的代码:

<template>
	<button @click="addCount">{{count}}</button>
</template>
<script>
export default {
	data(){
		return {
			count: 0
			}
		},
	methods: {
		addCount(){
			this.count++
		}
	}
}
</script>

Vue3组合式API实现的代码:

<template>
	<button @click="addCount">{{count}}</button>
</template>
<script setup>
	import {ref} from 'vue'
	const count = ref(0)
	const addCount = () => count.value++
</script>

Vue3更多的优势

  • 更容易维护
    • 组合式API
    • 更好的TypeScript支持
  • 更快的速度
    • 重写diff算法
    • 模板编译优化
    • 更高效的组件初始化
  • 更小的体积
    • 良好的TreeShaking
    • 按需引入
  • 更优的数据响应式
    • Proxy

认识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选项

setup选项的写法和执行

<script>
export default {
	setup(){
	
	},
	beforeCreate(){
	
	},
}
</script>

在这里插入图片描述

< script setup >语法糖

  • 原始复杂写法
<script>
export default {
	setup(){
		//数据
		const message = 'this is message'
		//函数
		const logMessage = () => {
			console.log(message)
		}
		return {
			message,
			logMessage
		}
	}
}
</script>
  • 语法糖写法
<script setup>
//数据
const message = 'this is message'
//函数
const logMessage = () => {
	console.log(message)
}
</script>

总结:

  1. setup选项的执行机制?
    beforeCreate钩子之前 自动执行
  2. setup写代码的特点是什么?
    定义数据 + 函数 然后以对象方式return
  3. < script setup >解决了什么问题?
    经过语法糖的封装更简单的使用组合式API
  4. setup中this还指向组件实例吗?
    指向undefined

组合式API - reactive和ref函数

  1. reactive()
    作用:接受对象类型数据的参数传入并返回一个响应式对象
  2. 核心步骤:
<script setup>
//导入
import {reactive} from 'vue'
//执行函数 传入参数 变量接收
const state = reactive(对象类型数据)
</script>
  • 从vue包中导入reactive函数
  • 在< script setup> 中执行reactive 函数并传入类型为对象的初始值,并使用变量接收返回值
    案例:
<script setup>
//1. 导入函数
import {reactive} from 'vue'

//2. 执行函数 传入一个对象类型的参数 变量接收
const state = reactive({
  count: 0
})

const setCount = () => {
  state.count++
}
</script>

<template>
  <div>
    <button @click="setCount">{{ state.count }}</button>
  </div>
</template>
  1. ref()
    作用:接收简单类型或者对象类型的数据传入并返回一个响应式的对象
    核心步骤:
<script setup>
//导入
import {ref} from 'vue'
//执行函数 传入参数 变量接收
const count = ref(简单类型或者复杂类型数据)
</script>
  • 从vue包中导入ref函数
  • 在< script setup >中执行ref函数并传入初始值,使用变量接收ref函数的返回值

总结:
(1) reactive和ref函数的共同作用是什么?
用函数调用的方式生成响应式数据
(2)reactive vs ref?
- reactive不能处理简单类型的数据
- ref参数类型支持更好但是必须通过.value访问修改
- ref函数的内部实现依赖于reactive函数
(3)在实际工作中推荐使用哪个?
推荐使用ref函数,更加灵活

computed计算属性函数

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

  1. 导入computed函数
  2. 执行函数在回调参数中return基于响应式数据做计算的值,用变量接收

计算属性小案例:

<script setup>
// 原始响应式数组
import {ref} from 'vue'
// 1.导入computed函数
import {computed} from 'vue'
const list = ref([1, 2, 3, 4, 5, 6, 7, 8])

// 2.执行函数 return 计算之后的值 变量接收
const computedList = computed(() => {
  return list.value.filter(item => item > 2)
})
setTimeout(() => {
  list.value.push(9, 10)
}, 3000)
</script>

<template>
  <div>
    原始响应数组 - {{ list }}
  </div>
  <div>
    计算属性数组 - {{ computedList }}
  </div>
</template>
  • 计算属性中不应该有“副作用”(异步请求/修改dom)
  • 避免直接修改计算属性的值(计算属性应该是只读的)

watch函数

作用:侦听一个或者多个数据的变化,数据变化时执行回调函数
两个额外的参数:1. immediate(立即执行)2. deep(深度侦听)

  1. 基础使用 - 侦听单个数据
  • 导入watch函数
  • 执行watch函数传入要侦听的响应式数据(ref对象)和回调函数
<script setup>
import {ref, watch} from 'vue'
const count = ref(0)
const setCount = ()=>{
  count.value++
}

// ref对象不需要加.value
watch(count, (newVal, oldVal)=>{
  
})
</script>

<template>
  <div>
    <button @click="setCount">+{{ count }}</button>
  </div>
</template>
  1. 基础使用 - 侦听多个数据
    说明:同时侦听多个响应式数据的变化,不管哪个数据变化都需要执行回调
<script setup>
// 侦听多个数据变化
import {ref, watch} from 'vue'

const count = ref(0)
const changeCount = ()=>{
  count.value++
}

const name = ref('cp')
const changeName = ()=>{
  name.value = 'pc'
}

watch([count, name], ([newCount, newName], [oldCount, oldName])=>{
  console.log('count或者name变化了', [newCount, newName], [oldCount, oldName]);
})
</script>

<template>
  <div>
    <button @click="changeCount">修改count--{{ count }}</button>
  </div>
  <div>
    <button @click="changeName">修改name--{{ name }}</button>
  </div>
</template>
  1. immediate
    说明:在侦听器创建时立即触发回调,响应式数据变化之后继续执行回调
const count = ref(0)
watch(count, () => {
	console.log('count发生了变化')}{immediate: true})
  1. deep
    默认机制:通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep选项
<script setup>
import {ref, watch} from 'vue'
const state = ref({count: 0})
const changeStateByCount = () => {
	//直接修改count
	state.value.count++
}
//watch深度监听
watch(state, ()=>{
	console.log('count变化了')
}, {
	deep: true
})
</script>
<template>
  <div>
    {{state.count}}
    <button @click="changeStateByCount">通过count修改</button>
  </div>
</templete>
  1. 精确侦听对象的某个属性
    需求:在不开启deep的前提下,侦听age的变化,只有age变化时才执行回调

总结:

  • 作为watch函数的第一个参数,ref对象需要添加.value吗?
    不需要,watch会自动读取
  • watch只能侦听单个数据吗?
    单个或者多个
  • 不开启deep,直接修改嵌套属性能触发回调吗?
    不能,默认是浅层侦听
  • 不开启deep,想在某个层次比较深的属性变化时执行回调怎么做?
    可以把第一个参数写成函数的写法,返回要监听的具体属性

组合式API - 生命周期函数

Vue3的生命周期(选项式 VS 组合式)

选项式API组合式API
beforeCreate/createdsetup
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted

生命周期函数的基本使用

  1. 导入生命周期函数
  2. 执行生命周期函数 传入回调

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

<script setup>
// 生命周期函数的使用
// 1.引入函数
import {onMounted} from 'vue'

// 2.执行函数 传入回调
onMounted(()=>{
  console.log('组件挂载完毕mounted执行了1')
})

onMounted(()=>{
  console.log('组件挂载完毕mounted执行了2')
})
</script>

<template>
  <div>

  </div>
</template>
  • 组合式API中生命周期函数的格式是什么?
    on+生命周期名字
  • 组合式API中可以使用onCreated吗?
    没有这个钩子函数,直接写到setup中
  • 组合式API中组件卸载完毕时执行哪个函数?
    onUnmounted

组合式API - 父子通信

组合式API下的父传子
基本思想

  1. 父组件中给子组件绑定属性
  2. 子组件内部通过props选项接收
    父:
<script setup>
// setup语法糖下局部组件无需注册直接可以使用
import SonCom from './son-com.vue'
</script>

<template>
  <div class="father">
    <h2>父组件App</h2>
    <!-- 1.绑定属性 -->
    <SonCom message="father message"/>
  </div>
</template>

<style scoped>
</style>

子:

<script setup>
// 2.defineProps接收数据
const props = defineProps({
    message: String
})
console.log(props);
</script>

<template>
    <div class="son">
        <h3>子组件Son</h3>
        <div>
            父组件传入的数据 - {{ message }}
        </div>
    </div>
</template>

<style scoped>
</style>

组合式API下的子传父
基本思想

  1. 父组件中给子组件标签通过 @ 绑定事件
  2. 子组件内部通过 $emit 方法触发事件
    父:
<script setup>
// 引入子组件
import sonComVue from './son-com.vue'
const getMessage = (msg) => {
  console.log(msg);
}
</script>
<template>
  <sonComVue @get-message="getMessage"/>
</template>

子:

<script setup>
//2. 通过defineEmits编译器宏生成emit方法
const emit = defineEmits(['get-message'])
const sendMsg = () => {
    //3. 触发自定义事件 并传递参数
    emit('get-message', 'this is son msg')
}
</script>

<template>
    <button @click="sendMsg">sendMsg</button>
</template>

父传子

  1. 子传父的过程中通过什么方式接收props?
defineProps({属性名:类型})
  1. setup语法糖中如何使用父组件传过来的数据?
const props = defineProps({属性名:类型})

子传父

  1. 子传父的过程中通过什么方式得到emit方法
defineEmits(['事件名称'])

组合式API - 模板引用

模板引用的概念:通过ref标识获取真实的dom对象或者组件实例对象
如何使用(以获取dom为例 组件同理)

  1. 调用ref函数生成一个ref对象
  2. 通过ref标识绑定ref对象到标签
<script setup>
import {onMounted, ref} from 'vue'
import TestCom from './test-com.vue'
//1. 调用ref函数 -> ref对象
const h1Ref = ref(null)
const comRef = ref(null)

//组件挂载完毕之后才能获取
onMounted(() => {
  console.log(h1Ref.value);
  console.log(comRef.value);
})
</script>

<template>
  <!-- //2. 通过ref标识绑定ref对象 -->
  <h1 ref="h1Ref">我是dom标签h1</h1>
  <TestCom ref="comRef"/>
</template>

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

<script setup>
import {ref} from 'vue'
const testMessage = ref('this is test msg')
</script>
<script setup>
import {ref} from 'vue'
const testMessage = ref('this is test msg')
defineExpose({
	testMessage
})
</script>
  1. 获取模板引用的时机是什么?
    组件挂载完毕
  2. defineExpose编译宏的作用是什么?
    显示暴露组件内部的属性和方法
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值