# 快速上手
在Vue3中使用所有Vue内置函数都需要引入,如ref、computed、onMounted、reactive等
# setup
- setup 是一个新的组件选项,(它充当在组件内部使用 Composition API 的入口点。)
- 在 beforeCreate 之前,全局只调用一次。
- 使用setup语法糖后所有函数都不需要
return
# setup 用法
<script setup></script>
# 使用ref定义基本响应式数据
js部分
<script setup>
import {ref} from "vue";
let name = ref('李四')
</script>
# 使用reactive定义响应式对象
<script setup>
import {reactive} from "vue";
let people = reactive({
name: '张三',
age: '18',
sex: '男'
})
</script>
# 计算属性
<script setup>
import {computed} from "vue";
//定义属性
let computedname = reactive({
firstname: '',
lastname: ''
})
//基本使用
const fillname = computed(() => {
return computedname.firstname + computedname.lastname
})
//定义在对象中 不考虑值被修改的情况(不考率写的情况)
computedname.name = computed(() => {
return computedname.firstname + computedname.lastname
})
</script>
# 监听器的使用
# 监视ref定义的一个响应式数据
watch 接收三个参数
- 要监视谁
- 监视的回调
- 监视的配置
# 示例代码
import {watch} from "vue";
let count = ref(0)
let msg = ref('张三')
watch(count, (newvalue, oldvalue) => {
console.log(`count变化了,新值是${newvalue},旧值是${oldvalue}`)
}, {
//开启立即监视
immediate: true,
//开启深度监视
deep: true
})
# 立即监视 immediate: true
开启后页面加载或页面刷新,将立即监视一次
# 开启深度监视 deep: true
开启后将对数据进行深层监视,任意孩子发生变化,函数将执行一次
# 监视ref定义的多个响应式数据
import {watch} from "vue";
let count = ref(0)
let msg = ref('张三')
watch([count, msg], (newvalue, oldvalue) => {
console.log(`count变化了,新值是${newvalue},旧值是${oldvalue}`)
})
# 监视reactive定义的数组或对象(全部数据)
import {watch} from "vue";
let watchpeople = reactive({
name: '王五',
age: 50,
job: {
jon1: {
money: 20
}
}
})
//此处无法正确获取oldvalue
//强制开启了深度监听 无法关闭
watch(watchpeople, (newvalue, oldvalue) => {
console.log(`watchpeople变化了,旧值是`, newvalue, oldvalue)
}, {
deep: false
}) //此处的deep配置无效
# 监视reactive定义的数组或对象中的某一个数据(需写成函数)
import {watch} from "vue";
let watchpeople = reactive({
name: '王五',
age: 50,
job: {
jon1: {
money: 20
}
}
})
watch(() => watchpeople.name, (newvalue, oldvalue) => {
console.log(`watchpeople.name变化了,新值是${newvalue},旧值是${oldvalue}`)
})
# 监视reactive定义的数组或对象中的某些数据(需写成数组函数)
import {watch} from "vue";
let watchpeople = reactive({
name: '王五',
age: 50,
job: {
jon1: {
money: 20
}
}
})
watch([() => watchpeople.name, () => watchpeople.age], (newvalue, oldvalue) => {
console.log(`watchpeople.name或age变化了,新值是${newvalue},旧值是${oldvalue}`)
})
# 监视对象中的对象(需要开启深度监听)
import {watch} from "vue";
let watchpeople = reactive({
name: '王五',
age: 50,
job: {
jon1: {
money: 20
}
}
})
watch(() => watchpeople.job, (newvalue, oldvalue) => {
console.log(`watchpeople.job变化了,新值是${newvalue},旧值是${oldvalue}`)
}, {
deep: true //此处由于监视的是reactive中定义的某个属性所以必须开启深度监听
})
# storeToRefs()监听pinia里的数据变化
- 在使用
pinia获取数据时,ES6解构出来的数据是有问题的,已经丢失了响应式,也就是一次性的,之后对数据的修改Vue是无法监测到数据变化的。 - 解决办法:使用Pinia为我们提供的storeToRefs()API,这就类似Vue3中的toRefs()。
- 在使用
storeToRefs()包裹的数据时需要加value,类似ref()
//导入
import {storeToRefs} from 'pinia'
//初始化
const {currentInstitution} = storeToRefs(useIntStore())
//使用
console.log(currentInstitution.value)
# 使用监听器监听pinia里的数据变化
注意
如果开启立即监听 将会在页面挂载前就监听一次,如果使用onload传递页面参数,监听器会在onload函数调用前监听一次
//监听当前医院选择的变化
watch(currentInstitution, (newvalue, oldvalue) => {
getlist(currentInstitution.value.id)
}, {
immediate: true//开启立即监听
})
`
# watchEffect监听(用到谁监听谁)
- watchEffect刚开始就会立即执行,并且会自动收集依赖,当其中的依赖项发生改变,都会执行回调函数。
- 并且能够分别多层的对象
import {watchEffect} from "vue";
let watchpeople = reactive({
name: '王五',
age: 50,
job: {
jon1: {
money: 20
}
}
})
watchEffect(() => {
const num = watchpeople.age
console.log('watchEffect所指定的回调函数执行了')
})
# watchEffect副作用函数
watchEffect接收一个副作用函数
watchEffect(onInvalidate => {
console.log(`${sum.person.age} 的值变化了!`)
onInvalidate(() => {
console.log('清除副作用函数执行了!')
})
})
//打印结果
//18 的值变化了!
//清除副作用函数执行了!
//19 的值变化了!
# onInvalidate清除副作用函数注意点
- 该函数总是在watchEffect执行的时候再次执行
- 当组件被销毁的时候该函数再次执行
- 该函数总是优先于watchEffect中的同步/异步代码执行
- Promize函数的执行应该在该函数下面
# 清除副作用函数的执行时机由flush控制
watchEffect(onInvalidate => {
console.log(`${sum.person.age} 的值变化了!`)
onInvalidate(() => {
console.log('清除函数执行了!')
})
}, {
//'pre' 在组件更新更新前运行,默认为'pre'
//'post'在组件更新更新后运行
//'sync'强制效果始终同步触发。然而,这是低效的,应该很少需要。
flush: 'post'
})
//打印结果
//18 的值变化了!
//清除函数执行了!
// 19 的值变化了!
# watchEffect停止监听
watchEffect选项中返回的函数是停止监听函数。
import {watchEffect} from "vue";
let watchpeople = reactive({
name: '王五',
age: 50,
job: {
jon1: {
money: 20
}
}
})
const cancel = watchEffect(() => {
const num = watchpeople.age
console.log('watchEffect所指定的回调函数执行了')
if (age >= 50) cancel()
})
# watchEffect侦听器调试
watchEffect(() => {
console.log(`${sum.person.age} 的值变化了!`)
}, {
onTrack(e) { //追踪其依赖的时候触发,只能在开发者模式下使用
console.log(e.target)
},
onTrigger(e) { //依赖项被改变的时候触发,只能在开发者模式下使用
console.log(e.target)
}
})
# 其他类型的watchEffect
watchPostEffect带有 flush: ‘post’ 选项。watchSyncEffect带有 flush: ‘sync’ 选项。
# 生命周期的使用
import {shallowReactive, onMounted} from "vue";
let list = shallowReactive({
arr: []
})
onMounted(() => {
list.arr = [{
id: 0,
name: '张三'
},
{
id: 1,
name: '李四'
},
{
id: 2,
name: '王五'
}
]
})
# hooks的使用 与mixin 同理
vue3里面可以自定义hook 主要是用来存储一些复用的逻辑、变量的封装。相当于vue2里面的minins
# 既然vue2有minins为什么vue3提出了Hook?
minins缺点:
- 组件的data、methods、filters会覆盖mixins里的同名data、methods、filters。
- 变量不好找,可读性不好,维护起来比较复杂 不同于mixin, hook是函数,这样就可以帮助我们提高代码的复用性, 让我们能在不同的组件中都利用 hooks 函数
# 定义hook(建议新建hooks文件夹)
export default () => {
let point = reactive({
pagex: 0,
pagey: 0
})
//获取鼠标位置的处理函数
const getpoint = (event) => {
point.pagex = event.pageX
point.pagey = event.pageY
}
//页面挂载时为win对象添加点击事件
onMounted(() => {
window.addEventListener('click', getpoint)
})
//页面卸载时移除点击事件
onBeforeUnmount(() => {
window.removeEventListener('click', getpoint)
})
return point
}
# hook的使用
<template>
<view class="title">动态获取鼠标位置</view>
<span>x:{{point.pagex}}</span>
<hr>
<span>y:{{point.pagey}}</span>
</template>
<script setup>
//引入
import Getpoint from '../../hooks/point.js'
//定义
const point = Getpoint()
</script>
# 组件中v-model的实现
- 实现
v-model组件中需要两个数据 props值emits
注意
- props和emits命名名称必须相同
- emits传入的函数声明必须使用 update前缀
<template>
<view>
<template
v-for="(item, index) in props.data"
:key="index">
<view
@click="change(item)">
{{ item.name }}
</view
>
</template>
</view>
</template>
<script setup>
import {defineProps} from 'vue'
const props = defineProps({
data: [],
value: {}//emits中使用 update:value
})
const emits = defineEmits(['update:value'])
const change = (item) => emits('update:value', item)
</script>
# 父组件使用
<template>
<TextModelValue
v-model:value="currentValue"
:data="dataList"/>
</template>