vue3使用Composition API,相比于vue2的Options API而言,我们可以按需引入需要使用到的api,而不必引入所有api,从而提高了项目打包构建的速度,减少了项目打包后的体积
1. setup
setup函数是composotion api的入口函数,我们的变量,方法,函数等都是在该函数里定义的
<template>
<div id="app">
<p>{{count}}</p>
<button @click="add">+</button>
</div>
</template>
<script>
import {ref} from 'vue' // 引入ref函数
export default {
name: 'App',
setup() {
let count = ref(0) // 用ref包装一个响应式变量
const add = () => {
count.value ++ // 被ref包装的变量取值使用.value
}
return {count, add} // 将count和add返回出去,供template使用
}
}
</script>
2. reactive
reactive方法是用来创建一个响应式的数据对象,该api很好的解决了vue2通过defineProperty实现数据响应式的缺陷(无法实现新增属性的响应式,无法实现删除属性的响应式,无法实现懒监听...)
<template>
<div id="app">
{{ data.count }}
</div>
</template>
<script>
import {reactive} from 'vue' // 从vue3中引入reactive
export default {
name: 'App',
setup() {
const data = reactive({count: 0}) // 创建响应式的数据对象
return {data} // 将响应式数据对象return出去,供template使用
}
}
</script>
3. ref?
ref底层通过reactive包装了一个对象,然后将值传递给该对象的value属性,可以将ref(prop)理解为reactive({value: prop}),所以访问ref所包装的对象时需要加上.value
<script>
import {ref, reactive} from 'vue'
export default {
name: 'App',
setup() {
const data = {count: 0}
const data1 = ref(obj)
const data2 = reactive(obj)
let data3 = ref(0)
}
}
</script>
当我们的响应式数据是基本类型或者单值对象时可以使用ref,而为引用类型时使用reactive
4. toRef?
toRef是将某个对象中的某个值转化为响应式数据,接受两个参数,第一个参数为obj对象,第二个参数为对象的属性名
<script>
import {toRef} from 'vue'
export default {
setup() {
const obj = {count: 0}
const data = toRef(obj, 'count')
return {data}
}
}
</script>
ref跟toRef的区别:
1. ref是对传入数据的拷贝,toRef是对传入数据的引用
2. ref值改变会更新视图,toRef值改变不会更新视图?
5. toRefs
toRefs的作用就是将传入对象所有的属性的值都转化为响应式数据对象,该函数只有一个参数,就是obj对象
<script>
import {toRefs} from 'vue'
export default {
setup() {
const obj = {
propA: 'vue3',
propB: 'toRefs'
}
const data = toRefs(obj)
console.log(data)
return {...toRefs(obj)}
}
}
</script>
6. shallowReactive
浅层次的reactive,reactive为深层次的,会为对象的每一层属性都使用proxy添加响应式,而shallowReactive只对对象的第一层属性添加响应式,可以进行性能优化
<script>
import {reactive, shallowReactive} from 'vue'
export default {
setup() {
const obj1 = {
propA: 0,
propB: {
propC: 1
}
}
const obj2 = {
propA: 0,
propB: {
propC: 1
}
}
const data1 = reactive(obj1) // obj1.propB.propC为响应式
const data2 = shallowReactive(obj2) // obj2.propB.propC不是响应式
}
}
</script>
7. shallowRef
浅层次的ref,可以类比shallowReactive,这里不做多解释
8. toRaw
toRaw用于获取ref或reactive对象的原始数据
<template>
<p>{{ data.propA }}</p>
<p>{{ data.propB }}</p>
<button @click="change">change</button>
</template>
<script>
import {reactive,toRaw} from 'vue'
export default {
setup() {
const obj = {
propA: 'vue3',
propB: 0
}
const data = reactive(obj)
const rawData = toRaw(data)
const change = () => {
data.propB ++
console.log(obj) // 打印原始数据obj
console.log(data) // 打印 reactive对象
}
console.log(obj === rwaData) // true
return {data, change}
}
}
</script>
9. markRaw
markRaw可以将原始数据标记为非响应式数据,即便使用ref或者reactive包装后仍然无法实现响应式,接收一个参数,即原始数据,并返回被标记后的数据
<template>
<p>{{ data.propA }}</p>
<p>{{ data.propB }}</p>
<button @click="change">change</button>
</template>
<script>
import {reactive, markRaw} from 'vue'
export default {
setup() {
const obj = {
propA: 'vue3',
propB: 0
}
// 通过markRaw标记原始数据obj, 使其数据更新不再被追踪
const rawData = markRaw(obj)
// 试图用reactive包装raw, 使其变成响应式数据
const data = reactive(rawData )
const change = () => {
data.propB ++ // 值被修改但视图不会更新
}
return {data, change}
}
}
</script>
10. provide&inject
与vue2中的provide&inject的作用是一样的,在vue3中需要手动引入
provide:向子组件以及子孙组件传递数据,接收两个参数,第一个参数是key,即数据名,第二个参数为value,即数据值
inject:接收父组件或祖先组件传递过来的数据,接收一个参数key,父组件或祖先组件传递的数据名
// C是B的子组件,B是A的子组件
// A.vue
<script>
import {provide} from 'vue'
export default {
setup() {
const data = {
prop: 'vue3'
}
// 向子组件以及子孙组件传递名为data的数据
provide('data', data)
}
}
</script>
// B.vue
<script>
import {inject} from 'vue'
export default {
setup() {
// 接收A.vue传递过来的数据
inject('data') // {prop: 'vue3'}
}
}
</script>
// C.vue
<script>
import {inject} from 'vue'
export default {
setup() {
// 接收A.vue传递过来的数据
inject('data') // {prop: 'vue3'}
}
}
</script>
11. watch&watchEffect?
用来监视某项数据变化从而执行指定的操作
1. watch(source, cb, [options]):
source:可以是表达式或函数,用于指定监听的依赖对象
cb:?依赖对象变化后执行的回调函数
options:?可选参数,可以配置的属性有immediate(立即触发回调函数),deep(深度监听)
watch方法会返回一个stop方法,如果需要停止监听,可以直接执行stop方法
<script>
import {ref, reactive, watch} from 'vue'
export default {
setup() {
// 监听ref
const data1 = ref(0)
watch(data1, (newValue, oldValue) => {
console.log(`原值为${oldValue}`, `新值为${newValue}`)
// 1秒后打印结果:原值为0,新值为1
})
setTimeout(() => {
data1.value ++
}, 1000)
// 监听reactive
const data2 = reactive({prop: 0})
watch(() => data2.prop, (newValue, oldValue) => {
console.log(`原值为${oldValue}`, `新值为${newValue})
// 1秒后打印结果:原值为0,新值为1
})
setTimeout(() => {
data2.prop ++
}, 1000)
// 监听多个数据
const data3 = reactive({ propA: 0, propB: 'vue3' })
watch(
[() => data3.propA, () => data3.propB],
([newPropA, newPropB], [oldPropA, oldPropB]) => {
console.log(oldPropA, newPropA, oldPropB, newPropB)
// 1秒后打印结果:0, 1, vue3, hello vue3
}
)
setTimeout(() => {
data3.propA ++
data3.propB = 'hello vue3'
}, 1000)
}
}
</script>
2. watchEffect
watchEffect跟watch不同,它不需要手动传入依赖,每次初始化的时候就会执行一次回调函数来自动获取到依赖,无法获取到原始值,只能获取改变后的值
<script>
import {reactive, watchEffect} from 'vue'
export default {
setup() {
const data = reactive({propA: 0, propB: 'vue3'})
watchEffect(() => {
console.log(data.propA, data.propB)
console.log(state.name)
// 初始化打印:0 vue3
// 一秒后打印:1 hello vue3
})
setTimeout(() => {
data.propA ++
data.propB = 'hello vue3'
}, 1000)
}
}
</script>
12. computed
<template>
<div>
<p><input type="text" v-model="propA"></p>
<p><input type="text" v-model="propB"></p>
</div>
</template>
<script>
import { computed, ref } from 'vue'
export default {
setup() {
const propA = ref(0)
const propB = computed(() => {
return propA.value + 1
})
return {
propA,
propB
}
}
}
13. useStore
vue3中使用vuex的方式跟vue2不一样,需要使用vuex中的useStore方法
import Vuex from 'vuex'
const store = Vuex.createStore({
state: {
propA: 'vue3'
},
mutations: {
……
}
})
<script>
import {useStore} from 'vuex'
export default {
setup() {
const store = useStore()
console.log(store)
}
}
</script>
14. useRouter
vue3中使用路由的方式跟vue2不一样,需要使用router中的useRouter方法
<script>
import {useRouter} from 'vue-router'
export default {
setup() {
const router = useRouter()
router.push({
path: `/`
})
}
}
</script>
15.?getCurrentInstance
vue3中获取实例的方式跟vue2不一样,需要使用getCurrentInstance方法
<template>
<p></p>
</template>
<script>
import {getCurrentInstance} from 'vue'
export default {
setup() {
const instance = getCurrentInstance()
console.log(instance)
return {}
}
}
</script>
16. 元素ref属性
元素ref属性可以获取到标签的元素或组件
<template>
<div>
<div ref="el">div元素</div>
</div>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup() {
// 创建一个DOM引用,名称必须与元素的ref属性名相同
const el = ref(null)
// 在挂载后才能通过 el 获取到目标元素
onMounted(() => {
console.log(el.value)
})
return {el}
}
}
</script>
|