文章目录
组合式API入口-setup
setup选项的写法和执行时间
写法
<script>
export default {
setup(){
},
beforeCreate(){
}
}
</script>
执行时间
由生命周期图得知,在组件进行渲染的时候会优先执行setup
,它的执行时机是在beforeCreate
之前并且是自动执行的。
示例
<script>
export default {
setup() {
console.log('setup')
},
beforeCreate() {
console.log('beforeCreate')
}
}
</script>
<template>
<div id="app"></div>
</template>
运行结果
setup选项中写代码的特点
在setup函数
中写的数据和方法需要在末尾以对象的方式return
,才能给模版使用。
<script>
export default {
setup() {
// 数据
const message = 'this is a message'
// 函数
const logMessage = () => {
console.log(message)
}
// 以对象的形式返回数据和方法,模板中才能使用数据和函数
return {
message,
logMessage
}
},
beforeCreate() {
}
}
</script>
<template>
<div>
{{ message }}
<button @click="logMessage">Log Message</button>
</div>
</template>
setup语法糖
上面的原始写法过于复杂,每定义一次数据或函数都需要return
一下,繁琐。而在script标签
添加 setup标记
,就不需要再写导出语句,默认会添加导出语句,简洁。
<script setup>
const message = 'this is a message'
const logMessage = ()=>{
console.log(message)
}
</script>
组合式API-reactive和ref函数
reactive
和ref函数
共同作用是用函数调用的方式生成响应式数据。
reactive()
作用
接受对象类型数据的参数传入并返回一个响应式的对象
核心步骤
- 从
vue
包中导入reactive函数
- 在
<script setup>
中执行reactive函数
并传入类型为对象的初始值,并使用变量接收返回值
<script setup>
// 导入
import { reactive } from 'vue'
// 执行函数 传入参数 变量接收
const state = reactive({
msg:'this is msg'
})
const setSate = ()=>{
// 修改数据更新视图
state.msg = 'this is new msg'
}
</script>
<template>
{{ state.msg }}
<button @click="setState">change msg</button>
</template>
ref()
作用
接收简单类型或者对象类型的数据传入并返回一个响应式的对象
核心步骤
- 从vue包中导入ref函数
- 在
<script setup>
中执行ref函数
并传入初始值,使用变量接收ref函数
的返回值
<script setup>
// 导入
import { ref } from 'vue'
// 执行函数 传入参数 变量接收
const count = ref(0)
const setCount = ()=>{
// 修改数据更新视图必须加上.value
count.value++
}
</script>
<template>
<button @click="setCount">{{count}}</button>
</template>
reactive 对比 ref
reactive
不能处理简单类型的数据ref参数
类型支持更好,但是必须通过.value
做访问修改ref函数
内部的实现依赖于reactive函数
- 推荐使用
ref函数
,更加灵活
组合式API-computed计算属性函数
计算属性基本思想和Vue2保持一致,组合式API下的计算属性只是修改了API写法
核心步骤
- 导入
computed函数
- 执行函数在回调参数中return基于响应式数据做计算的值,用变量接收
<script setup>
// 1.导入
import {ref, computed } from 'vue'
// 原始数据
const list = ref([1,2,3,4,5,6,7,8])
// 2.执行函数return计算之后的值,用变量接收
const filterList = computed(() => {
return list.value.filter(item=>item > 2)
})
</script>
<template>
<div>
原始响应数组:{{ list }}
</div>
<div>
计算属性数组:{{ computedList }}
</div>
</template>
注意
- 计算属性中不应该有“副作用”,比如
异步请求/修改dom
- 避免直接修改计算属性的值,计算属性应该是只读的
组合式API-watch函数
作用
侦听一个或者多个数据的变化,数据变化时执行回调函数,俩个额外参数immediate
控制立刻执行,deep
开启深度侦听
侦听单个数据
核心步骤
- 导入
watch函数
- 执行
watch函数
传入要侦听的响应式数据(ref对象
)和回调函数
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const count = ref(0)
// 2. 调用watch 侦听变化
watch(count, (newValue, oldValue)=>{
console.log(`count发生了变化,旧值为${oldValue},新值为${newValue}`)
})
</script>
侦听多个数据
说明
同时侦听多个响应式数据的变化,不管哪个数据变化都需要执行回调函数
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const count = ref(0)
const name = ref('cp')
// 2. 调用watch 侦听变化
// 侦听多个数据,第一个参数可以改写成数组的写法
watch([count, name], ([newCount, newName],[oldCount,oldName])=>{
console.log(`count或者name变化了,[newCount, newName],[oldCount,oldName])
})
</script>
immediate
说明
侦听器创建时立即出发回调,响应式数据变化之后继续执行回调
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const count = ref(0)
// 2. 调用watch 侦听变化
watch(count, (newValue, oldValue)=>{
console.log(`count发生了变化,旧值为${oldValue},新值为${newValue}`)
},{
immediate: true
})
</script>
deep
说明
通过watch
监听的ref对象
默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep
选项,但是一旦开启deep便会进行递归遍历,造成性能损耗,尽量不开启deep
。
// 默认机制
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const state = ref({ count: 0 })
// 2. 监听对象state
watch(state, ()=>{
console.log('数据变化了')
})
const changeStateByCount = ()=>{
// 直接修改不会引发回调执行
state.value.count++
}
</script>
// 开启deep选项
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const state = ref({ count: 0 })
// 2. 监听对象state 并开启deep
watch(state, ()=>{
console.log('数据变化了')
},{deep:true})
const changeStateByCount = ()=>{
// 此时修改可以触发回调
state.value.count++
}
</script>
精确侦听对象的某个属性
需求
在不开启deep
的前提下,侦听age的变化,只有age变化时才执行回调函数
// 默认机制
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const state = ref({
name: 'zhangsan',
age: 18
})
const changeName = () => {
//修改name
state.value.name = 'lisi'
}
const changeAge = () => {
//修改age
state.value.age = 20
}
// 2. 精确侦听某个具体属性
watch(
() => state.value.age,
()=>{
console.log('age变化了')
})
</script>
组合式API-生命周期函数
选项式API和组合式API的对比
生命周期函数的基本使用
核心步骤
- 导入生命周期函数
- 执行生命周期函数,传入回调函数
<scirpt setup>
// 导入生命周期函数
import { onMounted } from 'vue'
// 执行生命周期函数,传入回调函数
onMounted(()=>{
// 自定义逻辑
})
</script>
生命周期函数执行多次的时候,会按照顺序依次执行,故可以做到不动原有生命周期函数的逻辑,再补充新的逻辑。
<scirpt setup>
import { onMounted } from 'vue'
onMounted(()=>{
// 自定义逻辑
})
onMounted(()=>{
// 自定义逻辑
})
</script>
组合式API-父子通信
父传子
基本思想
- 父组件中给子组件绑定属性
- 子组件内部通过
props
选项接收
// 父组件
<script setup>
// 引入子组件,setup语法糖下局部组件无需注册导入后直接可以使用
import sonComVue from './son-com.vue'
// 响应式数据
const count = ref(100)
</script>
<template>
<!-- 1.绑定属性 message -->
<sonComVue :count="count" message="this is app message" />
</template>
// 子组件
<script setup>
// 2.通过definProps“编译器宏”接收子组件传递的数据
const props = definProps({
message: String,
count: Number
})
</script>
<template>
{{ message }}
{{ count }}
</template>
子传父
基本思想
- 父组件中给子组件标签通过
@
绑定事件 - 子组件内部通过
$emit
方法触发事件
// 父组件
<script setup>
// 引入子组件,setup语法糖下局部组件无需注册导入后直接可以使用
import sonComVue from './son-com.vue'
const getMessage = (msg) => {
console.log(msg)
}
</script>
<template>
<!-- 1.绑定自定义事件 -->
<sonComVue @get-message="getMessage" />
</template>
// 子组件
<script setup>
// 2.通过definEmits“编译器宏”生成emit方法
const emit = defineEmits(['get-message'])
const sendMsg = () => {
//3.触发自定义事件 并传递参数
emit('get-message', 'this is son message')
}
</script>
<template>
<button @click="sendMsg">发送信息</button>
</template>
组合式API模板引用
概念
通过ref标识
获取真实的dom对象
或者组件实例对象
实现步骤
- 调用
ref函数
生成一个ref对象
- 通过
ref标识
绑定ref对象
到标签
<script setup>
import { ref } from'vue'
//1.调用ref函数得到ref对象
const h1Ref = ref(null)
</script>
<template>
<!--2.通过ref标识绑定ref对象 -->
<h1 ref="h1Ref">我是dom标签h1</h1>
</template>
defineExpose
默认情况下在 <script setup>
语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose
编译宏指定哪些属性和方法容许访问
说明:指定testMessage
属性可以被访问到
<script setup>
import { ref } from'vue'
const name = ref('test name')
const setName = () => {
name.value = 'test new name'
}
defineExpose({
name,
setName
)}
</script>
<template>
<div>我是test组件</div>
</template>
组合式API - provide和inject
作用和场景
顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信信
跨层传递普通数据
实现步骤
- 顶层组件通过
provide
函数提供数据 - 底层组件通过
inject
函数提供数据
跨层传递响应式数据
在调用provide
函数时,第二个参数设置为ref
对象
跨层传递方法
顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件的数据