前言:
最近刚弄明白什么是组合式API,什么是选项式API,使用vue2.x这么多年,居然不知道一直在使用的居然是选项式API,以此文对这两个知识点做个总结,纪念自己的无知。
选项式API VS 组合式API
1.vue2中的选项式 API (options API)
页面使用methods、watch、computed等来处理页面逻辑,vue2中的常规格式,不做过多说明。
export default{
data(){
},
//方法
methods:{
},
//观察属性
watch:{
},
//计算属性
computed:{
}
}
为什么使用组合式API
选项式 API,看起来结构很清晰,当随着业务功能不断增加,代码不断迭代,methods、watch、computed中的代码会不断增加,可能一个vue中包含几个功能,这些功能在methods等内是零散的,当进行bug修复或者添加新功能时带来的工作量会很大,基于这些问题,vue3的组合式API应运而生。
2. vue3中的组合式API
引入vue官方示例,setup内的部分为组合式API
export default {
props: {
user: { type: String }
},
setup(props) {
console.log(props) // { user: '' }
return {} // 这里返回的任何内容都可以用于组件的其余部分
}
// 组件的“其余部分”
}
setup参数
1.props
父组件传入的props
示例:
export default {
props: {
title: String
},
setup(props) {
console.log(props.title) //父组件传入的title值
}
}
2.context
示例:
export default {
setup(props, context) {
// Attribute (非响应式对象)
console.log(context.attrs) //包含除props以外的参数,与vue2中的this.$attrs功能一致
// 插槽 (非响应式对象)
console.log(context.slots)//包含插槽,与this.$slots功能一致
// 触发事件 (方法)
console.log(context.emit)//触发事件,与this.$emit方法一致
}
}
前置知识点:
vue3支持tree-shaking(死代码消除),因此vue2中挂载在vue上的全局方法现在必须单独引入才能使用。
vue 2.x
this.$nextTich(()=>{
});
vue 3
import { nextTick } from 'vue'
nextTick(()=>{
})
setup什么时候触发
在组件创建之前执行,props
被解析,然后执行setup
并将props
传入方法,由于执行setup
时组件实例尚未创建,所以setup
内无法使用this
,并且无法访问methods
、watch
、computed
内的方法及属性。
setup使用
1. 响应式变量
setup
内使用ref
函数实现变量的响应式,并使用return
返回变量,供给模板内使用。
未使用ref
时
示例:
<template>
<div>name:{{name}}</div>
<button @click="updateName">修改姓名</button>
</template>
<script>
export default {
name: "test",
setup(){
let name = '';
let updateName = ()=>{
name = 'xiaoming';
console.log("修改名字",name)
}
return {name,updateName}
}
}
</script>
<style scoped>
</style>
由于变量是未响应的,所以点击修改触发方法,修改后的值并没有更新到dom
中。
使用ref
示例:
<template>
<div>name:{{name}}</div>
<button @click="updateName">修改姓名</button>
</template>
<script>
import {ref} from 'vue'
export default {
name: "test",
setup(){
let name = ref('')
console.log(name); //{value:''}
let updateName = ()=>{
name.value = 'xiaoming';
console.log("修改名字",name)
}
return {name,updateName}
}
}
</script>
<style scoped>
</style>
使用ref
方法定义变量后,返回的是一个对象,如果需要修改变量的值需要使用变量.value
修改变量的值。
2. setup
内使用watch
示例:
<template>
<div>name:{{name}}</div>
<button @click="updateName">修改姓名</button>
</template>
<script>
import {ref,watch} from 'vue'
export default {
name: "test",
setup(){
let name = ref('')
console.log(name);
let updateName = ()=>{
name.value = 'xiaoming';
console.log("修改名字",name)
}
//计算属性观察name变化
watch(name,(newVal,oldVal)=>{
console.log("newVal",newVal) //xiaoming
console.log("oldVal",oldVal) // ''
})
return {name,updateName}
}
}
</script>
<style scoped>
</style>
3. setup
内使用computed
示例:
<template>
<div>name:{{name}}</div>
<div>{{nowName}}</div>
<button @click="updateName">修改姓名</button>
</template>
<script>
import {ref,computed} from 'vue'
export default {
name: "test",
setup(){
let name = ref('')
console.log(name);
let updateName = ()=>{
name.value = 'xiaoming';
console.log("修改名字",name)
}
//使用计算属性返回
let nowName = computed(()=>{
return `现在的名字是:${name.value}`
})
return {name,updateName,nowName}
}
}
</script>
<style scoped>
</style>
4. setup
内触发生命周期函数
选项式API
与对应的组合式API
生命周期
选项式 API | Hook inside setup | beforeCreate | Not needed* | created | Not needed* | beforeMount | onBeforeMount | mounted | onMounted | beforeUpdate | onBeforeUpdate | updated | onUpdated | beforeUnmount | onBeforeUnmount | unmounted | onUnmounted | errorCaptured | onErrorCaptured | renderTracked | onRenderTracked | renderTriggered | onRenderTriggered |
---|
选项式API的生命周期钩子函数与组合式API的触发时机一致,书写方法有区别,下面列了几个常用的生命周期钩子函数的定义方式。
示例:
<template>
<div>name:{{name}}</div>
<div>{{nowName}}</div>
<button @click="updateName">修改姓名</button>
</template>
<script>
<!--引入所需内置函数-->
import {onBeforeMount,onMounted,onBeforeUpdate,onUpdated,ref} from 'vue'
export default {
name: "test",
setup(){
//挂载前
onBeforeMount(()=>{
console.log("onBeforeMount")
})
//挂载后
onMounted(()=>{
console.log("onMounted")
})
//修改前
onBeforeUpdate(()=>{
console.log("onBeforeUpdate")
})
//修改后
onUpdated(()=>{
console.log("onUpdated")
})
let name = ref('')
console.log(name);
let updateName = ()=>{
name.value = 'xiaoming';
console.log("修改名字",name)
}
return {name,updateName}
}
}
</script>
<style scoped>
</style>
5. 依赖注入( Provide
/ Inject
)
父组件将参数注入provide
,子、孙组件使用inject
,这里使用官方示例
父组件:
<template>
<MyMarker />
</template>
<script>
import { provide } from 'vue'
import MyMarker from './MyMarker.vue
export default {
components: {
MyMarker
},
setup() {
//向子组件及孙子组件注入两个参数,分别是地址及坐标,一个变量,一个对象
provide('location', 'North Pole')
provide('geolocation', {
longitude: 90,
latitude: 135
})
}
}
</script>
子组件:
<script>
import { inject } from 'vue'
export default {
setup() {
//引入父组件注入的变量
const userLocation = inject('location', 'The Universe')
const userGeolocation = inject('geolocation')
return {
userLocation,
userGeolocation
}
}
}
</script>
6. 依赖注入响应式
上面注入的参数如果发生变动,子组件内引入的参数并不会变化,接下来将参数动态化。
子组件
<template>
<MyMarker />
</template>
<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue
export default {
components: {
MyMarker
},
setup() {
<!--ref上面已经介绍过-->
const location = ref('North Pole')
<!--reactive用法与ref相同,不过ref针对的是基本数据类型,而reactive针对的是引用数据类型-->
const geolocation = reactive({
longitude: 90,
latitude: 135
})
provide('location', location)
provide('geolocation', geolocation)
}
}
</script>
如果要确保注入的参数不被子组件修改,可以在注入时使用readonly
避免子组件修改参数
父组件
<template>
<MyMarker />
</template>
<script>
import { provide, reactive, readonly, ref } from 'vue'
import MyMarker from './MyMarker.vue
export default {
components: {
MyMarker
},
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
<!--readonly使子组件无法修改父组件注入的参数-->
provide('location', readonly(location))
provide('geolocation', readonly(geolocation))
}
}
</script>
结语:
至此组合式API基本介绍完毕,在开发过程中还是需要自己选择是使用选项式API还是使用组合式API来开发,需要结合自己的使用场景做出选择。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!