1、options API:在对应的属性中编写对应的功能模块;比如data定义数据、methods中定义方法、computed中定义计算属性、watch中监听属性改变
缺点:实现一个功能时,功能对应的代码逻辑会被拆分到各个属性中,当组件复杂的时候 ,逻辑关注点的列表就会增长,同一个功能的逻辑就会被拆分的很分散,这种碎片化的代码使得理解和维护这个都复杂的组件会很困难,并且隐藏了潜在的逻辑问题,当处理单个逻辑关注点时,需要不断地跳到相应的代码块中
2、composition API:将同一个逻辑关注点相关的代码收集在一起
reactive是一个函数,接收一个普通的对象传入,把对象数据转化为响应式对象并返回
<template>
<div>{{ state.name }}</div>
<div>{{ state.age }}</div>
<button @click="state.name = 'pink'">改值</button>
</template>
<script>
import { reactive } from 'vue'
export default {
setup () {
const state = reactive({
name: 'wfz',
age: 18
})
return {
state
}
}
}
</script>
ref是一个函数,接受一个简单类型或者复杂类型的传入并返回一个响应式且可变的 ref 对象,在setup函数中使用ref结果,需要通过.value访问,模板中使用不需要加.value
<template>
<div>{{ money }}</div>
<button @click="changeMoney">改值</button>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
let money = ref(100)
return {
money
}
}
}
</script>
computed根据现有响应式数据经过一定的计算得到全新的数据
<template>
{{ list }}
{{ filterList }}
<button @click="changeList">change list</button>
</template>
<script>
import { computed, ref } from 'vue'
export default {
setup() {
const list = ref([1, 2, 3, 4, 5, 6])
// 输入大于2的数字
const filterList = computed(() => {
return list.value.filter(item => item > 2)
})
// 修改list的函数
function changeList() {
list.value.push(6, 7, 8)
}
return {
list,
filterList,
changeList
}
}
}
</script>
watch:基于响应式数据的变化执行回调逻辑,和vue2中的watch的功能一致
<template>
{{ state.name }}
{{ state.info.age }}
<button @click="state.name = 'pink'">change name</button>
<button @click="state.info.age++">change age</button>
</template>
<script>
import { reactive, toRefs, watch } from 'vue'
export default {
setup() {
const state = reactive({
name: 'cp',
info: {
age: 18
}
})
watch(() => {
// 详细的告知你要监听谁
return state.info.age
}, () => {
// 数据变化之后的回调函数
console.log('age发生了变化')
})
return {
state
}
}
}
</script>
在vue3的组合式API中,和vue2通信方式一致:父传子是通过prop进行传入,子传父通过调用自定义事件完成
App.vue
<template>
<son :msg="msg" @get-msg="getMsg"></son>
</template>
<script>
import { ref } from 'vue'
import Son from './components/son'
export default {
components: {
Son
},
setup() {
const msg = ref('this is msg')
function getMsg(msg) {
console.log(msg)
}
return {
msg,
getMsg
}
}
}
</script>
Children.vue
<template>
<div>
{{msg}}
<button @click="setMsgFromSon">set</button>
</div>
</template>
<script>
export default {
props: {
msg: {
type: String
}
},
emits: ['get-msg'], // 声明当前组件触发的自定义事件
setup(props,{emit}) {
function setMsgFromSon(){
emit('get-msg','这是一条来自子组件的新的msg信息')
}
return {
setMsgToSon
}
}
}
</script>
App.vue
<template>
<father></father>
</template>
<script>
import Father from '@/components/Father'
import { provide } from 'vue'
export default {
components: {
Father
},
setup() {
let name = 'xww'
// 使用provide配置项注入数据 key - value
provide('name', name)
}
}
</script>
grandSon.vue
<template>
我是子组件
{{ name }}
</template>
<script>
import { inject } from 'vue'
export default {
setup() {
const name = inject('name')
return {
name
}
}
}
</script>
provide默认情况下传递的数据不是响应式的,也就是如果对provide提供的数据进行修改,并不能响应式的影响到底层组件使用数据的地方,如果想要传递响应数据也非常简单,只需要将传递的数据使用ref或者reactive生成即可
<template>
<father></father>
<button @click="changeName">change name</button>
</template>
<script>
import Father from '@/components/Father'
import { provide, ref } from 'vue'
export default {
components: {
Father
},
setup() {
// 使用ref转换成响应式再传递
let name = ref('xww')
function changeName(){
name.value = 'pink'
}
provide('name', name)
return {
changeName
}
}
}
</script>